Pretty-Printing Output from Javax.Xml.Transform.Transformer with Only Standard Java API (Indentation and Doctype Positioning)

Indent XML made with Transformer

Try to set indent-amount, AFAIK the default is 0.

trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4")

How to pretty print XML from Java?

Now it's 2012 and Java can do more than it used to with XML, I'd like to add an alternative to my accepted answer. This has no dependencies outside of Java 6.

import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

/**
* Pretty-prints xml, supplied as a string.
* <p/>
* eg.
* <code>
* String formattedXml = new XmlFormatter().format("<tag><nested>hello</nested></tag>");
* </code>
*/
public class XmlFormatter {

public String format(String xml) {

try {
final InputSource src = new InputSource(new StringReader(xml));
final Node document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src).getDocumentElement();
final Boolean keepDeclaration = Boolean.valueOf(xml.startsWith("<?xml"));

//May need this: System.setProperty(DOMImplementationRegistry.PROPERTY,"com.sun.org.apache.xerces.internal.dom.DOMImplementationSourceImpl");

final DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
final DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
final LSSerializer writer = impl.createLSSerializer();

writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); // Set this to true if the output needs to be beautified.
writer.getDomConfig().setParameter("xml-declaration", keepDeclaration); // Set this to true if the declaration is needed to be outputted.

return writer.writeToString(document);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public static void main(String[] args) {
String unformattedXml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><QueryMessage\n" +
" xmlns=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message\"\n" +
" xmlns:query=\"http://www.SDMX.org/resources/SDMXML/schemas/v2_0/query\">\n" +
" <Query>\n" +
" <query:CategorySchemeWhere>\n" +
" \t\t\t\t\t <query:AgencyID>ECB\n\n\n\n</query:AgencyID>\n" +
" </query:CategorySchemeWhere>\n" +
" </Query>\n\n\n\n\n" +
"</QueryMessage>";

System.out.println(new XmlFormatter().format(unformattedXml));
}
}

Java XML Output - proper indenting for child items

If the Transformer implementation you're using is Xalan-J, then you should be able to use:

transformer.setOutputProperty(
"{http://xml.apache.org/xslt}indent-amount", "5");

See also: http://xml.apache.org/xalan-j/usagepatterns.html

how to generate formatted .xml file?

With some guessing and after looking at this question adding these lines
after obtaining the transformer might do the trick

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

Sort xml attributes for pretty print using javax.xml.transform.Transformer

As mentioned, by forty-two, you can make canonical XML from the XML and that will order the attributes alphabetically for you.

In Java we can use something like Apache's Canonicalizer

org.apache.xml.security.c14n.Canonicalizer

Something like this (assuming that the Document inXMLDoc is already a DOM):

Document retDoc;
byte[] c14nOutputbytes;
DocumentBuilderFactory factory;
DocumentBuilder parser;

// CANONICALIZE THE ORIGINAL DOM
c14nOutputbytes = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(inXMLDoc.getDocumentElement());

// PARSE THE CANONICALIZED BYTES (IF YOU WANT ANOTHER DOM) OR JUST USE THE BYTES
factory = DocumentBuilderFactory.newInstance();
factory.set ... // SETUP THE FACTORY
parser = factory.newDocumentBuilder();
// REPARSE TO GET ANOTHER DOM WITH THE ATTRIBUTES IN ALPHA ORDER
ByteArrayInputStream bais = new ByteArrayInputStream(c14nOutputbytes);
retDoc = parser.parse(bais);

Other things will get changed when Canonicalizing of course (it will become Canonical XML http://en.wikipedia.org/wiki/Canonical_XML) so just expect some changes other than the attribute order.

Creating XML only printing to one line

I use

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

Which seems to work just fine.

Coldfusion wddx with indentation

I don't think ColdFusion natively supports indenting xml/wddx. So either you can use xmlindent from cflib.org or if you are comfortable with java there are many solutions available see this thread like

Transformer transformer = TransformerFactory.newInstance().newTransformer();
// indent and omit xml declaration
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
return result.getWriter().toString();

Remove !DOCTYPE from output of property.storeToXML

Like most of the Properties class, you can't change it. Instead, capture the XML string produced, modify it, then send it out manually.

property.put("xyz", "serverpath");
property.put("*abc", "serverIPAddress");
ByteArrayOutputStream out = new ByteArrayOutputStream();
property.storeToXML(out, null, "UTF-8");
String str = out.toString("UTF-8").replaceAll("<!DOCTYPE[^>]*>\n", "");
byte[] bytes = str.getBytes("UTF-8");
OutputStream outs = response.getOutputStream();
outs.write(bytes, 0, bytes.length);
outs.close();

FYI ByteArrayOutputStream is an in-memory output stream you can use to capture and retrieve what was written to it. Because a Properties object is in practice not going to have many entries, this approach does not pose a memory consumption risk.



Related Topics



Leave a reply



Submit