Writing out a DOM tree to System.out

You can do this using the XSLT transform package. In XSLT, it is called an identity transform when the transformation is generating the source without any changes.

The following example programmatically creates a DOM tree and uses the Transformer class to output it to System.out.

Main.java:

import org.w3c.dom.*;
 
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;
  
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.newDocument();
  
         Element customers = doc.createElement("customers");
         Element customer = doc.createElement("customer");
         Element name = doc.createElement("name");
 
         name.appendChild(doc.createTextNode("Joris Van den Bogaert"));
         customer.appendChild(name);
         customers.appendChild(customer);
 
         doc.appendChild(customers);
  
         // use the XSLT transformation package to output the DOM tree we just created
         TransformerFactory tf = TransformerFactory.newInstance();
         Transformer transformer = tf.newTransformer();
         transformer.transform(new DOMSource(doc), new StreamResult(System.out));
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

outputs:

<?xml version="1.0" encoding="UTF-8"?>
<customers><customer><name>Joris Van den Bogaert</name></customer></customers>

Writing out a DOM subtree to System.out

You can use the XSLT Transformer class to do this.

Here’s an example.

Test.xml

<?xml version="1.0" encoding="UTF-8"?>
<message>
   <content>Hello World!</content>
   <destinations>
      <dest>jmsqueue:myjmsqueue</dest>
      <dest>file:/home/filequeue</dest>
      <dest>123.30.230.90</dest>
   </destinations>
</message>

Main.java:

import org.w3c.dom.*;
 
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;
  
import java.io.*;
 
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("test.xml"));
 
         NodeList nodeList = doc.getElementsByTagName("destinations");
         Node node = nodeList.item(0);
  
         // use the XSLT transformation package to output the subtree destinations
         TransformerFactory tf = TransformerFactory.newInstance();
         Transformer transformer = tf.newTransformer();
         transformer.transform(new DOMSource(node), new StreamResult(System.out));
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

outputs:

<?xml version="1.0" encoding="UTF-8"?>
<destinations>
      <dest>jmsqueue:myjmsqueue</dest>
      <dest>file:/home/filequeue</dest>
      <dest>123.30.230.90</dest>
   </destinations>

Getting the attributes of an XML Node

Use a NamedNodeMap. The following example shows you how to print out all elements for the tag customer.

customer.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<customers>
   <customer id="C12345" type="prio1">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
</customers>

Main.java:

import org.w3c.dom.*;
 
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customer.xml"));
 
         NodeList nodeList = doc.getElementsByTagName("customer");
         Node node = nodeList.item(0);
  
         NamedNodeMap attributes = node.getAttributes();
         for (int i=0; i<attributes.getLength(); i++) {
            Node attribute = attributes.item(i);
            System.out.println(attribute.getNodeName() + " = " + attribute.getNodeValue());
         }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

outputs:

id = C12345
type = prio1

To get a specific attribute, you can use the method getNamedItem.

Main.java:

import org.w3c.dom.*;
 
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customer.xml"));
 
         NodeList nodeList = doc.getElementsByTagName("customer");
         Node node = nodeList.item(0);
  
         NamedNodeMap attributes = node.getAttributes();
 
         Node custId = attributes.getNamedItem("id");
         Node custType = attributes.getNamedItem("type");
         System.out.println("id   = " + custId.getNodeValue());
         System.out.println("type = " + custType.getNodeValue());
         }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

Including binary data in an XML

All data in XML need to be characters. So, if you want to store binary data in an XML, you would have to encode it first. One way to do this is with Base64. So, you could have an XML file like the following:

   <binmessage>
      <body type="Base64">base64encodedbytearray</body>
   </binmessage>

For more information, check out this JavaWorld tip.

Turning off DTD validation

As soon as you create the DocumentBuilderFactory, call the method setValidating and set it to false.

Try out following example and set it to true to see the parsing errors.

