Homepage of Ingo Klöckl
 Home
 Programmieren
 - Toolbox
 - Java
 - PostScript
 - Perl
 - Assembler
 - Links
 - Download
Ingo Klöckl
i.kloeckl@2k-software.de

Manipulating XML files using JDom

JDom is a powerful and simple library for working with XML files. Here, I want to present the essential of writing and reading XML using JUnit.

TODO

Creating XML files

Assume we want to write the following configuration file in XML format:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <name>myConfig</name>
    <path id="src">/usr/ingo/src</path>
    <path id="tmp">/tmp/ingo</path>
    <path id="webroot">
        /usr/ingo/webapp
        <filter>*.jsp</filter>
        <filter>*.html</filter>
    </path>
</config>
This task can easily be performed using JDom (the code can be downloaded here):
package de.kksoftware.demo.xml;

import java.io.*;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

public class JDomCreateFile {

  public static void main(String[] args) throws Exception {
    // create empty document with root element 
    Element oRoot = new Element("config");
    Document oDoc = new Document(oRoot);
    /*
     * Document oDoc = new Document();
     * oDoc.setRootElement(oRoot);
     */
    
    // add  nodes to the document:
    //  first, create an empty element and add content
    Element oName = new Element("name");
    oName.setText("myConfig");
    oRoot.addContent(oName);
    // create another element, setting the content in one step
    // and adding an attribute
    Element oPath1 = new Element("path").addContent("/usr/ingo/src");
    oPath1.setAttribute("id", "src");
    oRoot.addContent(oPath1);
    Element oPath2 = new Element("path").addContent("/tmp/ingo");
    oPath2.setAttribute("id", "tmp");
    oRoot.addContent(oPath2);
    Element oPath3 = new Element("path").addContent("/usr/ingo/webapp");
    oPath3.setAttribute("id", "webroot");
    oPath3.addContent(new Element("filter").addContent("*.jsp"));
    oPath3.addContent(new Element("filter").addContent("*.html"));
    oRoot.addContent(oPath3);

    // write XML to console and file, using four spaces for
    // indentation and newlines for line-breaking    
    XMLOutputter oOut = new XMLOutputter("  ", true);
    oOut.output(oDoc, System.out);
    oOut.output(oDoc, new FileOutputStream(new File("myconfig.xml")));
  }
}

Reading XML files

Reading a XML file is as easy as creating one. Based on a SAXBuilder, a JDom Document is constructed. This document offer Java methods for finding and working with the document's nodes (the code can be downloaded here):
package de.kksoftware.demo.xml;

import java.io.*;
import java.util.*;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

public class JDomReadFile {

  public static void main(String[] args) throws Exception {
    // create a XML parser and read the XML file
    SAXBuilder oBuilder = new SAXBuilder();
    Document oDoc = oBuilder.build(new File("myconfig.xml"));
    
    // get the root node of the document
    Element oRoot = oDoc.getRootElement();
    System.out.println("Root element is "+oRoot.getName());
    // get first  node and print its content (see below)
    System.out.println("Configuration name is "+oRoot.getChildTextTrim("name"));
    
    // get all children of the root node of type 
    // other variants:
    //   oRoot.getChildren() would retrieve all sub-nodes
    List oPathes = oRoot.getChildren("path");
    System.out.println("There are "+oPathes.size()+" pathes defined:");
    Iterator iter = oPathes.iterator();
    while (iter.hasNext()) {
      Element oPath = (Element)iter.next();
      // read the "id" attribute
      String strId = oPath.getAttributeValue("id");
      // print out node content:
      //   - getText() just returns text
      //   - getTextNormalize() removes surrounding white space
      //    and compresses multiple spaces to a single one
      //   - getTextTrim() removes surrounding white space
      System.out.println("Path "+strId+" is "+oPath.getTextTrim());
      // get sub-nodes 
      Iterator iterFilter = oPath.getChildren("filter").iterator();
      while (iterFilter.hasNext()) {
        Element oFilter = (Element) iterFilter.next();
        System.out.println("  defined filter: "+oFilter.getTextTrim());
      }
    }
  }
}

Some methods

Some of the most important JDom methods follows below:

Element document.getRootElement()

element.addContent(Element element)
element.addContent(new CDATA(String content))
element.removeContent(Element element)
String element.getText()
String element.getTextTrim()
String element.getText()

List element.getChildren()
List element.getChildren(String name)
Element element.getChild(String name)

list.remove(int index)
list.removeAll(List)
list.add(Element element)
list.add(int index, Element element)

element.removeChildren(String name)

String element.getAttributeValue(String name)
Attribute element.getAttribute(String name)
 attribute.getValue()
element.setAttribute(String name, String value)
element.removeAttribute(String name)

Compiler prerequisites

To compile or start a program using JDom, you only have to ensure that the archive jdom.jar is in the classpath.
To use JDom's XPath capabilities, you need a XPath implementation, e.g. Jaxen. The libraries jaxen-full.jar and saxpath.jar must be found in the classpath.

Transforming XML files

You can use JDom to easily execute XSLT transformations on the JDom Document. To do this, some XSLT-related objects comes into play. We can extend the first example to create a XML file and transform it to print a report (the code can be downloaded here):
package de.kksoftware.demo.xml;

import java.io.*;

import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
import org.jdom.transform.JDOMSource;

public class JDomCreateFile {

  public static void main(String[] args) throws Exception {
    // create the document, see above
    Document oDoc = ...

    // transform the created document using XSLT, write it to 
    // the console
    JDOMSource oSource = new JDOMSource(oDoc);
    StreamResult oResult = new StreamResult(System.out);
    TransformerFactory transformerFactory = 
      TransformerFactory.newInstance();
    Templates oStylesheet = transformerFactory.newTemplates(
      new StreamSource(new File("mystyle.xsl")));
    Transformer oTransformer = oStylesheet.newTransformer();
    oTransformer.transform(oSource, oResult);
  }
}

(Note that this example is not as JDoc-specific as you might think, if you have a look at the JAXP page.)

Working with XPath expressions

JDom allows you to work with XPath expressions, if you supply a XPath implementation. This can be Jaxen. Its usage is simple: (the code can be downloaded here):
package de.kksoftware.demo.xml;

import java.io.*;
import java.util.*;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

public class JDomReadXPath {

  public static void main(String[] args) throws Exception {
    if (args.length!=1){
      System.out.println("Usage: JDomReadXPath ");
      System.exit(1);
    }
    String strXPathExpression = args[0];
    
    // create a XML parser and read the XML file
    SAXBuilder oBuilder = new SAXBuilder();
    Document oDoc = oBuilder.build(new File("myconfig.xml"));

    XPath oPath = XPath.newInstance(strXPathExpression);
    List oResult = oPath.selectNodes(oDoc);
    Iterator iter = oResult.iterator();
    while (iter.hasNext()) {
      Element oNode = (Element) iter.next();
      System.out.println("Found: "+oNode.getName());
    }
  }
}

back to toolbox page