JAXB marshals XML differently to OutputStream vs. StringWriter JAXB marshals XML differently to OutputStream vs. StringWriter xml xml

JAXB marshals XML differently to OutputStream vs. StringWriter


Looks like this might be a "bug" in JAXB. Looking at the source, the calls for marshal() create different writers based on the output/writer type parameter:

public void marshal(Object obj, OutputStream out, NamespaceContext inscopeNamespace) throws JAXBException {    write(obj, createWriter(out), new StAXPostInitAction(inscopeNamespace,serializer));}public void marshal(Object obj, XMLStreamWriter writer) throws JAXBException {    write(obj, XMLStreamWriterOutput.create(writer,context), new StAXPostInitAction(writer,serializer));}

The implementations of the writers is different with regards to how they handle "empty elements". The above code is from:

jaxb-ri\runtime\src\com\sun\xml\bind\v2\runtime\MarshallerImpl.java.

The two writers you are creating are:

jaxb-ri\runtime\src\com\sun\xml\bind\v2\runtime\output\UTF8XmlOutput.java

jaxb-ri\runtime\src\com\sun\xml\bind\v2\runtime\output\XMLStreamWriterOutput.java


The good news is that JAXB is a specification with more than one implementation (just like JPA). If one implementation is not meeting your needs, others are available such as EclipseLink JAXB (MOXy):


I don't know why JAXB is doing this - or even if it is JAXB - if JAXB is outputting XML via a SAXContentHandler for example, then it has no direct control over how close tags are produced.

To get consistent behaviour, you could wrap your OutputStream in a OutputStreamWriter, e.g.

   public void marshal(Marshalable obj, OutputStream os) throws XMLMarshalException {        try {            marshaller.marshal(obj, new OutputStreamWriter(os, "UTF-8"));        } catch (JAXBException jaxbe) {            throw new XMLMarshalException(jaxbe);        }    }

Along the same lines, you might see what happens if you wrap the StringWriter in a PrintWriter. Maybe there is some custom code that detects StringWriter to tries to keep the output short as possible. Sounds unlikely, but I have no other explanation.