ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

XML Basics for Java Developers, Part 3
Pages: 1, 2

With that out of the way we can present our TestDOM class:

import javax.xml.parsers.*;
import org.w3c.dom.*;

public class TestDOM
   public static void main( String [] args ) throws Exception
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder parser = factory.newDocumentBuilder();
      Document document = parser.parse( "zooinventory.xml" );
      Element inventory = document.getDocumentElement();
      NodeList animals = inventory.getElementsByTagName("Animal");

      System.out.println("Animals = ");
      for( int i=0; i<animals.getLength(); i++ ) {
         String name = DOMUtil.getSimpleElementText( 
            (Element)animals.item(i),"Name" );
         String species = DOMUtil.getSimpleElementText( 
            (Element)animals.item(i), "Species" );
         System.out.println( "  "+ name +" ("+species+")" );

      Element foodRecipe = DOMUtil.getFirstElement( 
         (Element)animals.item(1), "FoodRecipe" );
      String name = DOMUtil.getSimpleElementText( foodRecipe, "Name" );
      System.out.println("Recipe = " + name );
      NodeList ingredients = foodRecipe.getElementsByTagName("Ingredient");
      for(int i=0; i<ingredients.getLength(); i++) 
         System.out.println( "  " + DOMUtil.getSimpleElementText( 
            (Element)ingredients.item(i) ) );

TestDOM creates an instance of a DocumentBuilder and uses it to parse our zooinventory.xml file. We use the Document getDocumentElement() method to get the root element of the document, from which we will begin our traversal. From there, we ask for all the Animal child nodes. The getElementbyTagName() method returns a NodeList object, which we then use to iterate through our creatures. For each animal, we use our DOMUtil.getSimpleElementText() method to retrieve the basic name and species information. Next, we use the DOMUtil.getFirstElement() method to retrieve the element called FoodRecipe from the second animal. We use it to fetch a NodeList for the tags matching Ingredient and print them as before. The output should contain the same information as our SAX-based example.

Generating XML with DOM

Thus far, we've used the SAX and DOM APIs to parse XML. But what about generating XML? Sure, it's easy to generate trivial XML documents simply by emitting the appropriate strings. But if we plan to create a complex document on the fly, we might want some help with all those quotes and closing tags. What we can do is to build a DOM representation of our object in memory and then transform it to text. This is also useful if we want to read a document and then make some alterations to it. To do this, we'll use of the java.xml.transform package. This package does a lot more than just printing XML. As its name implies, it's part of a general transformation facility. It includes the XSL/XSLT languages for generating one XML document from another. (We'll talk about XSL later in this chapter.)

We won't discuss the details of constructing a DOM in memory here, but it follows fairly naturally from what you've learned about traversing the tree in our previous example. The following example, PrintDOM, simply parses our zooinventory.xml file to a DOM and then prints it back to the screen:

import javax.xml.parsers.*;
import org.w3c.dom.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class PrintDOM {
   public static void main( String [] args ) throws Exception
      DocumentBuilder parser = 
         DocumentBuilderFactory.newInstance().newDocumentBuilder(  );
      Document document=parser.parse( "zooinventory.xml" );
      Transformer transformer = 
         TransformerFactory.newInstance().newTransformer(  );
      Source source = new DOMSource( document );
      Result output = new StreamResult( System.out );
      transformer.transform( source, output );

Note that the imports are almost as long as the entire program! Here we are using an instance of a Transformer object in its simplest capacity to copy from a source to an output. We'll return to the Transformer later when we discuss XSL.


As we promised earlier, we'll now describe an easier DOM API: JDOM, created by Jason Hunter and Brett McLaughlin, two fellow O'Reilly authors (Java Servlet Programming and Java and XML, respectively). It is a more natural Java DOM that uses real Java collection types such as List for its hierarchy and provides more streamlined methods for building documents. You can get the latest JDOM from http://www.jdom.org. Here's the JDOM version of our standard "test" program:

import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;
import java.util.*;

public class TestJDOM {
   public static void main( String[] args ) throws Exception {
      Document doc = new SAXBuilder(  ).build("zooinventory.xml");
      List animals = doc.getRootElement(  ).getChildren("Animal");
      System.out.println("Animals = ");
      for( int i=0; i<animals.size(  ); i++ ) {
         String name = ((Element)animals.get(i)).getChildText("Name");
         String species = ((Element)animals.get(i)).getChildText("Species");
         System.out.println( "  "+ name +" ("+species+")" );
      Element foodRecipe = ((Element)animals.get(1)).getChild("FoodRecipe");
      String name = foodRecipe.getChildText("Name");
      System.out.println("Recipe = " + name );
      List ingredients = foodRecipe.getChildren("Ingredient");
      for(int i=0; i<ingredients.size(  ); i++)
         System.out.println( "  "+((Element)ingredients.get(i)).getText(  ) );

JDOM has convenience methods that take the place of our homemade DOM helper methods. Namely, the JDOM element has getChild() and getChildren() methods as well as a getChildText() method for retrieving node text.

In the next installment, learn about validating documents.

Return to ONJava.com.