📄 treesubst.java
字号:
package MyNa.xml;
import MyNa.utils.*;
import java.io.*;
import java.util.*;
import java.sql.SQLException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Attr;
/* sax, parser, XmlDocument are used only in main */
import org.xml.sax.SAXParseException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.sun.xml.parser.Resolver;
import com.sun.xml.tree.XmlDocument;
public class TreeSubst {
// handles an xml template with no DTD; output to a Writer.
// the idea is that the user takes a sample (minimal) of
// xml, which may well have a DTD; replaces constants by
// variables whose values will be provided by an env;
// wraps nodes within "substrow" nodes which are to be
// filled in by the next row, and substrowlist nodes to
// be filled in by however many rows there are. If
// substrow is called with no input, it generates no
// output, but sets a flag so substerr does generate
// output. Nodes which TreeSubst doesn't understand
// are simply echoed (recursively); there is at present
// no way to "quote", but it would be okay to add a
// substquote node which means "echo everything below
// this node without substitutions.
// We start with an Env, which may or may not contain a
// DBHandler to connect us with a database. If there is no
// DBHandler, there can't be dbOperation attributes. The Env
// may be generated by a RowSeq in which case
// substrow, substerr and substrowlist are legitimate;
// <substrowlist enumerateThrough="StrSeq" name="FieldName">
// may also be used to generate items from StrSeqs in an Env.
// in general, use this by identifying the top <template>
// node nd, the output out
Logger lg;
Writer out;
Env defs;
RowSeq rows;
int[]index;
int curIndex;
boolean substFailure;
public TreeSubst(){
lg=new Logger();
out=new PrintWriter(System.out);
defs=new Env(); rows=null;
index=new int[20];curIndex=-1;
substFailure=false;
lg.logIt("TreeSubst default initialization");
}
public void setOut(Writer o){out=o;}
public void setDefs(Env e){defs=e;}
public void setRows(RowSeq re){
rows=re;
defs=re.getRow();
}
public TreeSubst(Env e,Writer o){
lg=new Logger();
out=o; defs=e; rows=null;
index=new int[20];curIndex=-1;
substFailure=false;
lg.logIt("TreeSubst Env+Writer initialization");
}
public TreeSubst(RowSeq e,Writer o){
lg=new Logger();
rows=e;out=o; defs=e.getRow();
index=new int[20];curIndex=-1;
substFailure=false;
lg.logIt("TreeSubst RowSeq+Writer initialization");
}
// the core strategy is to echo an xml document; then echo with changes.
/* BEGIN basic echo functionality: */
public void echoChildren(Node theFirst, Writer out)
throws IOException {
while(null!=theFirst){
echoNode(theFirst,out);
theFirst=theFirst.getNextSibling();
}
}
public void echoDTD(String theName,NamedNodeMap theEntities,
NamedNodeMap theNotes,Writer out)
throws IOException {
out.write("<!DOCTYPE "); out.write(theName);
out.write(" [");
echoAttributes(theEntities,out);
out.write("]\n [");
echoAttributes(theNotes,out);
out.write("]>\n");
}
public void echoAttributes(NamedNodeMap attrs,Writer out)
throws IOException {
int N=attrs.getLength();
for(int i=0; i<N; i++)echoNode(attrs.item(i),out);
}
public void echoNode(Node theNode)
throws IOException {echoNode(theNode, out);}
public void echoNode(Node theNode,Writer out)
throws IOException {
short code=theNode.getNodeType();
switch(code){
case Node.ATTRIBUTE_NODE:
Attr at=(Attr)theNode;
out.write(" ");
out.write(at.getName());
out.write("='");
out.write(at.getValue());
out.write("'");
return;
case Node.CDATA_SECTION_NODE:
out.write("<CDATA[[");
out.write(theNode.getNodeValue());
out.write("]]>");
return;
case Node.COMMENT_NODE:
out.write("<!-- ");
out.write(theNode.getNodeValue());
out.write("-->\n");
return;
case Node.DOCUMENT_FRAGMENT_NODE: // we can't reconstitute this; dump it
case Node.DOCUMENT_NODE:
echoChildren(theNode.getFirstChild(),out);
return;
case Node.DOCUMENT_TYPE_NODE:
DocumentType dT=(DocumentType)theNode;
echoDTD(dT.getName(),dT.getEntities(),dT.getNotations(),out);
return;
case Node.ELEMENT_NODE:
out.write("<"); out.write(theNode.getNodeName());
echoAttributes(theNode.getAttributes(),out);
Node kid=theNode.getFirstChild();
if(kid==null) out.write("/>\n");
else {
out.write(">");
echoChildren(kid,out);
out.write("</");
out.write(theNode.getNodeName());
out.write(">\n");
}
return;
case Node.ENTITY_NODE:
out.write("<ENTITY: "); out.write(theNode.getNodeName());
out.write(">"); out.write(theNode.getNodeValue());
out.write("</"); out.write(theNode.getNodeName());
out.write(">\n");
return;
case Node.ENTITY_REFERENCE_NODE:
out.write("<ENTITY_REF: "); out.write(theNode.getNodeName());
out.write("/>\n");
return;
case Node.NOTATION_NODE :
out.write("<NOTATION: "); out.write(theNode.getNodeName());
out.write("/>\n");
return;
case Node.PROCESSING_INSTRUCTION_NODE:
out.write("<? "); out.write(theNode.getNodeName());
out.write(" "); out.write(theNode.getNodeValue());
out.write(" ?>\n");
return;
case Node.TEXT_NODE:
out.write(theNode.getNodeValue());
return;
default:return;
}
}
/* END basic echo functionality */
// we're going to be echoing again, but via lookUp:
static String substMarker="!=";
public String getKey(String S)throws TemplateException{
// S may be null, ibblebibble, "!=dbUser", "!=FieldName[3]", &c.
if(S==null)return S;
if(!S.startsWith(substMarker))return S;
S=S.substring(2,S.length());
int n=0;
if(S.endsWith("]")){
int i=S.lastIndexOf("[");
n=Integer.parseInt(S.substring(i+1,S.length()-1));
S=S.substring(0,i);
}
return getKeyIndex(S,n);
}
public String getKeyIndex(String S, int n)throws TemplateException{
if(n==0){
String R=defs.getStr(S);
if(null!=R)return R;
throw new TemplateException("no definition for key "+S);
}
if(n<0)n=index[curIndex];
String[] A=defs.getStrSeq(S);
if(A==null || A.length==0 || A.length<n)
throw new TemplateException("no definition for key "+S+"["+n+"]");
return A[n-1];
}
// we now extend the basic echo, by allowing special tags for elements,
// with a "chooseRule" function which interprets tags. echoChildren
// becomes substChildren, echoAttributes becomes substAttributes.
public void substChildren(Node theFirst, Writer out)
throws IOException,TemplateException {
while(null!=theFirst){
substNode(theFirst,out);
theFirst=theFirst.getNextSibling();
}
}
/* no substDTD function; we'll just use echoDTD */
public void substAttributes(NamedNodeMap attrs,Writer out)
throws IOException,TemplateException {
int N=attrs.getLength();
for(int i=0; i<N; i++)substNode(attrs.item(i),out);
}
public void substNode(Node theNode)
throws IOException,TemplateException {
substNode(theNode, out);}
public void substNode(Node theNode,Writer out)
throws IOException,TemplateException {
short code=theNode.getNodeType();
switch(code){
case Node.ATTRIBUTE_NODE:
Attr at=(Attr)theNode;
out.write(" ");
out.write(at.getName());
out.write("='");
out.write(getKey(at.getValue()));
out.write("'");
return;
case Node.CDATA_SECTION_NODE:
out.write("<CDATA[[");
out.write(theNode.getNodeValue());
out.write("]]>");
return;
case Node.COMMENT_NODE:
out.write("<!-- ");
out.write(theNode.getNodeValue());
out.write("-->\n");
return;
case Node.DOCUMENT_FRAGMENT_NODE: // can't reconstitute, just dump it
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -