To create a new document using the StAX API, we must first create an
XMLStreamWriter
that provides
methods to produce XML opening and closing tags, attributes and character
content. As this approach only keeps a small part of the document in memory, there is no
validation or even well-formedness guarantee on the program. The methods must be called
in the appropriate order in order to reflect the XML tree structure.
The most frequently XMLStreamWriter
(xmlsw
) methods are:
xmlsw.writeStartDocument();
xmlsw.writeStartElement(String s)
s
xmlsw.writeAttribute(String name, String value)
name
with the corresponding
value
to the last element produced by a call to writeStartElement
.
It is possible to add attributes as long as no call to writeElementStart
,
writeCharacters
or writeEndElement
has been done.
xmlsw.writeEndElement
xmlsw.writeCharacters(String s)
s
as content of the
last started element.
Like we did in Section 9.1, to simplify parsing, we create a customized
StreamTokenizer
(line 18‑) which returns a single token for all characters between
separators used in the compact form (i.e. opening and closing brackets, at-sign and
newline). The separators are also returned as a single token. The implementation of this
tokenizer is given in Example 9.1.
The main class for the StAX transformation (Example 9.5) is very simple: it creates an XMLStreamWriter
instance that will write
the output file (line 17‑) and an instance of
a
CompactTokenizer
to read the input
file. After skipping everything before the first opening bracket, we initialize the
output with a start document (line 26‑) and
call
expand
method (line 29‑) to deal with the
content of an element. As the output of an
XMLStreamWriter
is not indented,
we decided here to define the ignorableSpacing
method (line 73‑)
that outputs whitespace nodes. This is usually not needed but it is convenient to be able to see the
results. In this particular case, creating a properly indented is a bit tricky because we
must output a new line only when the last thing written was the end of an element or an attribute.
The expand
method (line 43‑) first
outputs the attributes on the current element (line 46‑
) and then writes either a new element and
calls itself recursively to process its contents (line 57‑
) or it outputs the character content of the
element (line 63‑
).
Example 9.5. [StAXExpand.java
]:
XML document creation using the StAX approach
1 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; 5 import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import java.util.Arrays; 10 public class StAXExpand { static XMLStreamWriter xmlsw = null; public static void main(String[] argv) { try { 15 xmlsw = XMLOutputFactory.newInstance() .createXMLStreamWriter(System.out); CompactTokenizer tok = new CompactTokenizer(new FileReader(argv[0]));
20 String rootName = "dummyRoot"; // ignore everything preceding the word before the first "[" while(!tok.nextToken().equals("[")){ rootName=tok.getToken(); } 25 // start creating new document xmlsw.writeStartDocument();
ignorableSpacing(0); xmlsw.writeStartElement(rootName); expand(tok,3);
30 ignorableSpacing(0); xmlsw.writeEndDocument();
xmlsw.flush(); xmlsw.close(); 35 } catch (XMLStreamException e){
System.out.println(e.getMessage()); } catch (IOException ex) { System.out.println("IOException"+ex); ex.printStackTrace(); 40 } } public static void expand(CompactTokenizer tok, int indent)
throws IOException,XMLStreamException { 45 tok.skip("["); while(tok.getToken().equals("@")) {// add attributes
String attName = tok.nextToken(); tok.nextToken(); xmlsw.writeAttribute(attName,tok.skip("[")); 50 tok.nextToken(); tok.skip("]"); } boolean lastWasElement=true; // for controlling the output of newlines while(!tok.getToken().equals("]")){ // process content
55 String s = tok.getToken().trim(); tok.nextToken(); if(tok.getToken().equals("[")){
if(lastWasElement)ignorableSpacing(indent); xmlsw.writeStartElement(s); 60 expand(tok,indent+3); lastWasElement=true; } else { xmlsw.writeCharacters(s);
lastWasElement=false; 65 } } tok.skip("]"); if(lastWasElement)ignorableSpacing(indent-3); xmlsw.writeEndElement();
70 } private static char[] blanks = "\n".toCharArray(); private static void ignorableSpacing(int nb)
throws XMLStreamException { 75 if(nb>blanks.length){// extend the length of space array blanks = new char[nb+1]; blanks[0]='\n'; Arrays.fill(blanks,1,blanks.length,' '); } 80 xmlsw.writeCharacters(blanks, 0, nb+1); } }
|
Creates the |
|
Creates a specialized tokenizer for the compact form. |
|
Initializes the XML document. |
|
Calls the expanding process on the root element. |
|
Terminates the XML writing proces by ending the document and closing the file. |
|
Deals with exceptions that can be raised during writing the XML code and the file. |
|
Recursive method to output an element properly indented. |
|
Adds attributes name and value on the last element outputted. |
|
Deals with the content of the element. |
|
Recursively calls the expansion on the content of the element. |
|
Outputs the character content. |
|
Outputs the end of the current element. |
|
Creates a character node containing a new line and an appropriate number of spaces. |