How to modify XML file in Java – (DOM Parser)

This tutorial shows how to use the Java built-in DOM Parser to modify an XML file.

Table of contents

P.S Tested with Java 11.

Note
Please read DOM parse XML and DOM write XML.

1. The XML file, before and after

The original XML file.

staff-simple.xml

<?xml version="1.0" encoding="utf-8"?>
<company>
    <staff id="1001">
        <name>mkyong</name>
        <role>support</role>
    </staff>
    <staff id="1002">
        <name>yflow</name>
        <role>admin</role>
    </staff>
</company>

Later we will use DOM parser to modify the following XML data.

For staff id 1001

  • Remove the XML element name.
  • For the XML element role, update the value to "founder".

For staff id 1002

  • Update the XML attribute to 2222.
  • Add a new XML element salary, contains attribute and value.
  • Add a new XML comment.
  • Rename an XML element, from name to n (remove and add).

Below is the final modified XML file.


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<company>
    <staff id="1001">
        <role>founder</role>
    </staff>
    <staff id="2222">
        <role>admin</role>
        <salary currency="USD">1000</salary>
        <!--from name to n-->
        <n>yflow</n>
    </staff>
</company>

2. Dom Parser modify XML file

Below is the DOM parser example to take the original XML file staff-simple.xml, modify the XML and generate the modified XML file staff-modified.xml.

ModifyXmlDomParser.java

package com.mkyong.xml.dom;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;

public class ModifyXmlDomParser {

    private static final String FILENAME = "src/main/resources/staff-simple.xml";
    // xslt for pretty print only, no special task
    private static final String FORMAT_XSLT = "src/main/resources/xslt/staff-format.xslt";

    public static void main(String[] args) {

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        try (InputStream is = new FileInputStream(FILENAME)) {

            DocumentBuilder db = dbf.newDocumentBuilder();

            Document doc = db.parse(is);

            NodeList listOfStaff = doc.getElementsByTagName("staff");
            //System.out.println(listOfStaff.getLength()); // 2

            for (int i = 0; i < listOfStaff.getLength(); i++) {
                // get first staff
                Node staff = listOfStaff.item(i);
                if (staff.getNodeType() == Node.ELEMENT_NODE) {
                    String id = staff.getAttributes().getNamedItem("id").getTextContent();
                    if ("1001".equals(id.trim())) {

                        NodeList childNodes = staff.getChildNodes();

                        for (int j = 0; j < childNodes.getLength(); j++) {
                            Node item = childNodes.item(j);
                            if (item.getNodeType() == Node.ELEMENT_NODE) {

                                if ("role".equalsIgnoreCase(item.getNodeName())) {
                                    // update xml element `role` text
                                    item.setTextContent("founder");
                                }
                                if ("name".equalsIgnoreCase(item.getNodeName())) {
                                    // remove xml element `name`
                                    staff.removeChild(item);
                                }
                            }

                        }

                        // add a new xml element, address
                        Element address = doc.createElement("address");
                        // add a new xml CDATA
                        CDATASection cdataSection =
                                doc.createCDATASection("HTML tag <code>testing</code>");

                        address.appendChild(cdataSection);

                        staff.appendChild(address);

                    }

                    if ("1002".equals(id.trim())) {

                        // update xml attribute, from 1002 to 2222
                        staff.getAttributes().getNamedItem("id").setTextContent("2222");

                        // add a new xml element, salary
                        Element salary = doc.createElement("salary");
                        salary.setAttribute("currency", "USD");
                        salary.appendChild(doc.createTextNode("1000"));
                        staff.appendChild(salary);

                        // rename a xml element from `name` to `n`
                        // sorry, no API for this, we need to remove and create
                        NodeList childNodes = staff.getChildNodes();

                        for (int j = 0; j < childNodes.getLength(); j++) {
                            Node item = childNodes.item(j);
                            if (item.getNodeType() == Node.ELEMENT_NODE) {

                                if ("name".equalsIgnoreCase(item.getNodeName())) {

                                    // Get the text of element `name`
                                    String name = item.getTextContent();

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

                                    // add a new xml element, n
                                    Element n = doc.createElement("n");
                                    n.appendChild(doc.createTextNode(name));

                                    // add a new comment
                                    Comment comment = doc.createComment("from name to n");
                                    staff.appendChild(comment);

                                    staff.appendChild(n);

                                }
                            }

                        }

                    }

                }

            }

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

            try (FileOutputStream output =
                         new FileOutputStream("c:\\test\\staff-modified.xml")) {
                writeXml(doc, output);
            }

        } catch (ParserConfigurationException | SAXException
                | IOException | TransformerException e) {
            e.printStackTrace();
        }

    }

    // write doc to output stream
    private static void writeXml(Document doc,
                                 OutputStream output)
            throws TransformerException, UnsupportedEncodingException {

        TransformerFactory transformerFactory = TransformerFactory.newInstance();

        // The default add many empty new line, not sure why?
        // https://mkyong.com/java/pretty-print-xml-with-java-dom-and-xslt/
        // Transformer transformer = transformerFactory.newTransformer();

        // add a xslt to remove the extra newlines
        Transformer transformer = transformerFactory.newTransformer(
                new StreamSource(new File(FORMAT_XSLT)));

        // pretty print
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.STANDALONE, "no");

        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(output);

        transformer.transform(source, result);

    }

}

Output – the modified XML file.

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

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<company>
    <staff id="1001">
        <role>founder</role>
        <address>
            <![CDATA[HTML tag <code>testing</code>]]>
        </address>
    </staff>
    <staff id="2222">
        <role>admin</role>
        <salary currency="USD">1000</salary>
        <!--from name to n-->
        <n>yflow</n>
    </staff>
</company>

3. Download Source Code

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

$ cd java-xml

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

4. References

10 comments on “How to modify XML file in Java – (DOM Parser)

  1. what if one of my tag is empty, for example name tag is empty, I tried and its giving me something like this <name/>, how to handle empty tags. This will help me alot. Thanks

    Reply
  2. Hi @mkyong,
    I am unable to get my output xml indented by using a similar xslt to yours. Do you know why?

    Reply
  3. Underscore-java can read xml to map and then generate xml from it.

    Reply
  4. How can i change the name of the element such as “lastname” to “LNAME”

    Reply
    1. The article is updated with rename XML element example.

      There is no rename DOM API, we need to remove and recreate the new XML element.

      Reply
  5. Hi.
    it’s not the first time that your explanations helped me.
    Just want to thank you … very much.
    Cheers from Portugal
    🙂

    Reply
  6. Dear Sir,

    I want to save the modified XML into a String variable- you have showed how to save it to a file.

    Please let me know how to save the modified XML to a string variable.

    Thanks,
    Arvind.

    Reply
    1. TransformerFactory transformerFac = TransformerFactory.newInstance();
      Transformer transformer = transformerFac.newTransformer();
      StreamResult streamResultToResp = new StreamResult(new StringWriter());
      DOMSource source = new DOMSource(doc);
      transformer.transform(source, streamResultToResp);
      //Now assing to string variable
      String xmlVal = streamResultToResp.getWriter().toString();

      Reply

Leave a Comment

Your email address will not be published. Required fields are marked *