Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Since moving to java 1.7 Xml Document Element does not indent

I'm trying to indent XML which generated by Transformer. All the DOM Node are being Indent as expected except for the First Node - The Document Element. document element does not start in a new line , just concat right after the XML Declaration.

This bug arise when I moved to java 1.7 , when using java 1.6 or 1.5 it does not happen.

My code :

ByteArrayOutputStream s = new OutputStreamWriter(out, "utf-8");

TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");

transformer.transform(new DOMSource(doc), new StreamResult(s));

The output:

<?xml version="1.0" encoding="UTF-8"?><a>
       <b>bbbbb</b>
 </a>

Anyone knows why ?

btw, when I add the property

transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");

It work as expected , but the xml declaration is changed, it now have the standalone property as well, and i don't want to change the xml declaration..

like image 420
john Smith Avatar asked Aug 15 '13 09:08

john Smith


3 Answers

Ok ,

I found in Java API this :

If the doctype-system property is specified, the xml output method should output a document type declaration immediately before the first element.

SO I used this property

 transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");

and it solve my problem with out changed my xml declartion.

Thanks.

like image 111
john Smith Avatar answered Oct 30 '22 08:10

john Smith


Xalan has at some point changed the behavior regarding the newline character after the XML declaration.

OpenJDK (and thus Oracle JDK, too) has implemented a workaround for this problem. This workaround can be enabled by setting a special property on the Transformer object:

try {
    transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
} catch (IllegalArgumentException e) {
    // Might be thrown by JDK versions not implementing the workaround.
} 

This way, the old behavior (printing a newline character after the XML declaration) is restored without adding the standalone attribute to the XML declaration.

like image 24
Sebastian Marsching Avatar answered Oct 30 '22 06:10

Sebastian Marsching


For me writing the XML declaration to the Writer or OutputStream before writing the XML and telling the transformer to omit declaration was the only thing that worked. The only other solution to preserve the spacing appears to be VTD-XML library.

    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"").append(doc.getXmlVersion()).append("\"");
    sb.append(" encoding=\"").append(doc.getXmlEncoding()).append("\"");
    if (doc.getXmlStandalone()) {
        sb.append(" standalone=\"").append("" + doc.getXmlStandalone()).append("\"");
    }
    sb.append("?>").append("\n");

    writer.write(sb.toString());
            TransformerFactory tf = TransformerFactory.newInstance();
    try {
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    }
    catch (Exception e)  {
    //snipped out for brevity
    }
like image 23
Adam Gent Avatar answered Oct 30 '22 06:10

Adam Gent