HomeXML Page 7 - XML Parsing With DOM and Xerces (part 2)
Of Method And Madness - 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.
All the previous examples have discussed parsing an already-created XML document using the DOM. But how about flipping tradition on its head and dynamically creating an XML document using the DOM?
Sounds a little strange? Not at all. Consider a situation where data is stored in a database, yet needs to be converted into XML, either because the recipient system (or customer) needs it in that format, or simply to make it easier to process with XSLT. In such a situation, the ability to dynamically generate an XML document tree from a recordset would be very handy indeed.
This next example demonstrates, using a MySQL database table as the data source for an XML document tree. First, take a look at the MySQL table dump:
CREATE TABLE addressbook (
name varchar(255),
address text,
tel varchar(30),
email
varchar(50),
url varchar(100)
);
INSERT INTO addressbook VALUES('John Doe',
'94,
Main Street, Nowhereville
13433, XY', '757 3838', johndoe@black.hole.com',
'http://www.unknown_and_unsung.com');
INSERT
INTO addressbook VALUES('Sherlock Holmes', '220, Baker Street,
London', '220
0220',
'sherlock@sherlock.com', 'http://www.sherlock.com');
So that's the data. Now, what about that Java code for dynamic tree generation?
import org.apache.xerces.parsers.DOMParser;
import org.xml.sax.SAXException;
import
org.apache.xerces.dom.*;
import org.w3c.dom.*;
import java.io.*;
import java.sql.*;
public
class MySeventhDomApp {
private Writer out;
String Content = "";
// a counter for keeping track of the tabs in the document tree
private
int
TabCounter = 0;
// constructor
public MySeventhDomApp (Writer out)
throws
SAXException {
this.out = out;
Document document = new
DocumentImpl();
Element rootNode = document.createElement("addressbook");
try {
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
} catch
(Exception e) {
System.err.println("Unable to load
driver.");
}
try {
// connect to the database and run
a query
Connection myConn =
DriverManager.getConnection("jdbc:mysql://localhost/db177?user=john&password
=doe");
Statement stmt = myConn.createStatement();
String query = "SELECT
* FROM addressbook";
ResultSet myResultSet = stmt.executeQuery(query);
if (myResultSet != null) {
// iterate through resultset
while (myResultSet.next()) {
Element userNode
=
document.createElement("user");
Element userChildNode = document.createElement("name");
Element userChildNode = document.createElement("name");
userChildNode.appendChild(document.createTextNode(myResultSet.getString("nam
e")));
userNode.appendChild(userChildNode);
userChildNode
= document.createElement("address");
userChildNode = document.createElement("address");
userChildNode.appendChild(document.createTextNode(myResultSet.getString("add
ress")));
userNode.appendChild(userChildNode);
userChildNode
= document.createElement("tel");
userChildNode = document.createElement("tel");
userChildNode.appendChild(document.createTextNode(myResultSet.getString("tel
")));
userNode.appendChild(userChildNode);
userChildNode
= document.createElement("email");
userChildNode = document.createElement("email");
userChildNode.appendChild(document.createTextNode(myResultSet.getString("ema
il")));
userNode.appendChild(userChildNode);
userChildNode
= document.createElement("url");
userChildNode = document.createElement("url");
userChildNode.appendChild(document.createTextNode(myResultSet.getString("url
")));
userNode.appendChild(userChildNode);
rootNode.appendChild(
userNode);
}
}
} catch (SQLException e) {
throw new SAXException(e);
} catch (DOMException e) {
throw
new SAXException(e);
}
document.appendChild( rootNode );
NodeDetails(document);
}
// recursively traverse the document tree
private void NodeDetails
(Node node) throws SAXException {
try {
int type = node.getNodeType();
// handle each node type
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 required
}
NodeList children = node.getChildNodes();
if (children
!= null) {
for (int i=0; i< children.getLength();
i++) {
TabCounter++;
NodeDetails(children.item(i));
TabCounter--;
}
}
} catch (IOException
e) {
throw new SAXException(e);
}
}
// function to format
the output as a tree
private void FormatTree (int TabCounter) throws SAXException
{
try {
for(int j = 1; j < TabCounter; j++) {
out.write(" ");
}
} catch (IOException e) {
throw new SAXException(e);
}
}
}
Plug this into a JSP document,
<%@ page language="java" import="java.io.IOException" %>
<html>
<head>
</head>
<body>
<h1><font
face="Verdana">Address book</font></h1>
<%
try {
MySeventhDomApp
mySeventhExample = new MySeventhDomApp(out);
} catch (Exception e) {
out.println("<font face="verdana" size="2">Something bad just
happened: <br><b>"
+ e + "</b></font>");
}
%>
</body>
</html>
and here's what the result looks like:
The first thing to do here is import a couple of extra things - the java.sql.* and the org.apache.xerces.dom.* classes. The first is required to connect to a database, the second provides the methods and interfaces to construct a DOM tree in memory.
The DocumentImpl interface is the starting point in the process of constructing
the DOM tree. This interface exposes the createElement() method, which you'll be seeing a lot of in the next few paragraphs. This createElement() method makes it possible to construct a new element node on the DOM tree.
Document document = new DocumentImpl();
Element rootNode = document.createElement("addressbook");
In the snippet above, it has been used to construct the outermost element of
the tree, the <addressbook> element.
Next, the JDBC driver is used to connect to the MySQL database and retrieve a list of records from it.
Once all the records have been retrieved from the database, the next step is
to iterate through the recordset and construct branches of the XML DOM tree to hold each data fragment.
As the snippet above demonstrates, nodes can be created using the createElement()
and createTextNode() methods, and attached to a parent node via the parent node's appendChild() method. In this manner, a complete DOM tree can be created to represent a well-formed XML document.
This dynamically-constructed DOM tree can now be processed further. You could write it to a file, transform it into something else with XSLT, or just display it to the user (which is what I've done, using the NodeDetails() function from a previous example).