1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
\chapter{Retrieving Data From An \XML{} Stream}
If you're retrieving data from a stream, but you don't want to wait to process the data until it's completely read, you can use streaming.
\section{The \XML{} Builder}
The \XML{} data tree is created using an \XML{} builder. By default, the builder creates a tree of \classname{IXMLElement}.
While the parser parses the data, it notifies the builder of any elements it encounters. Using this information, the builder generate the object tree. When the parser is done processing the data, it retrieves the object tree from the builder using \methodname{getResult}.
The following example shows a simple builder that prints the notifications on the standard output.
\begin{example}
\xkeyword{import} java.io.*;
\xkeyword{import} net.n3.nanoxml.*;
~
\xkeyword{public class} MyBuilder
~~~~\xkeyword{implements} IXMLBuilder
~~\{
~~\xkeyword{public void} startBuilding(String systemID,\xcallout{1}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~\xkeyword{int} lineNr)
~~\{
~~~~System.out.println("Document started");
~~\}
~
~~\xkeyword{public void} newProcessingInstruction(String target,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Reader reader)
~~~~\xkeyword{throws} IOException
~~\{
~~~~System.out.println("New PI with target " + target);
~~\}
~
~~\xkeyword{public void} startElement(String name,\xcallout{3}
~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,
~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID,
~~~~~~~~~~~~~~~~~~~~~~~~~~~String systemID,
~~~~~~~~~~~~~~~~~~~~~~~~~~~\xkeyword{int} lineNr)
~~\{
~~~~System.out.println("Element started: " + name);
~~\}
~
~~\xkeyword{public void} endElement(String name,\xcallout{4}
~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,
~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID)
~~\{
~~~~System.out.println("Element ended: " + name);
~~\}
~
~~\xkeyword{public void} addAttribute(String key,\xcallout{5}
~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,
~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID,
~~~~~~~~~~~~~~~~~~~~~~~~~~~String value,
~~~~~~~~~~~~~~~~~~~~~~~~~~~String type)
~~\{
~~~~System.out.println(" " + key + ": " + type + " = " + value);
~~\}
~
~~\xkeyword{public void} elementAttributesProcessed(String name,\xcallout{6}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsPrefix,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~String nsSystemID)
~~\{
~~~~// nothing to do
~~\}
~
~~\xkeyword{public void} addPCData(Reader reader,\xcallout{7}
~~~~~~~~~~~~~~~~~~~~~~~~String systemID,
~~~~~~~~~~~~~~~~~~~~~~~~\xkeyword{int} lineNr)
~~~~\xkeyword{throws} IOException
~~\{
~~~~System.out.println("\#PCDATA");
~~\}
~
~~\xkeyword{public} Object getResult()\xcallout{8}
~~\{
~~~~\xkeyword{return null};
~~\}
\}
\end{example}
\begin{callout}
\coitem
The \XML{} parser started parsing the document. The \variable{lineNr}
parameter contains the line number where the document starts.
\coitem
The \XML{} parser encountered a processing instruction (PI) which is not
handled by the parser itself.
The target contains the target of the PI.
The contents of the PI can be read from reader.
\coitem
A new element has been started at line \variable{lineNr}.
The name of the element is stored in \variable{name}.
\coitem
The current element has ended.
For convenience, the name of that element is put in the parameter
\variable{name}.
\coitem
An attribute is added to the current element.
\coitem
This method is called when all the attributes of the current element
have been processed.
\coitem
A \ltext{\#PCDATA} section has been encountered.
The contents of the section can be read from reader.
\coitem
This method is called when the parsing has finished.
If the builder has a result, it has to return it to the parser in this
method.
\end{callout}
\section{Registering an XML Builder}
You can register the builder to the parser using the method \methodname{setBuilder}.
The following example shows how to create a parser which uses the builder we created in the previous section:
\begin{example}
\xkeyword{import} net.n3.nanoxml.*;
\xkeyword{import} java.io.*;
~
\xkeyword{public class} DumpXML
\{
~~\xkeyword{public static void} main(String args[])
~~~~\xkeyword{throws} Exception
~~\{
~~~~IXMLParser parser = XMLParserFactory.createDefaultXMLParser();
~~~~IXMLReader reader = StdXMLReader.fileReader("test.xml");
~~~~parser.setReader(reader);
~~~~parser.setBuilder(new MyBuilder());
~~~~parser.parse();
~~\}
\}
\end{example}
|