advanced.tex

来自「Nano的XML解析器」· TEX 代码 · 共 483 行 · 第 1/2 页

TEX
483
字号
~~~~\xkeyword{this}.children = \xkeyword{new} Vector();~~\}~~~\xkeyword{public void} setAttribute(String attrName,~~~~~~~~~~~~~~~~~~~~~~~~~~~String value)~~\{~~~~\xkeyword{this}.attrs.put(attrName, value);~~\}~~~\xkeyword{public void} addChild(DocumentElement elt)~~\{~~~~\xkeyword{this}.children.addElement(elt);~~\}\}\end{example}This base class simply makes it easy for our builder to set attributes and to add children to an element.The \classname{Chapter} and \classname{Paragraph} classes extend this base class to give more practical access to their attributes and children:\begin{example}\xkeyword{public class} Chapter~~\xkeyword{extends} DocumentElement\{~~\xkeyword{public} String getTitle()~~\{~~~~\xkeyword{return this}.attrs.getProperty("title");~~\}~~~\xkeyword{public} String getID()~~\{~~~~\xkeyword{return this}.attrs.getProperty("id");~~\}~~~\xkeyword{public} Enumeration getParagraphs()~~\{~~~~\xkeyword{return this}.children.elements();~~\}\}~\xkeyword{public class} Paragraph~~\xkeyword{extends} DocumentElement\{~~\xkeyword{public static final int} LEFT = 0;~~\xkeyword{public static final int} CENTER = 1;~~\xkeyword{public static final int} RIGHT = 2;~~~\xkeyword{private static} Hashtable alignments;~~~\xkeyword{static}~~\{~~~~alignments = \xkeyword{new} Hashtable();~~~~alignments.put("left", \xkeyword{new} Integer(LEFT));~~~~alignments.put("center", \xkeyword{new} Integer(CENTER));~~~~alignments.put("right", \xkeyword{new} Integer(RIGHT));~~\}~~~\xkeyword{public} String getContent()~~\{~~~~\xkeyword{return this}.attrs.getProperty("\#PCDATA");~~\}~~~\xkeyword{public int} getAlignment()~~\{~~~~String str = \xkeyword{this}.attrs.getProperty("align");~~~~Integer align = alignments.get(str);~~~~\xkeyword{return} align.intValue();~~\}\}\end{example}The builder creates the data structure based on the \XML{} events it receives from the parser.Because both \classname{Chapter} and \classname{Paragraph} extend \classname{DocumentElement}, the builder is fairly simple.\begin{example}\xkeyword{import} net.n3.nanoxml.*;\xkeyword{import} java.util.*;\xkeyword{import} java.io.*;~\xkeyword{public class} DocumentBuilder~~\xkeyword{implements} IXMLBuilder\{~~\xkeyword{private static} Hashtable classes;~~\xkeyword{private} Stack elements;~~\xkeyword{private} DocumentElement topElement;~~~\xkeyword{static}~~\{~~~~classes = \xkeyword{new} Hashtable();~~~~classes.put("Chapter", Chapter.\xkeyword{class});~~~~classes.put("Paragraph", Paragraph.\xkeyword{class});~~\}~~~\xkeyword{public void} startBuilding(String systemID,~~~~~~~~~~~~~~~~~~~~~~~~~~~~\xkeyword{int} lineNr)~~\{~~~~\xkeyword{this}.elements = \xkeyword{new} Stack();~~~~\xkeyword{this}.topElement = \xkeyword{null};~~\}~~~\xkeyword{public void} newProcessingInstruction(String target,~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Reader reader)~~\{~~~~// nothing to do~~\}~~~\xkeyword{public void} startElement(String name,~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID,~~~~~~~~~~~~~~~~~~~~~~~~~~~String systemID,~~~~~~~~~~~~~~~~~~~~~~~~~~~\xkeyword{int} lineNr)~~\{~~~~DocumentElement elt = \xkeyword{null};~~~~\xkeyword{try} \{~~~~~~Class cls = (Class) classes.get(name);~~~~~~elt = (DocumentElement) cls.newInstance();~~~~\} \xkeyword{catch} (Exception e) \{~~~~~~// ignore the exception~~~~\}~~~~\xkeyword{this}.elements.push(elt);~~~~\xkeyword{if} (\xkeyword{this}.topElement == \xkeyword{null}) \{~~~~~~\xkeyword{this}.topElement = elt;~~~~\}~~\}~~~\xkeyword{public void} endElement(String name,~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID)~~\{~~~~DocumentElement child = (DocumentElement) \xkeyword{this}.elements.pop();~~~~\xkeyword{if} (! \xkeyword{this}.elements.isEmpty()) \{~~~~~~DocumentElement parent = (DocumentElement) \xkeyword{this}.elements.peek();~~~~~~parent.addChild(child);~~~~\}~~\}~~~\xkeyword{public void} addAttribute(String key,~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID,~~~~~~~~~~~~~~~~~~~~~~~~~~~String value,~~~~~~~~~~~~~~~~~~~~~~~~~~~String type)~~\{~~~~DocumentElement child = (DocumentElement) \xkeyword{this}.elements.peek();~~~~child.setAttribute(key, value);~~\}~~~\xkeyword{public void} elementAttributesProcessed(String name,~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID)~~\{~~~~// nothing to do~~\}~~~\xkeyword{public void} addPCData(Reader reader,~~~~~~~~~~~~~~~~~~~~~~~~String systemID,~~~~~~~~~~~~~~~~~~~~~~~~\xkeyword{int} lineNr)~~~~\xkeyword{throws} IOException~~\{~~~~StringBuffer str = \xkeyword{new} StringBuffer(1024);~~~~\xkeyword{char}[] buf = \xkeyword{new char}[bufSize];~~~~\xkeyword{for} (;;) \{~~~~~~\xkeyword{int} size = reader.read(buf);~~~~~~\xkeyword{if} (size < 0) \{~~~~~~~~\xkeyword{break};~~~~~~\}~~~~~~str.append(buf, 0, size);~~~~\}~~~~\xkeyword{this}.addAttribute("\#PCDATA", \xkeyword{null}, \xkeyword{null}, str.toString(), "CDATA");~~\}~~~\xkeyword{public} Object getResult()~~\{~~~~\xkeyword{return} topElement;~~\}\}\end{example}Note that, for simplicity, error and exception handling is not present in this example.The builder holds a stack of the current elements it builds.Character data is read from a reader.The method \methodname{addPCData} reads this data in blocks of 1K.Finally, this application sets up the \NanoXML{} parser and converts an \XML{} document to \ltext{HTML} which it dumps on the standard output:\begin{example}\xkeyword{import} java.util.*;\xkeyword{import} net.n3.nanoxml.*;~\xkeyword{public class} XML2HTML\{~~\xkeyword{public static void} main(String[] params)~~~~\xkeyword{throws} Exception~~\{~~~~IXMLBuilder builder = \xkeyword{new} DocumentBuilder();~~~~IXMLParser parser = XMLParserFactory.createDefaultXMLParser();~~~~parser.setBuilder(builder);~~~~IXMLReader reader = StdXMLReader.fileReader(param[0]);~~~~parser.setReader(reader);~~~~Chapter chapter = (Chapter) parser.parse();~~~~System.out.println("$<$!DOCTYPE \ldots{} $>$");~~~~System.out.print("$<$HTML$><$HEAD$><$TITLE$>$");~~~~System.out.print(chapter.getTitle());~~~~System.out.println("</TITLE></HEAD><BODY>");~~~~System.out.print("$<$H1$>$");~~~~System.out.print(chapter.getTitle());~~~~System.out.println("$<$/H1$>$");~~~~Enumeration enum = chapter.getParagraphs();~~~~\xkeyword{while} (enum.hasMoreElements()) \{~~~~~~Paragraph para = (Paragraph) enum.nextElement();~~~~~~System.out.print("$<$P$>$");~~~~~~System.out.print(para.getContent());~~~~~~System.out.println("$<$/P$>$");~~~~\}~~~~System.out.println("$<$/BODY$><$/HTML$>$");~~\}\}\end{example}If we run the example on the following \XML{} file:\begin{example}$<$!DOCTYPE Chapter SYSTEM "document.dtd"$>$~$<$Chapter id="ch01" title="The Title"$>$~~~~$<$Paragraph$>$First paragraph...$<$/Paragraph$>$~~~~$<$Paragraph$>$Second paragraph...$<$/Paragraph$>$$<$/Chapter$>$\end{example}The output will be:\begin{example}$<$!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'~~'http://www.w3.org/TR/html4/strict.dtd'>$<$HTML$><$HEAD$><$TITLE$>$The Title$<$/TITLE$><$/HEAD$><$BODY$>$$<$H1$>$The Title$<$/H1$>$$<$P$>$First paragraph...$<$/P$>$$<$P$>$Second paragraph...$<$/P$>$$<$/BODY$>$\end{example}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?