Channels ▼

Eric Bruno

Dr. Dobb's Bloggers

Creating and Modifying XML in Java

March 14, 2013

Almost two years ago, I wrote a blog with code (found here) that parsed XML easily using the Apache Xerces DOM parser. In the blog, I wrote some helper methods to locate XML elements and return their values in a less verbose way. This proved to be one of my most popular blog entries to date. However, one reader commented that it would be nice to add helper methods to easily create or modify XML, not just parse it. This blog is the answer to that request.

I've added two new helper methods to the code I presented last time:

  1. setNodeValue — takes an element (or tag) name, a String value, and the list of nodes within which the existing node can be found
  2. addNode — takes an element (or tag) name, a String value, and the parent node for which the new node is to be a child of

Let's look at setNodeValue, which is meant to set the value of an existing XML element within your XML document:

    protected void setNodeValue(String tagName, String value, NodeList nodes) {
        Node node = getNode(tagName, nodes);
        if ( node == null )
            return;

        // Locate the child text node and change its value
        NodeList childNodes = node.getChildNodes();
        for (int y = 0; y < childNodes.getLength(); y++ ) {
            Node data = childNodes.item(y);
            if ( data.getNodeType() == Node.TEXT_NODE ) {
                data.setNodeValue(value);
                return;
            }
        }
    }

The code works by first locating the specified node within the list of nodes provided. If it's not found, the method returns without doing anything. Otherwise it locates the node's text value child node, sets that child node's value to the new value, and returns. Pretty straightforward but somewhat verbose, and definitely not something you want to repeat all over your code. As a result, this helper method comes in handy.

Next, let's look at addNode, which adds a new XML element, with value, to your XML document:

    protected void addNode(String tagName, String value, Node parent) {
        Document dom = parent.getOwnerDocument();
        
        // Create a new Node with the given tag name
        Node node = dom.createElement(tagName);
        
        // Add the node value as a child text node
        Text nodeVal = dom.createTextNode(value);
        Node c = node.appendChild(nodeVal);
        
        // Add the new node structure to the parent node
        parent.appendChild(node);
    }

To create any type of Node or Element object with the Xerces parser, you need a reference to the XML document's Document object. Any existing Node or Element can provide this via a call to getOwnerDocument. Next, we create a generic Element object with the element tag name provided. Then, we create a specific Text Node with the value provided, and append it to the new Element created prior. Finally, the Element (with its child Text Node) is added as a child to the parent Node provided, and our work is done.

Using the Methods

In my previous blog, I presented code that simply parsed the XML and read the values of some tags, as such:

    DOMParser parser = new DOMParser();
    parser.parse("mydocument.xml");
    Document doc = parser.getDocument();

    // Get the document's root XML node
    NodeList root = doc.getChildNodes();

    // Navigate down the hierarchy to get to the CEO node
    Node comp = getNode("Company", root);
    Node exec = getNode("Executive", comp.getChildNodes() );
    String execType = getNodeAttr("type", exec);

    // Load the executive's data from the XML
    NodeList nodes = exec.getChildNodes();
    String lastName = getNodeValue("LastName", nodes );
    String firstName = getNodeValue("FirstName", nodes);
    String street = getNodeValue("street", nodes );
    ...

I won't go into detail here as this is all explained in the previous blog. Instead, let's modify the value of the "street" tag, assuming the company moved:

    setNodeValue("street", "456 Maple Avenue", nodes);

Next, let's add the person's phone number, which was missing in the original XML:

    addNode("Phone", "123-456-7890", exec );

And that's it. Very simple and one line of code for changes made to the XML.

Serializing the DOM

After using these two methods to modify your XML document, you may want to write the content out as an XML file to disk. To do so, you need to serialize the Document as shown in this abbreviated sample code that loads an XML document, modifies it, and then saves it back to disk:

    // First read the XML file and parse
    DOMParser parser = new DOMParser();
    parser.parse("mydocument.xml");
    Document doc = parser.getDocument();

    // Modify the XML
    ...

    // Write updated XML
    doc = parser.getDocument();
    OutputFormat format = new OutputFormat(doc);
    format.setIndenting(true);
    String filename = "mydocument"+System.currentTimeMillis()+".xml";
    XMLSerializer serializer = new XMLSerializer(
        new FileOutputStream(new File(filename)), format);
    serializer.serialize(doc);

When beginning the serialization process, it's important to call getDocument again to be sure we have the updated Document structure. Next, set the formatting to maintain indentation. To preserve the original XML file, a new filename is created. Finally, the Xerces XMLSerializer is used to write the contents of the Document to a new file with the given filename. Of course, you can alternatively provide the previous file to overwrite it.

The Xerces parser makes it easy to create and parse XML documents, although some of the API leads to verbose Java code. This blog, combined with the previous one I wrote, makes it much easier to perform common operations when parsing and modifying your XML files. I hope you find it useful.

Happy Coding!
-EJB

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video