views:

373

answers:

6

What are the ways of producing XML in Java?

Simple question, multiple answers possible.

I'd like a small discussion about the pros and cons of the various methods, as it seems the current community's opinion is very focused: any way but not with println(). Why? Can you explain it?

To make my question more community wiki, I'd also like to see code examples about the ways (not for myself) as the question itself is a reoccurring pattern here on SO.

A: 

Really depends on what the XML is representing, i.e. does it need to be generated from your object model or do you need more of a template based approach.

If you want your xml to come from your object model then I would suggest jibx as the performance is amazing.

karl

Karl
+1  A: 

Why not println?

  • You should use something tag-aware, so that element nesting is handled properly.
  • You should use something aware of the escaping rules, and how they understand how to escape inside of text data, attributes, comments, and CDATA sections, since each has different escaping rules.
  • You should use something aware of the encoding issues, so that the header is set properly to match the actual content.

Just about every representation of XML has a way to serialize. DOM, XOM, etc. all have serializers that have these issues worked out.

lavinio
A: 

A useful middle ground between string dumping and object serialization is a "smart println" -- it encapsulates concepts like 'element', 'attribute', and 'cdata', opening and closing tags, and also takes care of encoding issues. See XmlWriter for an example.

Chris Winters
A: 

Luckily, XML frameworks do it automagically, without a single println() or write() to a stream. So you won't find things such as this:

PrintWriter out = new PrintWriter(new OutputStreamWriter(
    new FileOutputStream("data.xml"), "UTF-8"), false);
out.printf("<?xml version='1.0' encoding='UTF-8'?>%n");
out.printf("<properties>%n");
out.printf("    <entry key='%s'>%s</entry>%n", toXML("Q&A'"), toXML("<<<---"));
out.printf("</properties>%n");
out.flush();
out.close();

String toXML(String s) {
    return s == null ? "" : s.replaceAll("&", "&amp;")
    .replaceAll("'", "&apos;").replaceAll("<", "&lt;")
    .replaceAll("\"", "&quot;");
}
kd304
+2  A: 

Here are some ways to emit well-formed XML using the Java 6 API.

Use LSSerializer:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element foo = doc.createElement("foo");
doc.appendChild(foo);

DOMImplementationLS lsImpl = (DOMImplementationLS) doc
    .getImplementation();
LSOutput lsOut = lsImpl.createLSOutput();
lsOut.setByteStream(System.out);
LSSerializer lsSerializer = lsImpl.createLSSerializer();
lsSerializer.write(doc, lsOut);

This assumes your DOM parser implementation implements DOMImplementationLS.

Use a Transformer:

TransformerFactory tFactory = TransformerFactory
    .newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.transform(new DOMSource(doc),
    new StreamResult(System.out));

Since the transformation API accepts a wide range of input and result types, this is probably the most flexible approach.

Another approach is to use the StAX API (see XMLStreamWriter and XMLEventWriter):

XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter streamWriter = xmlOutputFactory
    .createXMLStreamWriter(System.out);
streamWriter.writeStartDocument();
streamWriter.writeStartElement("foo");
streamWriter.writeEndElement();
streamWriter.writeEndDocument();
streamWriter.flush();

Using JAXB to marshal objects:

@XmlRootElement
class Foo {
}
JAXB.marshal(new Foo(), System.out);

I'm sure there are plenty of other ways to do this both in the Java 6 and in the numerous 3rd party Java XML APIs.

McDowell
Thank you for the code samples.
kd304
Wow thanks. I wasn't aware of the LSSerializer.
kd304
+1  A: 

I recommend Java 6's XMLStreamWriter interface (found in the javax.xml.stream package). I believe it can also be found in the Java EE 5 library.

Pros include:

  • Included in the standard library
  • Low overhead (does not maintain a DOM tree)

Cons include:

  • Requires Java 6

Here is a sample of writing some XHTML:

OutputStream outputStream = ...;
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(outputStream);

xml.writeStartDocument();
xml.writeDefaultNamespace("http://www.w3.org/1999/xhtml");

xml.writeStartElement("html");
xml.writeStartElement("body");
xml.writeCharacters("The less-than (<) and greater-than (>) characters are automatically escaped for you");
xml.writeEndElement(); // </body>
xml.writeEndElement(); // </html>

xml.writeEndDocument();
Adam Paynter