// 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)); } }