customers.dtd (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<!ELEMENT customer (name, addresses+, email)+ >
<!ATTLIST customer custid CDATA #REQUIRED>
 
<!ELEMENT name (#PCDATA)>
 
<!ELEMENT addresses (addline1, addline2, zip, location, state)>
<!ELEMENT addline1 (#PCDATA)>
<!ELEMENT addline2 (#PCDATA)>
<!ELEMENT zip (#PCDATA)>
<!ELEMENT location (#PCDATA)>
<!ELEMENT state (#PCDATA)>
 
<!ELEMENT email (#PCDATA)>

customers.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE customers SYSTEM "customers.dtd">
<customers>
   <customer id="C12345" type="prio1">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
</customers>

Main.java:

import org.w3c.dom.*;
  
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         dbf.setValidating(true);
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customers.xml"));
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

Checking whether an XML node has attributes

Use the method hasAttributes defined in the interface Node, a superinterface of Element.

Main.java:

import org.w3c.dom.*;
  
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customers.xml"));
 
         Element root = doc.getDocumentElement();
         if (root.hasAttributes()) {
            System.out.println(root.getTagName() + " has attributes!");
         }
         else {
            System.out.println(root.getTagName() + " has no attributes!");
         }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

customers.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<customers id="1">
   <customer id="C12345" type="prio1">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
</customers>

List out the elements that belong to a particular XML namespace

For more information about namespaces, check out http://www.jclark.com/xml/xmlns.htm.

customers.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<customers xmlns='http://www.esus.com/custns'>
   <customer id="C12345" type="prio1">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
   <destination>
      <address xmlns='http://www.esus.com/destns'>123.321.1.20</address>
   </destination>
</customers>

Main.java:

import org.w3c.dom.*;
  
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
  
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         dbf.setNamespaceAware(true);
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customers.xml"));
 
         Element root = doc.getDocumentElement();
         root.normalize();
 
         // display all custns elements
         NodeList nl = doc.getElementsByTagNameNS("http://www.esus.com/custns", "*");
         System.out.println("Elements that belong to http://www.esus.com/custns namespace:");
         printNodeList(nl);
 
         // display all destns elements
         nl = doc.getElementsByTagNameNS("http://www.esus.com/destns", "*");
         System.out.println("Elements that belong to http://www.esus.com/destns namespace:");
         printNodeList(nl);          
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
 
   public static void printNodeList(NodeList nl) {
      for (int i=0; i<nl.getLength(); i++) {
         Node n = nl.item(i);
         System.out.println("t" + n.getNodeName());
         Node tn = n.getFirstChild();
         if (!tn.getNodeValue().trim().equals("")) {   
            System.out.println("tt" + tn.getNodeValue());
         }
         System.out.println();
      }
   }
}

outputs:

Elements that belong to http://www.esus.com/custns namespace:
	customers
 
	customer
 
	name
		Joris Van den Bogaert
 
	address
 
	addressline
		Handelskaai 3
 
	zip
		1000
 
	location
		Brussels
 
	country
		BELGIUM
 
	destination
 
Elements that belong to http://www.esus.com/destns namespace:
	address
		123.321.1.20

Creating your own DOM error handler

Call the method setErrorHandler and pass in your custom class that implements org.xml.sax.ErrorHandler. Make sure you call the method setValidating(true)!

The following example prints out a bunch of error messages, because the XML doesn’t match the DTD.

customers.dtd (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<!ELEMENT customer (name, addresses+, email)+ >
<!ATTLIST customer custid CDATA #REQUIRED>
 
<!ELEMENT name (#PCDATA)>
 
<!ELEMENT addresses (addline1, addline2, zip, location, state)>
<!ELEMENT addline1 (#PCDATA)>
<!ELEMENT addline2 (#PCDATA)>
<!ELEMENT zip (#PCDATA)>
<!ELEMENT location (#PCDATA)>
<!ELEMENT state (#PCDATA)>
 
<!ELEMENT email (#PCDATA)>

customers.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE customers SYSTEM "customers.dtd">
<customers>
   <customer id="C12345">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
   <destination>
      <address>123.321.1.20</address>
   </destination>
</customers>

Main.java:

import org.w3c.dom.*;
  
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
 
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         dbf.setValidating(true);
         
         DocumentBuilder db = dbf.newDocumentBuilder();
         MyErrorHandler handler = new MyErrorHandler();
         db.setErrorHandler(handler);
         doc = db.parse(new File("customers.xml")); 
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}
 
class MyErrorHandler implements ErrorHandler {
   public void warning(SAXParseException e) throws SAXException {
      System.err.println("[warning] "+e.getMessage());
   }
 
   public void error(SAXParseException e) throws SAXException {
      System.err.println("[error] "+e.getMessage());
   }
 
   public void fatalError(SAXParseException e) throws SAXException {
      System.err.println("[fatal error] "+e.getMessage());
      throw e;
   }
};

outputs:

[error] Element type "customers" must be declared.
[error] Attribute "custid" is required and must be specified for element type "customer".
[error] Attribute "id" must be declared for element type "customer".
[error] Element type "address" must be declared.
[error] Element type "addressline" must be declared.
[error] Element type "country" must be declared.
[error] The content of element type "customer" must match "(name,addresses+,email)+".
[error] Element type "destination" must be declared.
[error] Element type "address" must be declared.

Using SAX

SAX stands for Simple API for XML. A SAX parser is event-based. Events are reported through callbacks as the parser moves through the XML document.

This example was compiled and run with JDK1.4, as the APIs and reference implementation are included. If you use a lower JDK version, download JAXP (Java APIs for XML Processing) on http://java.sun.com/xml/jaxp.html.

Main.java:

import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import java.io.*;
 
public class Main 
{
   public static void main(String []args) {
      try {
         SAXParserFactory factory = SAXParserFactory.newInstance();
         SAXParser parser = factory.newSAXParser();
 
         InputSource is = new InputSource(new FileReader("example.xml"));
         parser.parse(is, new MySAXHandler());
      }
      catch(ParserConfigurationException e) {
         e.printStackTrace();
      }
      catch(SAXException e) {
         e.printStackTrace();
      }
      catch(IOException e) {
         e.printStackTrace();
      }        
   }
}
 
class MySAXHandler extends DefaultHandler
{
   int indent = 0;
 
   public void startDocument() throws SAXException {
      System.out.println("startDocument()");
   }
 
   public void endDocument() throws SAXException {
      indent(-3);
      System.out.println("endDocument()");
   }
 
   public void characters(char[] ch, int start, int length)  {
      String s = new String(ch, start, length);
      if (!s.trim().equals("")) {
         indent(0);
         System.out.println(s);
      }
   }
 
   public void ignorableWhitespace(char[] ch, int start, int length) {
      System.out.println("[whitespace]");
   }
 
   public void startElement(String uri, String localName, 
                            String qName, Attributes attributes) {
      indent(3);
      System.out.println("[element " + qName + "]");
      for (int i=0; i<attributes.getLength(); i++) {
         indent(0);
         System.out.println("[Attribute " + attributes.getQName(i) +
                            ", value=" + attributes.getValue(i) + "]");
      }
   }
 
   public void endElement(String uri, String localName, String qName) {
      indent(0);
      System.out.println("[endelement " + qName + "]");
      indent -= 3;
   }
 
   public void indent(int pos) {
      indent += pos;
      for (int i=0; i<indent; i++) {
         System.out.print(" ");
      }
   }
}

example.xml:

<?xml version="1.0"?>
<customer id="C123456">
   <name>Joris Van den Bogaert</name>
   <email>joris1@esus.com</email>
</customer>

output:

startDocument()
   [element customer]
   [Attribute id, value=C123456]
      [element name]
      Joris Van den Bogaert
      [endelement name]
      [element email]
      joris1@esus.com
      [endelement email]
   [endelement customer]
endDocument()