JAXB marshalling - String XML pretty-print not working on all objects of generic type org.w3c.dom.Element

Viewed 20

I have a JAXB pojo that sometimes contain a generic org.w3c.dom.Element.

Such element is contained inside the following class:

@XmlRootElement(name = "businessObject")
@XmlAccessorType(XmlAccessType.PROPERTY)
public final class BusinessObjectWrapper {

    @XmlJavaTypeAdapter(value = PureXmlElementAdapter.class)
    @XmlAnyElement(lax = true)
    private Object xmlElementHolder;

}

... which is itself contained into some other classes that all end up into my main pojo MxML.

When the marshal method of the PureXmlElementAdapter.class is called to marshal the content, the following code is executed:

Element v = this.element;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
NodeList childNodes = v.getChildNodes();
for (int j = 1; j < (childNodes.getLength() - 1); j++) {
    Node node = document.importNode(childNodes.item(j), true);
    document.appendChild(node);
}
return document.getDocumentElement();

Now, what happens is that if I try to print into a string the document that I create using the following function:

public static String fromXmlDocument(Document document, Charset encoding) throws TransformerException {
    try(StringBuilderWriter sw = new StringBuilderWriter()) {
        Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        transformer.setOutputProperty(OutputKeys.ENCODING, encoding.name());
        transformer.transform(new DOMSource(document), new StreamResult(sw));
        return sw.toString();
    }
}

... I end up with an XML document which is properly formatted.

However, when I try to build an XML string out of my MxML object using this code:

JAXBContext JAXB_CONTEXT = JAXBContext.newInstance(MxML.class, BusinessObjectWrapper.class);
Marshaller jaxbMarshaller = JAXB_CONTEXT.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter stringWriter = new StringWriter();
jaxbMarshaller.marshal(this, stringWriter); //this is the instance of MxML
return stringWriter.toString();

... then what happens is that the output XML string is properly formatted, except for the org.w3c.dom.Element that I returned in my marshal call just above that looks like containing one new extra line for each line:

<MxML>
   <something>
      <somethingOk>
         <item nb="1">2.3</item>
         <item nb="2">2.4</item>
      </somethingOk>
      <somethingElse>
         <businessObject>
            <someElement>

               <someOtherElement>

                  <item nb="1">2.3</item>

                  <item nb="2">2.4</item>

    </someOtherElement>

</someElement>
         </businessObject>
      </somethingElse>
   </something>
</MxML>

So to sum-up, the marshaling of the whole MxML class done by JAXB is:

  • Clean on all the objects that are proper JAXB pojo classes
  • On all the opening tags of the nested org.w3c.dom.Element, I end up with proper indentation but unexpected new lines
  • On all the closing tags of the nested org.w3c.dom.Element, not only I have unexpected new lines but I also lose indentation (as it seems the indentation is respected across closing elements but overall it restarts from the root level of the document)

I really don't know how to print this XML properly as I don't see any difference between what I do using the Transformer and what JAXB may be doing behind the scenes.

Does anyone know how could I get the proper output please?

0 Answers
Related