dom4j
dom4j [http://www.dom4j.org/] began as a fork of the JDOM project by one developer, James Strachan, who disagreed with several aspects of the JDOM architecture, including the decision to use classes instead of interfaces. dom4j has since gone its own way to feature a very different approach to a pure-Java, tree-based API than either DOM or JDOM. Notable unique features in dom4j include integrated XPath and XSLT support and optional DOM compatibility (for example, you can wrap a dom4j Element inside a DOM Element).
Example 5.8 shows the dom4j version of our standard example. It's structured pretty much like the previous two tree-based APIs. First a Document object representing the XML-RPC request is constructed in memory, and then it is serialized onto the URLConnection's output stream. Finally, the response document is parsed to find the desired value.
Example 5.8 A dom4j-Based Client for the Fibonacci XML-RPC Server
import java.net.*; import java.io.*; import org.dom4j.*; import org.dom4j.io.*; public class Fibonaccidom4jClient { public final static String DEFAULT_SERVER = "http://www.elharo.com/fibonacci/XML-RPC"; public static void main(String[] args) { if (args.length <= 0) { System.out.println( "Usage: java Fibonaccidom4jClient number url" ); return; } String server = DEFAULT_SERVER; if (args.length >= 2) server = args[1]; try { // Build request document Document request = DocumentHelper.createDocument(); Element methodCall = request.addElement("methodCall"); Element methodName = methodCall.addElement("methodName"); methodName.addText("calculateFibonacci"); Element params = methodCall.addElement("params"); Element param = params.addElement("param"); Element value = param.addElement("value"); // Had to break the naming convention here because of a // conflict with the Java keyword int Element intElement = value.addElement("int"); intElement.addText(args[0]); // Transmit the request document URL u = new URL(server); URLConnection uc = u.openConnection(); HttpURLConnection connection = (HttpURLConnection) uc; connection.setDoOutput(true); connection.setDoInput(true); connection.setRequestMethod("POST"); OutputStream out = connection.getOutputStream(); XMLWriter serializer = new XMLWriter(out); serializer.write(request); out.flush(); out.close(); // Read the response InputStream in = connection.getInputStream(); SAXReader reader = new SAXReader(); Document response = reader.read(in); in.close(); connection.disconnect(); // Use XPath to find the element we want Node node = response.selectSingleNode( "/methodResponse/params/param/value/double" ); String result = node.getStringValue(); System.out.println(result); } catch (Exception e) { System.err.println(e); } } }
In dom4j the request Document object is initially created by the DocumentHelper.createDocument() factory method. The contents of the document are formed at the same time they're added to their parent, so that no nodes are ever orphaned from the tree. The XMLWriter class performs the serialization to the server.
Once dom4j receives the response, it parses it into a Document object using the SAXReader class that connects dom4j to an underlying parser such as Crimson or Xerces. XPath extracts the double element from this document. If you're comfortable with XPath, this is a very useful and convenient feature.