Java: How to Indent XML Generated by Transformer

JavaXmlTransformIndentation

Java Problem Overview


I'm using Java's built in XML transformer to take a DOM document and print out the resulting XML. The problem is that it isn't indenting the text at all despite having set the parameter "indent" explicitly.

sample code

public class TestXML {
 
 public static void main(String args[]) throws Exception {
  ByteArrayOutputStream s;
  
  Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
  Transformer t = TransformerFactory.newInstance().newTransformer();
  
  Element a,b;
  
  a = d.createElement("a");
  b = d.createElement("b");
  
  a.appendChild(b);
  
  d.appendChild(a);
  
  t.setParameter(OutputKeys.INDENT, "yes");
  
  s = new ByteArrayOutputStream();
  
  t.transform(new DOMSource(d),new StreamResult(s));
  
  System.out.println(new String(s.toByteArray()));
  
 }
}

result

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

desired result

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

Thoughts?

Java Solutions


Solution 1 - Java

You need to enable 'INDENT' and set the indent amount for the transformer:

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

Update:


Reference : How to strip whitespace-only text nodes from a DOM before serialization?

(Many thanks to all members especially @marc-novakowski, @james-murty and @saad):

Solution 2 - Java

Neither of the suggested solutions worked for me. So I kept on searching for an alternative solution, which ended up being a mixture of the two before mentioned and a third step.

  1. set the indent-number into the transformerfactory
  2. enable the indent in the transformer
  3. wrap the otuputstream with a writer (or bufferedwriter)

//(1)
TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));

//(2)
Transformer t = tf.newTransformer();
t.setOutputProperty(OutputKeys.INDENT, "yes");

//(3)
t.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "utf-8"));

You must do (3) to workaround a "buggy" behavior of the xml handling code.

Source: johnnymac75 @ http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

(If I have cited my source incorrectly please let me know)

Solution 3 - Java

The following code is working for me with Java 7. I set the indent (yes) and indent-amount (2) on the transformer (not the transformer factory) to get it working.

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

@mabac's solution to set the attribute didn't work for me, but @lapo's comment proved helpful.

Solution 4 - Java

import com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory

transformer.setOutputProperty(OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2");

Solution 5 - Java

If you want the indentation, you have to specify it to the TransformerFactory.

TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute("indent-number", new Integer(2));
Transformer t = tf.newTransformer();

Solution 6 - Java

I used the Xerces (Apache) library instead of messing with Transformer. Once you add the library add the code below.

OutputFormat format = new OutputFormat(document);
format.setLineWidth(65);
format.setIndenting(true);
format.setIndent(2);
Writer outxml = new FileWriter(new File("out.xml"));
XMLSerializer serializer = new XMLSerializer(outxml, format);
serializer.serialize(document);

Solution 7 - Java

For me adding DOCTYPE_PUBLIC worked:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMikeView Question on Stackoverflow
Solution 1 - JavaKV PrajapatiView Answer on Stackoverflow
Solution 2 - JavamabacView Answer on Stackoverflow
Solution 3 - JavaremipodView Answer on Stackoverflow
Solution 4 - Javauser2660852View Answer on Stackoverflow
Solution 5 - JavalucbelangerView Answer on Stackoverflow
Solution 6 - JavasevensevensView Answer on Stackoverflow
Solution 7 - JavaVikas ChowdhuryView Answer on Stackoverflow