【问题标题】:How to control line endings that javax.xml.transform.Transformer creates?如何控制 javax.xml.transform.Transformer 创建的行尾?
【发布时间】:2017-07-23 15:50:14
【问题描述】:

我正在使用将 DOM 文档 (org.w3c.dom.Document) 转换为流

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, UTF_8.name());
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamResult output = new StreamResult(out);
Source input = new DOMSource(document);
transformer.transform(input, output);

文档包含带有换行符 ('\n') 的文本节点。在输出中他们 替换为不需要的 CRLF ("\r\n")。有没有办法控制这种情况(当然,除了事后替换它们)?

我无法控制文档 DTD(-> XML 空白处理)。

(备注:OutputKeys.INDENT 不是正确答案。)

备注:为什么这个问题与question 19102804 (Ensure Unix-style line endings)不同:

  • 此问题明确提到 javax.xml.transform.Transformer 以及影响其对行尾处理的可能性。问题 19102804 要求任何解决方案,而不仅仅是使用 javax.xml.transform.Transformer 的解决方案。

  • 问题 19102804 仅限于获取“Unix 风格的行尾”的任务。在我的情况下,理想的解决方案是一个组件,它按原样输出 DOM 模型实例,而不触及任何节点(到目前为止一切都是如此)。

  • 更改 line.separator 系统属性不是一种选择(见注释)。

【问题讨论】:

标签: java xml dom


【解决方案1】:

如果您只想序列化一个 DOM 节点,那么在 Java 世界中,您可以使用 LSSerializer (https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSSerializer.html) 而不是默认的 Transformer,然后您就有了方法 setNewLine (https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSSerializer.html#setNewLine(java.lang.String) ) 来定义或控制您喜欢的行尾。

【讨论】:

  • 这可能是最好的解决方案。 Gustave 需要将他的转换目标更改为 DOMResult 才能使用此方法。
  • @VGR,我不明白你为什么需要DOMResultLSSerializer 有一个方法docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/… 可以写入LSOutput,并且允许设置 OutputStream 或 Writer .
  • 问题不在于 LSSerializer 的写入位置,而在于 LSSerializer 的输入。 Gustave 想要转换 XML,而转换后的 XML 包含不需要的换行符。
  • 通过使用TransformerFactory.newInstance().newTransformer(),您无需应用您自己的任何转换输入XML 的XSLT 样式表,您只需序列化输入XML。执行TransformerFactory.newInstance().newTransformer(someXslt) 时有所不同,但帖子中未显示。
  • 哎呀,你是对的。我错过了他正在使用身份转换器。
【解决方案2】:

基于 Martin Honnens 答案的工作解决方案。 (但这并不完全是对这个问题的答案,它明确地指的是 Transformer。所以正确的答案可能是“不”,但我暂时保持开放。):

final DOMImplementationLS dom =
  (DOMImplementationLS) DOMImplementationRegistry.newInstance().getDOMImplementation("LS")
;
final LSSerializer serializer = dom.createLSSerializer();
serializer.setNewLine("\n");
final LSOutput destination = dom.createLSOutput();
destination.setEncoding(UTF_8.name());
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
destination.setByteStream(bos);
serializer.write(document, destination);

Transformer 和 LSSerializer 之间的一个区别是 Transformer 写入

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

之后不插入空格,而 LSSerializer 写入

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

并在之后插入换行符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    相关资源
    最近更新 更多