【问题标题】:Java 1.6: javax.xml.transform.Transformer refuses to indent xml strings which contain newlinesJava 1.6:javax.xml.transform.Transformer 拒绝缩进包含换行符的 xml 字符串
【发布时间】:2011-10-19 23:42:00
【问题描述】:

我需要能够使用 Java API 漂亮地打印 xml 字符串,并且在 Web 和这个特定网站上找到了多种解决方案。然而,尽管多次尝试让它与 javax.xml.transform.Transformer 一起工作,但到目前为止它一直是失败的。 我在下面提供的代码仅在参数中的 xml 字符串不包含 xml 元素之间的任何换行符时部分起作用。这是行不通的。我需要能够漂亮地打印任何东西,假设它是格式良好且有效的 xml,甚至是以前漂亮的打印字符串。

我得到了这个(从我找到的代码 sn-ps 拼凑而成,人们声称它对他们有用):

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class XMLFormatter {

    public static String format(String xml, int indent, boolean omitXmlDeclaration)
            throws TransformerException {

        if (indent < 0) {
            throw new IllegalArgumentException();
        }
        String ret = null;
        StringReader reader = new StringReader(xml);
        StringWriter writer = new StringWriter();
        try {
            TransformerFactory factory = TransformerFactory.newInstance();
            factory.setAttribute("indent-number", new Integer(indent));
            Transformer transformer = factory.newTransformer();
            if (omitXmlDeclaration) {
                transformer.setOutputProperty(
                        OutputKeys.OMIT_XML_DECLARATION, "yes");
            }
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(
                    "{http://xml.apache.org/xslt}indent-amount",
                    String.valueOf(indent));
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.transform(
                    new StreamSource(reader),
                    new StreamResult(writer));
            ret = writer.toString();
        } catch (TransformerException ex) {
            throw ex;
        } finally {
            if (reader != null) {
                reader.close();
            }
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException ex) {}
        }

        return ret;
    }

    public static void main(String[] args) throws TransformerException {
        StringBuilder sb = new StringBuilder();
        sb.append("<rpc-reply><data><smth/></data></rpc-reply>");

        System.out.println(sb.toString());
        System.out.println();
        System.out.println(XMLFormatter.format(sb.toString(), 4, false));

        final String NEWLINE = System.getProperty("line.separator");
        sb.setLength(0);
        sb.append("<rpc-reply>");sb.append(NEWLINE);
        sb.append("<data>");sb.append(NEWLINE);
        sb.append("<smth/>");sb.append(NEWLINE);
        sb.append("</data>");sb.append(NEWLINE);
        sb.append("</rpc-reply>");

        System.out.println(sb.toString());
        System.out.println();
        System.out.println(XMLFormatter.format(sb.toString(), 4, false));
    }
}

这段代码不应该被那些换行符所困扰,不是吗?这是一个错误还是我在这里遗漏了一些重要的东西?代码 sn-p 的输出:

<rpc-reply><data><smth/></data></rpc-reply>

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply>
    <data>
        <smth/>
    </data>
</rpc-reply>

<rpc-reply>
<data>
<smth/>
</data>
</rpc-reply>

<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply>
<data>
<smth/>
</data>
</rpc-reply>

据我所知,我的代码与其他示例的不同之处在于我使用 StringWriter 和 StringReader 作为 transform(in, out) 方法。我已经尝试将 xml 转换为 ByteArrayOutputStream,甚至用 DOM 解析它,然后将其提供给转换器,但结果是一样的。 我真的很想知道为什么这只适用于单行字符串。

我将 jdk1.6_u24 与 Netbeans 6.9.1 结合使用。

这个问题与(并且可能与许多其他问题有关)但不一样:

How to pretty print XML from Java?

indent XML text with Transformer

Indent XML made with Transformer

【问题讨论】:

    标签: java xml jdk1.6 indentation transformer


    【解决方案1】:

    我已经得出结论,这是 Transformer 的正常行为。更。它的缩进功能并不意味着用作漂亮的打印机,无论如何都不是它自己的。当 XML 打印得很漂亮时,它的结构会发生变化,除非您确切地知道文档应该是什么样子(基于它的 XSD、DTD 或类似的东西)。这是确定哪些换行符被视为可忽略的空格以及哪些是实际元素值或它们的一部分的唯一方法。 Transformer 不会重新格式化现有的空格,这就是为什么我的代码输出是这样的原因。

    因此,如果您想使用 Transformer 或任何其他类漂亮地打印已经打印好的 XML 字符串,您首先必须摆脱可忽略的空白,唯一安全的方法是了解您的 XML 文档的结构应该是这样的。我希望有人为我确认此声明,因为目前这只是我的假设。如果这个说法是正确的;第三方漂亮的打印机是如何做到的?我知道 JTidy 不需要 XSD,但无论如何都打印得很漂亮。它是否只是将所有空白视为可忽略的空白,除非它包含在文本 XML 节点中?还有其他方法可以确定和消除可忽略的空格吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      相关资源
      最近更新 更多