如何防止XML Transformer改变行尾标识符

7

我有一个编辑xml文件的方法。该方法的一般概述如下:

public void process(Path anXmlFile) {
    try {
        anXmlFile= anXmlFile.normalize();
        log.debug("processing {}",anXmlFile);
        Document dom = buildDOM(anXmlFile.toFile());

        //do stuff with dom...
        //delete original file
        //and finally ...
        dom.normalize(); //so we get a more predictable order

        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT,"yes");
        Source source = new DOMSource(dom);
        Result result = new StreamResult(anXmlFile.toFile());
        transformer.transform(source, result);
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
}

我的问题是,如果我在 XML 中有一个多行注释,它在某一行打开并在下一行关闭(注意换行符):

<!-- this is a long comment[cr][lf] 
     that spans 2 lines -->

然后,当我写出修改后的DOM时,结果将会是:
<!-- this is a long comment[cr] 
     that spans 2 lines -->

问题在于[回车][换行]变成了[回车]。这是XML中唯一受到此影响的部分。所有其他行尾都与原始行尾相同([回车][换行]) - 即使我修改了它们(我的代码不会更改DOM中的注释节点)。

是否有任何配置选项可以给我创建的Transformer,以避免这种情况?所有操作都使用JDK类完成,无涉及XML库。


XML规范要求解析器具有此行为;请参见End-of-Line Handling部分。 - McDowell
@McDowell 哇,他们真是太愚蠢了。有没有任何解析器可以选择性地忽略这个问题并给我一致的换行? - radai
但是,这是关于DOM树序列化的问题,因此该规范并不适用。 - forty-two
@forty-two 说得好,但我认为这解释了默认行为。我注意到LSSerializer有一个选项可以设置行尾序列。 - McDowell
1个回答

3
XML规范要求XML处理器(解析器)将 \ r \ n 或只是 \ r 替换为单个 \ n 。因此,如果您检查DOM文本节点,您会发现您只有 \ n 作为行尾。在序列化DOM树时,大多数实现在写入字符数据中出现的换行符时使用平台默认值,或者它们提供一个选项来显式设置行尾字符串。然而,注释文本不是字符数据;这些字符仅按原样编写,没有任何其他处理。至少,这是大多数序列化程序的行为。如果非常重要,您可以切换到JDOM并扩展AbstractXMLOutputProcessor以更改编写注释的方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接