【问题标题】:Java: How to Indent XML Generated by TransformerJava:如何缩进 Transformer 生成的 XML
【发布时间】:2010-11-25 23:14:58
【问题描述】:

我正在使用 Java 的内置 XML 转换器来获取 DOM 文档并打印出生成的 XML。问题在于,尽管明确设置了参数“缩进”,但它根本没有缩进文本。

示例代码

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>

想法?

【问题讨论】:

    标签: java xml transform indentation


    【解决方案1】:

    您需要启用 'INDENT' 并​​为转换器设置缩进量:

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

    更新:


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

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

    【讨论】:

    • 默认缩进为 0 对我来说似乎很愚蠢,但除了 INDENT=yes 我还必须添加:t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
    • 当心。这个缩进属性在 java 5 中不起作用。它在 java 7 中起作用。在 java 6 中没有尝试过
    • 如果内部节点是多行的,你也可以缩进内部部分吗?仅使用它不会缩进内部节点。
    • 我遇到了@eipark 可能提到的类似问题。我正在将一个普通的 XML 字符串转换为一个节点,然后使用转换器来缩进它。我的纯字符串包含空格,并且缩进似乎不起作用(鉴于上述建议)。在转换为 Node 之前,我会尝试删除空格,也许这样会起作用。
    • @lapo 如果您的提供者是 xalan(如果可行的话,它可能是),那么它可以作为 org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
    【解决方案2】:

    建议的解决方案都不适合我。所以我一直在寻找替代解决方案,最终成为了前面提到的两者和第三步的混合。

    1. 在transformerfactory中设置缩进数
    2. 在转换器中启用缩进
    3. 使用写入器(或缓冲写入器)包装 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

    (如果我错误地引用了我的来源,请告诉我)

    【讨论】:

    • 我猜是因为您的提供商不是 Xalan。你能检查一下你的TransformerFactory实际上是什么让其他人知道。
    • 第 3 步,使用 Writer 作为输出,是必不可少的。
    【解决方案3】:

    以下代码适用于 Java 7。我在转换器(不是转换器工厂)上设置了缩进 (yes) 和缩进量 (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 的评论证明很有帮助。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 这是一个内部类,因此您的代码将无法移植到其他(甚至更新的)JVM。
      【解决方案5】:

      如果你想要缩进,你必须将它指定给TransformerFactory

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

      【讨论】:

        【解决方案6】:

        我使用 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 奏效了。
        【解决方案7】:

        对我来说添加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,"yes");是关键
        猜你喜欢
        • 1970-01-01
        • 2011-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-31
        相关资源
        最近更新 更多