106

What is the easiest way to pretty print (a.k.a. formatted) a org.w3c.dom.Document to stdout?

DwB
  • 33,855
  • 10
  • 50
  • 78
flybywire
  • 232,954
  • 184
  • 384
  • 491

6 Answers6

189

Call printDocument(doc, System.out), where that method looks like this:

public static void printDocument(Document doc, OutputStream out) throws IOException, TransformerException {
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

    transformer.transform(new DOMSource(doc), 
         new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}

(The indent-amount is optional, and might not work with your particular configuration)

Marco Lackovic
  • 4,522
  • 4
  • 38
  • 46
Bozho
  • 554,002
  • 136
  • 1,025
  • 1,121
  • 65
    Isn't it ironic that that's the "easiest" way to simply print an XML document in Java? – Thomas Jan 07 '11 at 13:37
  • 7
    on the other hand you have plenty of control ;) – Bozho Jan 07 '11 at 15:29
  • 2
    Brilliant! And yes, it is a bit much text but it is crystal clear what the selected options are and Eclipse/Netbeans really help you write this. Show me a smaller version and I tell you what it cannot do. Worse, I will tell you where you need 3 debugging rounds to get it right ... – Peter Kriens Mar 11 '13 at 12:52
  • 4
    I swear to god Java.. make me write ridiculous number of lines of code for something that can be done in one or two in other languages... with full control too.. – l46kok Jun 16 '13 at 15:54
  • But if your XML contains astral characters, and you are using Xalan, note https://issues.apache.org/jira/browse/XALANJ-2419 and see also http://stackoverflow.com/a/11987283/1031689 – JasonPlutext Aug 24 '15 at 07:07
  • If you are seeing unexpected newlines in the output, take a look at https://stackoverflow.com/a/33541820/415404 – Gus Apr 19 '20 at 04:28
12

How about:

OutputFormat format = new OutputFormat(doc);
format.setIndenting(true);
XMLSerializer serializer = new XMLSerializer(System.out, format);
serializer.serialize(doc);
informatik01
  • 15,174
  • 9
  • 67
  • 100
Dennis
  • 121
  • 1
  • 2
8

Try jcabi-xml with one liner:

String xml = new XMLDocument(document).toString();

This is the dependency you need:

<dependency>
  <groupId>com.jcabi</groupId>
  <artifactId>jcabi-xml</artifactId>
  <version>0.14</version>
</dependency>
yegor256
  • 93,933
  • 106
  • 409
  • 558
4
private void printNode(Node rootNode, String spacer) {
    System.out.println(spacer + rootNode.getNodeName() + " -> " + rootNode.getNodeValue());
    NodeList nl = rootNode.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++)
        printNode(nl.item(i), spacer + "   ");
}
Robert Harvey
  • 168,684
  • 43
  • 314
  • 475
hannes
  • 57
  • 1
  • 1
    I appreciate that the Q asks for the shortest, but (for the benefit of anyone else) perhaps you could elaborate your answer to explain what's going on? – Andrew Oct 26 '12 at 05:29
  • html -> head -> meta -> title -> body -> If I place a space of string as the spacer above is the result is what I get. Is it what its intended to do? A full print of the XML is what is needed I think when it meants pretty printed. – jeraldfdo Feb 28 '19 at 02:58
0

This will return a nicely formated output by using recursive descent/ascent.

private static boolean skipNL;
private static String printXML(Node rootNode) {
    String tab = "";
    skipNL = false;
    return(printXML(rootNode, tab));
}
private static String printXML(Node rootNode, String tab) {
    String print = "";
    if(rootNode.getNodeType()==Node.ELEMENT_NODE) {
        print += "\n"+tab+"<"+rootNode.getNodeName()+">";
    }
    NodeList nl = rootNode.getChildNodes();
    if(nl.getLength()>0) {
        for (int i = 0; i < nl.getLength(); i++) {
            print += printXML(nl.item(i), tab+"  ");    // \t
        }
    } else {
        if(rootNode.getNodeValue()!=null) {
            print = rootNode.getNodeValue();
        }
        skipNL = true;
    }
    if(rootNode.getNodeType()==Node.ELEMENT_NODE) {
        if(!skipNL) {
            print += "\n"+tab;
        }
        skipNL = false;
        print += "</"+rootNode.getNodeName()+">";
    }
    return(print);
}
Mark
  • 33
  • 2
-1

if you use dom4j, it would be dom4JDOM.asString()

Rockoder
  • 706
  • 2
  • 9
  • 20