If we save a DOM Document to an XML file using javax.xml.transform.Transformer, DOCTYPE declaration gets emitted by default. This example shows how we can retain PUBLIC and SYSTEM id of the DOCTYPE declaration for external DTD.

Tools and Technologies used in this article

  1. w3c Dom parser
  2. JDK 1.6
  3. Eclipse 3.7

1. Create Java Project

Select from the menu File --> New --> Java Project (say 'HowToRetainXMLDocType').
Copy 'sampleXml.xml' and 'sc.dtd' directly under project directory.

File: sampleXml.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE srccodes PUBLIC "-//SRCCODES PUBLISHING GROUP//DTD 4.0//EN" "sc.dtd">
<srccodes>
    <article changefreq="weekly" id="10">http://www.srccodes.com/p/article/10/Programmatically-Start-or-Stop-an-Application-deployed-in-IBM-WebSphere-Application-Server-using-Java-Code</article>
    <article changefreq="weekly" id="11">http://www.srccodes.com/p/article/11/spring-3-hello-world-example-tutorial-using-maven-tool-and-eclipse-ide</article>
</srccodes>

Note: We'll modify 'changefreq' of article having id '10' from 'weekly' to 'monthly', then save modified DOM to the same XML file.

File: sc.dtd

<!ELEMENT srccodes (article+)>
<!ELEMENT article (#PCDATA)>
<!ATTLIST article changefreq CDATA #REQUIRED>
<!ATTLIST article id ID #REQUIRED>

Note: We are going to use 'getElementById' method of Document to get the article having id '10'. So it is required to define 'id' attribute of element 'article' as type 'ID' in DTD file. Otherwise 'getElementById' will return null.

2. Write code

Create a java class (say com.srccodes.examples.howto.HowToRetainXMLDocType)
Modify the java class as per the following code.

File: HowToRetainXMLDocType.java

package com.srccodes.examples.howto;
 
import java.io.File;
import java.io.IOException;
 
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 org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
 
/**
 * @author Abhijit Ghosh
 * @version 1.0
 *
 */
public class HowToRetainXMLDocType {
    private static final String SAMPLE_XML_FILE = "sampleXml.xml";
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            // Get the xml document
            Document xmlDoc = getDocument(SAMPLE_XML_FILE);
             
            // Modify the 'changefreq' attribute of the element having id 10
            Element articleElement = xmlDoc.getElementById("10");
            articleElement.setAttribute("changefreq", "monthly");
             
            // Update the xml file
            saveToXml(xmlDoc, SAMPLE_XML_FILE);
             
        } catch (Exception ex) { // For simplicity Exception is used instead of handling specific one
            ex.printStackTrace();
        }
    }
     
    /**
     * To get DOM Document from the xml file.
     * 
     * @param filePath
     * @return DOM Document
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document getDocument(String filePath) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
         
        Document xmlDoc = docBuilder.parse(filePath);
         
        return xmlDoc;
    }
     
    /**
     * To save the Document in xml file 
     * 
     * @param xmlDoc
     * @param filePath
     * @throws TransformerException
     */
    public static void saveToXml(Document xmlDoc, String filePath) throws TransformerException {
        DOMSource source = new DOMSource(xmlDoc);
        StreamResult result = new StreamResult(new File(filePath));
         
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
         
        transformer.transform(source, result);
    }
}

3. Overall Project Structure

Overall Project Structure

4. Run Your Code

Right click on 'HowToRetainXMLDocType.java' and select from context menu 'Run As' --> 'Java Application'.

Open the 'sampleXml.xml' and you will see that 'changefreq' of article having id '10' is modified to 'monthly' but DOCTYPE declaration part is missing.

File: sampleXml.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<srccodes>
    <article changefreq="monthly" id="10">http://www.srccodes.com/p/article/10/Programmatically-Start-or-Stop-an-Application-deployed-in-IBM-WebSphere-Application-Server-using-Java-Code</article>
    <article changefreq="weekly" id="11">http://www.srccodes.com/p/article/11/spring-3-hello-world-example-tutorial-using-maven-tool-and-eclipse-ide</article>
</srccodes>

5. Add code to retain DOCTYPE declaration

Manually change the value of 'changefreq' from 'monthly' to 'weekly' for the article id 10 in 'sampleXml.xml'.
Modify 'saveToXml(Document xmlDoc, String filePath)' method as shown below

File: HowToRetainXMLDocType.java

package com.srccodes.examples.howto;
 
import java.io.File;
import java.io.IOException;
 
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 org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
 
/**
 * @author Abhijit Ghosh
 * @version 1.0
 *
 */
public class HowToRetainXMLDocType {
    private static final String SAMPLE_XML_FILE = "sampleXml.xml";
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            // Get the xml document
            Document xmlDoc = getDocument(SAMPLE_XML_FILE);
             
            // Modify the 'changefreq' attribute of the element having id 10
            Element articleElement = xmlDoc.getElementById("10");
            articleElement.setAttribute("changefreq", "monthly");
             
            // Update the xml file
            saveToXml(xmlDoc, SAMPLE_XML_FILE);
             
        } catch (Exception ex) { // For simplicity Exception is used instead of handling specific one
            ex.printStackTrace();
        }
    }
     
    /**
     * To get DOM Document from the xml file.
     * 
     * @param filePath
     * @return DOM Document
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Document getDocument(String filePath) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
         
        Document xmlDoc = docBuilder.parse(filePath);
         
        return xmlDoc;
    }
     
    /**
     * To save the Document in xml file 
     * 
     * @param xmlDoc
     * @param filePath
     * @throws TransformerException
     */
    public static void saveToXml(Document xmlDoc, String filePath) throws TransformerException {
        DOMSource source = new DOMSource(xmlDoc);
        StreamResult result = new StreamResult(new File(filePath));
         
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");  
         
        DocumentType doctype = xmlDoc.getDoctype();
        if(doctype != null) {
            transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doctype.getPublicId());
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doctype.getSystemId());
        }
         
        transformer.transform(source, result);
    }
}

6. Run Your Code Again

Right click on 'HowToRetainXMLDocType.java' and select from context menu 'Run As' --> 'Java Application'.

Open the 'sampleXml.xml' and you will see that 'changefreq' of article having id '10' is modified to 'monthly' and DOCTYPE declaration is also preserved in the xml file.

File: sampleXml.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE srccodes PUBLIC "-//SRCCODES PUBLISHING GROUP//DTD 4.0//EN" "sc.dtd">
<srccodes>
    <article changefreq="monthly" id="10">http://www.srccodes.com/p/article/10/Programmatically-Start-or-Stop-an-Application-deployed-in-IBM-WebSphere-Application-Server-using-Java-Code</article>
    <article changefreq="weekly" id="11">http://www.srccodes.com/p/article/11/spring-3-hello-world-example-tutorial-using-maven-tool-and-eclipse-ide</article>
</srccodes>

Download SrcCodes

All code samples shown in this post are available in the following link HowToRetainXMLDocType.zip

References

, XML , DTD , Java , How To , classic