How to retain DOCTYPE declaration while saving DOM Document to an XML file
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
- w3c Dom parser
- JDK 1.6
- 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
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