Java XML Tutorial

How to modify XML file in Java – (JDOM)

This tutorial shows how to use the JDOM to modify an XML file.

Table of contents

P.S Tested with JDOM 2.0.6

Note
We need to understand how to JDOM parse XML and write XML, in order to modify the XML documents.

1. Download the JDOM 2.x

Maven for JDOM.

pom.xml

  <dependency>
      <groupId>org.jdom</groupId>
      <artifactId>jdom2</artifactId>
      <version>2.0.6</version>
  </dependency>

2. The XML file, before and after

2.1 The original XML file.

c:\\test\\staff.xml

<?xml version="1.0" encoding="utf-8"?>
<company>
    <staff id="1001">
        <name>mkyong</name>
        <role>support</role>
        <salary currency="USD">5000</salary>
        <!-- for special characters like < &, need CDATA -->
        <bio><![CDATA[HTML tag <code>testing</code>]]></bio>
    </staff>
    <staff id="1002">
        <name>yflow</name>
        <role>admin</role>
        <salary currency="EUR">8000</salary>
        <bio><![CDATA[a & b]]></bio>
    </staff>
</company>

2.2 See below JDOM example to modify the above XML, add, remove and update the elements, attribute, comments, CDATA, etc.

For staff, id is 1001

  1. Remove XML element role
  2. Update XML element salary, update attribute to MYR

For staff, id is 1002

  1. Remove xml element name
  2. Add a new xml element address and CDATA content
  3. Update xml element salary to 2000
  4. Remove the xml element CDATA

Also, add a new XML child node, staff, and remove all the XML comments.

The below is the modified XML Output.

c:\\test\\staff.xml

<?xml version="1.0" encoding="UTF-8"?>
<company>
  <staff id="1001">
    <name>mkyong</name>
    <salary currency="MYR">5000</salary>
    <bio><![CDATA[HTML tag <code>testing</code>]]></bio>
  </staff>
  <staff id="1002">
    <role>admin</role>
    <salary currency="EUR">2000</salary>
    <bio>a &amp; b &amp; c</bio>
    <address><![CDATA[123 & abc]]></address>
  </staff>
  <staff id="1003" />
</company>

3. Modify XML file

The below example uses JDOM to parse the above XML file, modify the content and write it to a file.

Read the code comments for self-explanatory.

ModifyXmlJDom.java

package com.mkyong.xml.jdom;

import org.jdom2.CDATA;
import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import javax.xml.XMLConstants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class ModifyXmlJDom {

    private static final String FILENAME = "src/main/resources/staff.xml";

    public static void main(String[] args) throws JDOMException, IOException {

        SAXBuilder sax = new SAXBuilder();

        // https://rules.sonarsource.com/java/RSPEC-2755
        // prevent xxe
        sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

        Document doc = sax.build(new File(FILENAME));

        Element rootNode = doc.getRootElement();

        List<Element> listChildrenNode = rootNode.getChildren("staff");

        // staff = 2
        System.out.println("No of child nodes: " + listChildrenNode.size());

        // loop the elements
        for (Element staff : listChildrenNode) {

            String id = staff.getAttribute("id").getValue();

            // if staff id is 1001
            if ("1001".equals(id.trim())) {

                // remove element role
                staff.removeChild("role");

                // update xml element `salary`, update attribute to MYR
                staff.getChild("salary").setAttribute("currency", "MYR");

            }

            // if staff id is 1002
            if ("1002".equals(id.trim())) {

                // remove xml element `name`
                staff.removeChild("name");

                // add a new xml element `address` and CDATA content
                staff.addContent(new Element("address")
                        .addContent(new CDATA("123 & abc")));

                // update xml element `salary` to 2000
                staff.getChild("salary").setText("2000");

                // remove the xml element CDATA
                staff.getChild("bio").setText("a & b & c"); // now the & will escape automatically
            }

            // Java 8 to remove all XML comments
            staff.getContent().removeIf(
                    content -> content.getCType() == Content.CType.Comment);

            // remove the XML comments via iterator
            /*ListIterator<Content> iter = staff.getContent().listIterator();
            while (iter.hasNext()) {
                Content content = iter.next();
                if (content.getCType() == Content.CType.Comment) {
                    iter.remove();
                }
            }*/

        }

        // add a new XML child node, staff id 1003
        rootNode.addContent(new Element("staff").setAttribute("id", "1003"));

        // print to console for testing
        XMLOutputter xmlOutput = new XMLOutputter();
        xmlOutput.setFormat(Format.getPrettyFormat());

        // write to console
        // xmlOutput.output(doc, System.out);

        // write to a file
        try (FileOutputStream output =
                     new FileOutputStream("c:\\test\\staff-update.xml")) {
            xmlOutput.output(doc, output);
        }

    }

}

Output

c:\\test\\staff-update.xml

<?xml version="1.0" encoding="UTF-8"?>
<company>
  <staff id="1001">
    <name>mkyong</name>
    <salary currency="MYR">5000</salary>
    <bio><![CDATA[HTML tag <code>testing</code>]]></bio>
  </staff>
  <staff id="1002">
    <role>admin</role>
    <salary currency="EUR">2000</salary>
    <bio>a &amp; b &amp; c</bio>
    <address><![CDATA[123 & abc]]></address>
  </staff>
  <staff id="1003" />
</company>

4. Find and remove XML elements

If an XML element name equals mkyong, remove its data, and the entire staff elements.

ModifyXmlJDom4.java

package com.mkyong.xml.jdom;

import org.jdom2.CDATA;
import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import javax.xml.XMLConstants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class ModifyXmlJDom4 {

  private static final String FILENAME = "src/main/resources/staff.xml";

  public static void main(String[] args) throws JDOMException, IOException {

      SAXBuilder sax = new SAXBuilder();

      // https://rules.sonarsource.com/java/RSPEC-2755
      // prevent xxe
      sax.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
      sax.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

      Document doc = sax.build(new File(FILENAME));

      Element rootNode = doc.getRootElement();

      List<Element> listChildrenNode = rootNode.getChildren("staff");

      // loop the elements
      for (Element staff : listChildrenNode) {

          // if name = mkyong, remove the staff node
          if ("mkyong".equals(staff.getChildText("name"))) {
              rootNode.removeContent(staff);
          }

      }

      // print to console for testing
      XMLOutputter xmlOutput = new XMLOutputter();
      xmlOutput.setFormat(Format.getPrettyFormat());

      // write to console
      xmlOutput.output(doc, System.out);

  }

}

Output

Terminal

<?xml version="1.0" encoding="UTF-8"?>
<company>
  <staff id="1002">
    <name>yflow</name>
    <role>admin</role>
    <salary currency="EUR">8000</salary>
    <bio><![CDATA[a & b]]></bio>
  </staff>
</company>

Note
More JDOM2 examples – JDOM2 A Primer

5. Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-xml

$ cd src/main/java/com/mkyong/xml/jdom/

6. References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
mist42nz
6 years ago

removing a single field is trival.
how does one do the more common practice of identifying a record by a value (eg staff member: mkyong) and then remove ALL of mkyong’s data from his mkyong record, smoothly and safely?