SAX Transformer 和 <?xml ... ?> 之后的行尾

SAX Transformer and end of line after <?xml ... ?>

要编写我的 xml 代码,我使用以下代码:

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
...
XMLOutputFactory xMLOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = xMLOutputFactory.createXMLStreamWriter(stringWriter);
writer.writeStartDocument("UTF-8", "1.0");
writer.writeCharacters("\n");
//I tried also writer.writeCharacters(System.getProperty("line.separator"));
writer.writeStartElement("settings");
...

要将一行 xml 转换为多行正常 xml 格式,我使用以下代码:

public String transform(final String xml) throws XMLStreamException, TransformerException {
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    Writer writer = new StringWriter();
    transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(writer));
    return writer.toString();
}

这是结果

<?xml version="1.0" encoding="UTF-8"?><settings>
   ...
</settings>

如您所见,<settings 在第一行。如何让 <settings> 移动到第二行以获得以下结果

<?xml version="1.0" encoding="UTF-8"?>
<settings>
   ...
</settings>

怎么做?

假设您正在使用 Java 附带的内置 XSLT 处理器。那是一个 XSLT 1.0 处理器,所以我们需要查看 XSLT 1.0 规范。

这就是 XSLT 1.0 关于缩进的说法="yes":

If the indent attribute has the value yes, then the xml output method may output whitespace in addition to the whitespace in the result tree (possibly based on whitespace stripped from either the source document or the stylesheet) in order to indent the result nicely; if the indent attribute has the value no, it should not output any additional whitespace. The default value is no. The xml output method should use an algorithm to output additional whitespace that ensures that the result if whitespace were to be stripped from the output using the process described in [3.4 Whitespace Stripping] with the set of whitespace-preserving elements consisting of just xsl:text would be the same when additional whitespace is output as when additional whitespace is not output.

这一切都相当复杂,但最重要的是,处理器可以在您需要的位置输出换行符,但没有义务这样做。

如果您使用 Saxon 作为 XSLT 处理器,此时它会输出一个换行符。

但是你还没有说为什么这个换行符对你如此重要。你描述没有它作为 "problem",但为什么这是一个问题?如果您使用标准 XML 解析器解析生成的文档,那么此时的任何换行符都将被忽略。有一种情况会有所不同,即如果您生成的 XML 用作合并到某个较大文档中的外部解析实体。但是对于那种情况,您肯定不想要换行符(这也许就是 Xalan 不输出它的原因)。

注意:另见 Remove space in between doctype in XML using XSLT 用户这次抱怨序列化输出中的换行符,在这种情况下是不需要的。如果您关心同一文档的不同序列化之间的差异,这不会影响任何符合规范的解析器处理文档的方式,那么 (a) 您可能不得不编写自己的序列化程序,(b) 您你将失去 XML 的主要好处之一,即大量一致工具的可用性,并且 (c) 你做错了什么:可能使用了不一致的解析器(或根本没有解析器)处理生成的 XML.

对我来说,它适用于缩进和 XML standalone="yes"

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

当然,但是,这需要您的客户端或应用程序能够容忍独立声明。