// DOMExample.java
// Example of using DOM for XML parsing
// Bill MacCartney
// 11 October 2004
import java.util.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
/**
This is a simple class that processes an XML file using a DOM
parser. Intended to run on a data file like this:
this is before the first dot
and it continues on multiple lines
flip is on
flip is off
*/
class DOMExample {
/** XML tag strings */
public final String DOTS = "dots";
public final String DOT = "dot";
public final String X = "x";
public final String Y = "y";
public final String FLIP = "flip";
/** Data model */
private class Dot {
int x;
int y;
public Dot(int x, int y) { this.x = x; this.y = y; }
public String toString() { return "(" + x + ", " + y + ")"; }
}
public List dotList = new ArrayList();
private DocumentBuilder db;
/** Construct instance and initialize DocumentBuilder. */
public DOMExample() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
/** Read XML from input stream, construct Document (i.e. XML node
* tree) in memory, and process nodes.
*/
private void readXML(InputStream in) {
try {
// Invoke DocumentBuilder to parse input and create Document
Document doc = db.parse(in);
System.out.println("\nHere's the Document tree I just read:");
printDocument(doc);
// Get the root element
Element root = doc.getDocumentElement();
// Get all the DOT children
NodeList dots = root.getElementsByTagName(DOT);
// Iterate through them and add them to data model
for (int i = 0; i < dots.getLength(); i++) {
Element dotElement = (Element) dots.item(i);
int x = Integer.parseInt(dotElement.getAttribute(X));
int y = Integer.parseInt(dotElement.getAttribute(Y));
dotList.add(new Dot(x, y));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/** Create the XML element for a single dot. */
private Element createDotElement(Document doc, int x, int y) {
Element dot = doc.createElement(DOT);
dot.setAttribute(X, Integer.toString(x));
dot.setAttribute(Y, Integer.toString(y));
return(dot);
}
/** Construct Document (i.e. XML node tree) from data model. */
public Document createDocument() {
// Make new empty Document
Document doc = db.newDocument();
// Create the root node and add to the document
Element root = doc.createElement(DOTS);
doc.appendChild(root);
// Go through all the dots and append them to the DOTS node
Iterator it = dotList.iterator();
while (it.hasNext()) {
Dot dot = (Dot) it.next();
Element dotElement = createDotElement(doc, dot.x, dot.y);
root.appendChild(dotElement);
}
return doc;
}
/** Construct Document (i.e. XML node tree) from data model and
* ask it to write itself out.
*
* Note 1: Since JAXP 1.1, there is no simple, documented way to
* write out a Document object. This code uses an undocumented
* trick. There is a supported way via the XSLT library, but it
* is far more clumsy than this two-line trick.
*
* Note 2: Another strategy would be just to println() the XML
* text straight from our data model.
*/
public void writeXML(OutputStream o) {
try {
Writer out = new OutputStreamWriter(o);
Document doc = createDocument();
// Here's the trick:
// 1. Downcast Document to a Crimson XmlDocument
org.apache.crimson.tree.XmlDocument x =
(org.apache.crimson.tree.XmlDocument) doc;
// 2. XmlDocument knows how to write itself out -- woo hoo!
x.write(out, "UTF-8");
out.close();
}
catch (Exception e) {
System.err.println("Save XML err:" + e);
}
}
/** Test by running "java DOMExample " */
public static void main (String[] args) {
if (args.length != 1) {
System.err.println ("Usage: cmd filename");
System.exit(1);
}
try {
DOMExample example = new DOMExample();
InputStream in = new BufferedInputStream(new FileInputStream(new File(args[0])));
example.readXML(in);
System.out.println("\nFinished parsing input. Got the following dots:");
System.out.println(example.dotList);
System.out.println("\nRecreated XML document:");
example.writeXML(System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
// The remaining methods just enable tree printing.
// They are not especially instructive to read.
private String nodeToString(Node node, int indentLevel) {
StringBuffer buf = new StringBuffer("\n");
for (int i = 0; i < indentLevel; i++)
buf.append(" ");
if (node.hasChildNodes()) {
buf.append("(" + nodeLabel(node));
NodeList kids = node.getChildNodes();
for (int i = 0; i < kids.getLength(); i++) {
buf.append(" " + nodeToString(kids.item(i), indentLevel + 1));
}
buf.append(")");
} else {
buf.append(nodeLabel(node));
}
return buf.toString();
}
// An array of names for DOM node-types
// (Array indexes = nodeType() values.)
static final String[] typeName = {
"none",
"Element",
"Attr",
"Text",
"CDATA",
"EntityRef",
"Entity",
"ProcInstr",
"Comment",
"Document",
"DocType",
"DocFragment",
"Notation",
};
private String nodeLabel(Node node) {
short typeCode = node.getNodeType();
String type = typeName[typeCode];
String name = node.getNodeName();
String value = node.getNodeValue();
if (value != null) value = value.trim();
return type +
" \"" + name +
(((typeCode != Node.TEXT_NODE &&
typeCode != Node.COMMENT_NODE) ||
value.equals("") || value.equals("null")) ?
"" :
"\", value=\"" + value) +
"\"";
}
public void printDocument(Document doc) {
System.out.println(nodeToString(doc, 0));
}
}