Java:如何缩进由Transformer生成的XML


112

我正在使用Java的内置XML转换器来获取DOM文档并打印出结果XML。问题在于,尽管已显式设置参数“ indent”,但根本不缩进文本。

样例代码

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()));

 }
}

结果

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

理想的结果

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

有什么想法吗?

Answers:


215

您需要启用“ INDENT”并设置变压器的缩进量:

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

更新:


参考:如何在序列化之前从DOM中删除纯空白文本节点?

(非常感谢所有成员,尤其是@ marc-novakowski,@ james-murty和@saad)


70
在我看来,默认缩进为0似乎很愚蠢,但除了INDENT=yes我,我还必须添加以下内容:t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
lapo 2011年

1
谨防。此缩进属性在Java 5中不起作用。在Java 7中
不起作用。Java

4
如果内部节点有多行,您是否也可以缩进内部部分?只使用它不会缩进内部节点。
eipark

1
@eipark与stackoverflow.com/a/979606/837530,我删除了空格,现在缩进就像一个魅力
萨阿德

1
@lapo,如果您的提供者是xalan(如果可行,则可能是这样),那么它的org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
格式

21

所建议的解决方案都不适合我。因此,我一直在寻找替代解决方案,该解决方案最终是前面提到的两者和第三步的结合。

  1. 将缩进号设置为变形工厂
  2. 启用缩进变压器
  3. 用writer(或bufferedwriter)包装otuputstream
//(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"));

您必须执行(3)来解决xml处理代码的“笨拙”行为。

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

(如果我引用的来源有误,请告诉我)


3
最后一行中的“输出”是什么?
mujimu 2011年

您是否需要使用构造函数创建新的整数?
Benjineer

我猜是因为您的提供者不是Xalan。您能检查一下自己TransformerFactory实际是什么,以便其他人知道。
OrangeDog

步骤3(使用a Writer作为输出)至关重要。
erickson

14

以下代码在Java 7中对我有效。我在转换器(不是转换器工厂)上设置了缩进(是)和缩进量(2),以使其正常工作。

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设置属性的解决方案对我不起作用,但事实证明@lapo的评论很有帮助。


8

导入com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory

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

这是一个内部类,因此您的代码将无法移植到其他(甚至更新的)JVM中。
OrangeDog

5

如果要缩进,则必须将其指定为TransformerFactory

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

4

我使用Xerces(Apache)库而不是与Transformer搞混。添加库后,添加以下代码。

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);

是。我尝试了其他所有方法使用Transformer,但都失败了。整个W3C库都是一团糟。Xerces工作了。
调谐的'17

3

对我来说,添加DOCTYPE_PUBLIC工作:

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

Transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,“是”); 是关键
–silentsudo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.