February 9, 2010

Minimal Java for XML Processing

XML Logo
These Java examples show very simple ways to write, validate, and read XML files.  Use the examples as tutorials to learn the basics of working with XML.

Catalog of Java examples for XML processing:
Java Get Powered
The examples are presented as complete programs so you can quickly run and test them.

For example, to try out the "XML Writer" program, you would download the XmlWriter.java file and execute the following commands:
     $ javac *.java
     $ java XmlWriter.class
Code here is Public Domain Software — free to use as you like.


XML Writer
This example program creates a very simple DOM (Document Object Model) containing a list of countries and then writes the DOM out to an XML file.

XmlWriter.java
import java.io.File;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;

public class XmlWriter {

   public static void main(String[] args) {
      try {
         //Sample Data (countries and capitals)
         HashMap<String, String> data = new HashMap<String, String>();
         data.put("Egypt",   "Cairo");
         data.put("Finland", "Helsinki");
         data.put("Japan",   "Tokyo");

         //Create DOM (with top-level node)
         DocumentBuilder xmlBuilder =
            DocumentBuilderFactory.newInstance().newDocumentBuilder();
         Document xmlDoc = xmlBuilder.newDocument();
         Node node = xmlDoc.createElement("countries");
         xmlDoc.appendChild(node);  //top-level node

         //Add Data to DOM
         for (String key : data.keySet()) {
            Element elem = xmlDoc.createElement("country");
            elem.setAttribute("capital", data.get(key));   //attrib
            elem.appendChild(xmlDoc.createTextNode(key));  //content
            node.appendChild(elem);
            }

         //Write DOM to XML file
         Source source = new DOMSource(xmlDoc);
         Result result = new StreamResult(new File("countries.xml"));
         Transformer xformer =
            TransformerFactory.newInstance().newTransformer();
         xformer.setOutputProperty(OutputKeys.INDENT, "yes");
         xformer.transform(source, result);
         }
      catch (Exception e) {
         System.out.println(e.getMessage());
         }
      }

   }
View/Download: XmlWriter.java

countries.xml
<?xml version="1.0" encoding="UTF-8"?>
<countries>
<country capital="Helsinki">Finland</country>
<country capital="Cairo">Egypt</country>
<country capital="Tokyo">Japan</country>
</countries>
File Created by Program

Note that using a DOM holds the entire XML tree structure in memory. For large data sets it is often necessary to instead use SAX (Simple API for XML) which uses an event based approach to hold and process only the part of the document that is needed.


XML Validator
This example program validates an XML file against an XSD (XML Schema Definition).

XmlValidator.java
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.transform.stream.StreamSource;

public class XmlValidator {

   public static void main(String[] args) {
      try {
         StreamSource xsdInput = new StreamSource(new
            XmlValidator().getClass().getResourceAsStream("countries.xsd"));
         Schema schema = SchemaFactory.newInstance(
            XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(xsdInput);
         schema.newValidator().validate(new StreamSource(
            new File("countries.xml")));
         System.out.println("XML file sucessfully validated against XSD.");
         }
      catch (Exception e) {
         System.out.println(e.getMessage());
         }
      }

   }
View/Download: XmlValidator.java

XML Schema Used to Validate XML
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:element name="countries">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="country" maxOccurs="unbounded"/>
            </xs:sequence>
         </xs:complexType>
      </xs:element>
   <xs:element name="country">
      <xs:complexType mixed="true">
         <xs:attribute name="capital" type="xs:string" use="required" />
         </xs:complexType>
      </xs:element>
   </xs:schema>
View/Download: countries.xsd

cvc-complex-type.2.4.a: Invalid content was found starting
with element 'region'. One of '{"":country}' is expected.
Program Output

The above error message was generated from an input file (countries.xml) containing invalid XML.  A <region> tag was used where a <country> tag was expected.


XML Reader
This example program reads an XML file and prints out the name of each node along with its first attribute.

XmlReader.java
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;

public class XmlReader {

   static void processNode(Node node) {
      String msg = "node --> " + node.getNodeName();
      String nodeContent = node.getFirstChild().getNodeValue();
      if (!nodeContent.equals("\n"))  //check if has text content
         msg = msg + " | value: " + nodeContent; //add text content
      if (node.hasAttributes())  //add first attrib if exists
          msg = msg + " | attrib: " +
            node.getAttributes().item(0).getNodeName() + "=" +
            node.getAttributes().item(0).getNodeValue();
      System.out.println(msg);  //display node information
      for (Node subNode = node.getFirstChild(); subNode != null;
            subNode = subNode.getNextSibling())
         if (subNode.getNodeType() == Node.ELEMENT_NODE)
            processNode(subNode);
      }

   public static void main(String[] args) {
      try {
         DocumentBuilder xmlBuilder =
            DocumentBuilderFactory.newInstance().newDocumentBuilder();
         Document xmlDoc = xmlBuilder.parse(new File("countries.xml"));
         processNode(xmlDoc.getDocumentElement());
         }
      catch (Exception e) {
         System.out.println(e.getMessage());
         }
      }

   }
View/Download: XmlReader.java

node --> countries
node --> country | value: Finland | attrib: capital=Helsinki
node --> country | value: Egypt | attrib: capital=Cairo
node --> country | value: Japan | attrib: capital=Tokyo
Program Output (input file: countries.xml)


Further Reading

Elsewhere: