HomeXML Page 2 - XML Parsing With DOM and Xerces (part 2)
The Writing On The Wall - XML
In this concluding article of a two-part series, use your knowledge of DOM processing with Xerces to construct simple Web applications based on Xerces, XML and JSP. Examples include transforming an XML file to HTML via Xerces and dynamically generating an XML document tree from a MySQL database.
Let's begin by quickly revisiting the sample XML file used earlier:
<?xml version="1.0"?>
<inventory>
<!-- time to lock and load -->
<item>
<id>758</id>
<name>Rusty, jagged nails for nailgun</name>
<supplier>NailBarn, Inc.</supplier>
<cost currency="USD">2.99</cost>
A
<quantity alert="500">10000</quantity>
</item>
<item>
<id>6273</id>
<name>Power pack for death ray</name>
<supplier>QuakePower.domain.com</supplier>
<cost currency="USD">9.99</cost>
<quantity alert="20">10</quantity>
</item>
</inventory>
This next example ports the dynamically-printed tree structure you saw in a previous
example to work with a Web server.
import org.apache.xerces.parsers.DOMParser;
import org.xml.sax.SAXException;
import
org.w3c.dom.*;
import java.io.*;
public class MyFourthDomApp {
private Writer
out;
String Content = "";
// a counter for keeping track of the "tabs"
private int TabCounter = 0;
// constructor
public MyFourthDomApp (String
xmlFile, Writer out) {
this.out = out;
// create a Xerces DOM
parser
DOMParser parser = new DOMParser();
// parse the document
and
// access the root node with its children.
try {
parser.parse(xmlFile);
Document document = parser.getDocument();
NodeDetails(document);
} catch (SAXException e) {
// something went wrong!
} catch (IOException e) {
// something went wrong!
}
}
// recursively
traverse the document tree
private
void NodeDetails (Node node) {
try
{
int type = node.getNodeType();
if (type == Node.ELEMENT_NODE)
{
// if element
FormatTree(TabCounter);
out.write
("Element: " + node.getNodeName()
+ "<br>");
if(node.hasAttributes())
{
NamedNodeMap
AttributesList = node.getAttributes();
for(int j = 0; j < AttributesList.getLength();
j++) {
FormatTree(TabCounter);
out.write("Attribute:
" +
AttributesList.item(j).getNodeName()
+ " = " +
AttributesList.item(j).getNodeValue()
+ "<br>");
}
}
} else if (type == Node.TEXT_NODE)
{
//
if character data
Content = node.getNodeValue();
if (!Content.trim().equals("")){
FormatTree(TabCounter);
out.write ("Character Data: " + Content + "<br>");
}
} else if (type == Node.COMMENT_NODE) {
// if comment
Content = node.getNodeValue();
if (!Content.trim().equals("")){
FormatTree(TabCounter);
out.write("Comment:
" + Content + "<br>");
}
// add code for other node
types here if you like
}
NodeList children = node.getChildNodes();
if (children != null) {
for (int i=0; i< children.getLength();
i++) {
TabCounter++;
NodeDetails(children.item(i));
TabCounter--;
}
}
} catch (IOException
e) {
// something went wrong!
}
}
// this formats the output
as a tree
private void FormatTree (int TabCounter) {
try {
for(int
j = 1; j < TabCounter; j++) {
out.write(" ");
}
} catch (IOException e) {
// something went wrong!
}
}
}
The most important difference between this example and the previous one is the
introduction of a new Writer object, which makes it possible to redirect output to the browser instead of the standard output device.
private Writer out;
The constructor also needs to be modified to accept two parameters: the name
of the XML file, and a reference to the Writer object.
Note that, since I'm using a Writer object, I also need to add some code to trap
and resolve IOExceptions, if they occur. I've left that aside for a more detailed discussion a little later - however, you should be aware of this requirement and design your code appropriately.
You'll notice that I haven't made any major changes to the NodeDetails() function, other than the inclusion of HTML tags in the output - this is what will ultimately get sent to the browser. The only item left is to handle the connection between the Java class above and the Web server - which is where JSP comes in.