Pretty-printing output from javax.xml.transform.Transformer with only standard java api (Indentation and Doctype positioning)

Alderath picture Alderath · Aug 12, 2009 · Viewed 83.2k times · Source

Using the following simple code:

package test;

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class TestOutputKeys {
    public static void main(String[] args) throws TransformerException {

        // Instantiate transformer input
        Source xmlInput = new StreamSource(new StringReader(
                "<!-- Document comment --><aaa><bbb/><ccc/></aaa>"));
        StreamResult xmlOutput = new StreamResult(new StringWriter());

        // Configure transformer
        Transformer transformer = TransformerFactory.newInstance()
                .newTransformer(); // An identity transformer
        transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "testing.dtd");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.transform(xmlInput, xmlOutput);

        System.out.println(xmlOutput.getWriter().toString());
    }

}

I get the output:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Document comment --><!DOCTYPE aaa SYSTEM "testing.dtd">

<aaa>
<bbb/>
<ccc/>
</aaa>

Question A: The doctype tag appears after the document comment. Is it possible to make it appear before the document comment?

Question B: How do I achieve indentation, using only the JavaSE 5.0 API? This question is essentially identical to How to pretty-print xml from java, however almost all answers in that question depend on external libraries. The only applicable answer (posted by a user named Lorenzo Boccaccia) which only uses java's api, is basically equal to the code posted above, but does not work for me (as shown in the output, i get no indentation).

I am guessing that you have to set the amount of spaces to use for indentation, as many of the answers with external libraries do, but I just cannot find where to specify that in the java api. Given the fact that the possibility to set an indentation property to "yes" exists in the java api, it must be possible to perform indentation somehow. I just can't figure out how.

Answer

Rich Seller picture Rich Seller · Aug 12, 2009

The missing part is the amount to indent. You can set the indentation and indent amount as follow:

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