Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

XML document processing in Java using XPath and XSLT

Discover how XPath and XSLT can significantly reduce the complexity of your Java code when handling XML documents

  • Print
  • Feedback

Page 3 of 5

We now need to write some Java code that will help us identify the <address> element in the source tree that needs to be replaced with the updated element. The findAddress() method below shows how that can be accomplished. Please note that, to keep the sample short, we've left out the appropriate error handling.

public Node findAddress(String name, Document source) {
   Element root = source.getDocumentElement();
   NodeList nl = root.getChildNodes();
   // iterate over all address nodes and find the one that has the correct addressee
   for (int i=0;i<nl.getLength(); i++) {
      Node n = nl.item(i);
      if ((n.getNodeType() == Node.ELEMENT_NODE) && 
          (((Element)n).getTagName().equals("address"))) {
         // we have an address node, now we need to find the 
         // 'addressee' child
         Node addressee = ((Element)n).getElementsByTagName("addressee").item(0);
         // there is the addressee, now get the text node and compare
         Node child = addressee.getChildNodes().item(0);
         do {
            if ((child.getNodeType()==Node.TEXT_NODE) &&
                (((Text)child).getData().equals(name))) {             
               return n;
            }
            child = child.getNextSibling(); 
                  } while (child != null);
      }
   }
   return null;
}


The code above could most likely be optimized, but it is obvious that iterating over the DOM tree can be tedious and error prone. Now let's look at how the target node can be located by using a simple XPath statement. The statement could look like this:

//address[child::addressee[text() = 'Jim Smith']]


We can now rewrite our previous method. This time, we use the XPath statement to find the desired node:

public Node findAddress(String name, Document source) throws Exception {
   // need to recreate a few helper objects
   XMLParserLiaison xpathSupport = new XMLParserLiaisonDefault();
   XPathProcessor xpathParser = new XPathProcessorImpl(xpathSupport);
   PrefixResolver prefixResolver = new PrefixResolverDefault(source.getDocumentElement());
   // create the XPath and initialize it
   XPath xp = new XPath();
   String xpString = "//address[child::addressee[text() = '"+name+"']]";
   xpathParser.initXPath(xp, xpString, prefixResolver);
   // now execute the XPath select statement
   XObject list = xp.execute(xpathSupport, source.getDocumentElement(), prefixResolver);
   // return the resulting node
   return list.nodeset().item(0);
}


The above code may not look a lot better than the previous try, but most of this method's contents could be encapsulated in a helper class. The only part that changes over and over is the actual XPath expression and the target node.

This lets us create an XPathHelper class, which looks like this:

import org.w3c.dom.*;
import org.xml.sax.*;
import org.apache.xalan.xpath.*;
import org.apache.xalan.xpath.xml.*;
public class XPathHelper {
   XMLParserLiaison xpathSupport = null;
   XPathProcessor xpathParser = null;
   PrefixResolver prefixResolver = null;
   XPathHelper() {
      xpathSupport = new XMLParserLiaisonDefault();
      xpathParser = new XPathProcessorImpl(xpathSupport);
   }
   public NodeList processXPath(String xpath, Node target) thrws SAXException {
      prefixResolver = new PrefixResolverDefault(target);
      // create the XPath and initialize it
      XPath xp = new XPath();
      xpathParser.initXPath(xp, xpath, prefixResolver);
      // now execute the XPath select statement
      XObject list = xp.execute(xpathSupport, target, prefixResolver);
      // return the resulting node
      return list.nodeset();
   }
}


After creating the helper class, we can rewrite our finder method again, which is now very short:

  • Print
  • Feedback

Resources
  • Recent XML articles in JavaWorld
  • XML help
  • Other valuable XML-related resources