0

XML Parsed/Serialized as [#document: null]

It’s a huge annoyance when you’re working with XML and after parsing the web service’s XML or deserializing the XML from BlazeDS, you see in your debugger that the output is [#document: null]. When I was still fresh out of the woods, I thought that [#document: null] is null, but as it turns out, it isn’t. The toString() method on the Document object is trying to communicate that the Document’s root element’s “node value” is not defined. Unfortunately, it chooses to represent that as [#document: null], which is just plain confusing.

If I’d read the Node documentation earlier, which states clearly that for the Document interface, the nodeName is “#document” and the nodeValue is null, it would have saved me many hours of frustration. If the XML API you’re working with returns you this output, you’d have to recurse through all the nodes and build the XML yourself. One way of avoiding this is to use JDOM:

import java.io.StringWriter;
import java.io.IOException;
import org.jdom.*;
import org.jdom.output.*;
import org.jdom.input.*;

public String buildXML(org.w3c.dom.Document xmlDoc) throws IOException
{
    xmlDoc.getDocumentElement().normalize();
    DOMBuilder domBuilder = new DOMBuilder();
    Document jdomDocument = domBuilder.build(xmlDoc);
    XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
    StringWriter stringWriter = new StringWriter();
    xmlOutputter.output(jdomDocument, stringWriter);
    String xmlString = stringWriter.toString();
    return xmlString;
}
0

Building XML strings in Java

I had to build relatively simple XML strings from user input recently in a project and was trying to come up with a beautiful, elegant solution to do it. Naturally, manual string concatenation was out. It’s messy, brittle, and basically a nightmare to maintain. My next alternative was XMLBeans but I rejected as it was too heavyweight. I didn’t need to register a schema and it was simply too inefficient and a huge overkill to use XMLBeans to generate a straightforward XML string due to the amount of boilerplate required.

Another consideration was that I wanted to build the string in the style of fluent interfaces, such that one could simply tell if the string was well formed simply by eyeballing it. I thought of using VTD-XML, which was the XML parser being used in the project, but I couldn’t find any XML building capabilities, only parsing ones. I then settled on JDom as I’ve used it before as well as a new kid on the block, java-xmlbuilder (uses JAXP internally to build the DOM). With that, let’s see some code!

JDom version:

Element orderXml= new Element("ORDER").addContent(new Element
							("ORDER_DETAILS").addContent(new Element
									("ORDER_ID").setText(
										"123"))).addContent(new Element
							("SHOP_DETAILS").addContent(new Element
									("SHOP_TYPE").setText
										("ONLINE")).addContent(new Element
									("SHOP_COUNTRY").setText
										("SG")));

XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
StringWriter stringWriter = new StringWriter();
xmlOutputter.output(new Document(orderXml), stringWriter);
System.out.println(stringWriter.toString());

// JDom output
<?xml version="1.0" encoding="UTF-8"?>
<ORDER>
  <ORDER_DETAILS>
    <ORDER_ID>123</ORDER_ID>
  </ORDER_DETAILS>
  <SHOP_DETAILS>
    <SHOP_TYPE>ONLINE</SHOP_TYPE>
    <SHOP_COUNTRY>SG</SHOP_COUNTRY>
  </SHOP_DETAILS>
</ORDER>

java-xmlbuilder version:

XMLBuilder xmlBuilder =
			XMLBuilder.create("ORDER")
								.e("ORDER_DETAILS")
									.e("ORDER_ID")
										.t("123")
									.up()
								.up()
								.e("SHOP_DETAILS")
									.e("SHOP_TYPE")
										.t("ONLINE")
									.up()
									.e("SHOP_COUNTRY")
										.t("SG");

Properties outputProperties = new Properties();
outputProperties.put(javax.xml.transform.OutputKeys.INDENT, "yes");
outputProperties.put("{http://xml.apache.org/xslt}indent-amount", "2");
System.out.println(xmlBuilder.asString(outputProperties));

// java-xmlbuilder output
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ORDER>
  <ORDER_DETAILS>
    <ORDER_ID>123</ORDER_ID>
  </ORDER_DETAILS>
  <SHOP_DETAILS>
    <SHOP_TYPE>ONLINE</SHOP_TYPE>
    <SHOP_COUNTRY>SG</SHOP_COUNTRY>
  </SHOP_DETAILS>
</ORDER>

Needless to say, I decided to use java-xmlbuilder as I found it more readable and also, it’s more easier to write code in the style of fluent interfaces with it. With JDom, I had to really pay attention to the indentation and bracketing as the correct visual position of the elements do not necessarily mean that your XML is well-formed. Get the order of your method calls and your closing brackets mixed up and even though it looks right, the resulting string will be malformed.

For java-xmlbuilder, coding in the style of fluent interfaces comes naturally due to the API and the brackets are simple to match up. The really cool thing about this is that once you have finished adding items to a new element, you can call the up() method to retrieve the XMLBuilder node that represents the parent of the current node. If you balance every call to element() with a call to up(), you can write code that closely resembles the structure of the XML document you are creating.

Verdict: java-xmlbuilder