由于迁移到java 1.7 Xml文档元素不会缩进

时间:2013-08-15 09:04:40

标签: java xml parsing dom transform

我正在尝试缩进由Transformer生成的XML。 除了第一个节点 - 文档元素之外,所有DOM节点都按预期缩进。 document元素不会以新行开头,只是在XML声明之后立即生成。

当我转移到java 1.7时会出现这个错误,当使用java 1.6或1.5时,它不会发生。

我的代码:

ByteArrayOutputStream s = new OutputStreamWriter(out, "utf-8");

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

transformer.transform(new DOMSource(doc), new StreamResult(s));

输出:

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

任何人都知道为什么?

顺便说一句, 当我添加属性

transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");

它按预期工作,但xml声明已更改, 它现在也有独立属性,我不想更改xml声明..

4 个答案:

答案 0 :(得分:10)

好的,

我在Java API中找到了这个:

如果指定了doctype-system属性,则xml输出方法应在第一个元素之前输出文档类型声明。

所以我使用了这个属性

 transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");

它解决了我的问题,改变了我的xml声明。

感谢。

答案 1 :(得分:1)

Xalan在某些时候改变了XML声明后换行符的行为。

OpenJDK(以及Oracle JDK)也针对此问题实施了workaround。可以通过在Transformer对象上设置特殊属性来启用此变通方法:

try {
    transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
} catch (IllegalArgumentException e) {
    // Might be thrown by JDK versions not implementing the workaround.
} 

这样就恢复了旧的行为(在XML声明之后打印换行符),而没有将独立属性添加到XML声明中。

答案 2 :(得分:1)

我在编写XML之前将XML声明写入WriterOutputStream并告诉变换器省略声明是唯一有效的方法。保留间距的唯一其他解决方案似乎是VTD-XML库。

    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"").append(doc.getXmlVersion()).append("\"");
    sb.append(" encoding=\"").append(doc.getXmlEncoding()).append("\"");
    if (doc.getXmlStandalone()) {
        sb.append(" standalone=\"").append("" + doc.getXmlStandalone()).append("\"");
    }
    sb.append("?>").append("\n");

    writer.write(sb.toString());
            TransformerFactory tf = TransformerFactory.newInstance();
    try {
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    }
    catch (Exception e)  {
    //snipped out for brevity
    }

答案 3 :(得分:0)

这似乎是Java中XML实现的一个问题(bug)。在XML声明之后获取换行符的唯一方法是显式指定standalone属性。您可以将其设置为no,这是隐式默认值,即使它在不使用DTD时完全无关紧要。