使用Java解析时如何在文档元素之前保留空格?

Posted

技术标签:

【中文标题】使用Java解析时如何在文档元素之前保留空格?【英文标题】:How to keep whitespace before document element when parsing with Java? 【发布时间】:2010-10-26 12:22:12 【问题描述】:

在我的应用程序中,我更改了 XML 文件的某些部分,其开头如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: version control yadda-yadda $ -->

<myElement>
...

注意&lt;myElement&gt; 之前的空行。加载、修改、保存后,效果差强人意:

<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: version control yadda-yadda $ --><myElement>
...

我发现注释和文档节点之间的空格(一个换行符)根本没有在 DOM 中表示。以下独立代码可靠地重现了该问题:

String source =
    "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<!-- foo -->\n<empty/>";
byte[] sourceBytes = source.getBytes("UTF-16");

DocumentBuilder builder =
    DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc =
    builder.parse(new ByteInputStream(sourceBytes, sourceBytes.length));

DOMImplementationLS domImplementation =
    (DOMImplementationLS) doc.getImplementation();
LSSerializer lsSerializer = domImplementation.createLSSerializer();
System.out.println(lsSerializer.writeToString(doc));

// output: <?xml version="1.0" encoding="UTF-16"?>\n<!-- foo --><empty/>

有人知道如何避免这种情况吗?本质上,我希望输出与输入相同。 (我知道 xml 声明将被重新生成,因为它不是 DOM 的一部分,但这不是问题。)

【问题讨论】:

我最终使用自定义 OutputStream 类将其破解到输出中,该类查找“--> 我有同样的问题。你能帮忙吗? ***.com/questions/30940162/… 【参考方案1】:

一般来说,空白在 XML 中被认为是不相关的,因此在解析 XML 文件时不会保留。大多数输出​​ XML 的库都可以选择以良好的格式和正确的缩进输出它,但它总是相当通用的。没有“在这里有一个额外的行”。

【讨论】:

关键是原始输入中有一行,应该保留 - 就像文档其余部分中的所有空白一样!跨度> 【参考方案2】:

为什么要避免这种情况?

标签/元素之外的空白被规范定义为无关紧要。就您的 DOM 所代表的信息集而言,它根本不存在。

因此,在再次序列化 DOM 时,它将不存在。

如果您正在开发依赖于这个空行的东西......不要。

【讨论】:

当然,没有程序依赖这种格式。但是,这些文件包含翻译数据;它们被签入版本控制并持续维护。因此,如果我的应用所做的唯一更改是有意更改,那么查看差异会很好。 我是这么认为的...我认为唯一明智的处理方法是在文件中不要有这个空行。我认为没有任何可推荐的方法来保留这条线。也许文件应该在签入之前通过整理工具作为规则传递,以避免这些不一致。 @Tomalak::你能帮帮我吗:***.com/questions/30940162/…【参考方案3】:

我遇到了同样的问题。我的解决方案是编写自己的 XML 解析器:DecentXML

主要特点:它可以 100% 保留原始输入,空白,实体,一切。它不会打扰你的细节,但如果你的代码需要像这样生成 XML:

 <element
     attr="some complex value"
     />

那么你就可以了。

【讨论】:

感谢您的建议; DecentXML 看起来确实是一件值得牢记的好东西! bookmarksIt 很高兴看到至少有一个“又一个解析器”项目有一个非常好的存在理由。但是,对于我当前的问题,我更愿意在整个处理代码中使用标准 DOM API,并在输出阶段简单地添加该行。 那么你需要在根元素之前手动添加文本节点。查看 Document 对象如何添加普通(非元素)节点。如果这不可能,您必须为写入器/输出流创建一个过滤器,该过滤器会破解其中的换行符。 @AaronDigulla::你能帮我解决这个问题吗***.com/questions/30940162/…【参考方案4】:

我同意 Kris 和 Tomalak 的观点,从 XML 的角度来看,空行是不相关的。如果您的应用程序需要在输出中生成一个空行,我建议您查看该要求的需要。

无论如何,如果您仍然希望显示该空白行,我建议您下载您正在使用的 XML 解析器的源代码并修改该行为。但请记住,这不是标准 XML,它不会与其他应用程序兼容。

Jdom Source Dom4j Source检查org.dom4j.io.DOMWriter

【讨论】:

那些打算由人类编辑的 XML 文件呢?在这种情况下,原始格式很重要。 XML不仅是为了序列化,如果是二进制格式会更好。【参考方案5】:

根本原因是标准DOM Level 3 无法在不违反规范的情况下将文本节点表示为文档的子节点。任何兼容的解析器都会删除空格。

Document -- 
    Element (maximum of one),
    ProcessingInstruction,
    Comment,
    DocumentType (maximum of one)

如果您需要符合标准的解决方案并且目标是可读性而不是 100% 可复制,我会在您的输出机制中寻找它。

【讨论】:

很好的答案,但在我看来,这是规范中的一个愚蠢的错误。你当然可以在document元素之前输出文本,但是不能输入? @McDowell 我们可以做些什么来避免这种情况,请查看我的问题。 ***.com/questions/30940162/…

以上是关于使用Java解析时如何在文档元素之前保留空格?的主要内容,如果未能解决你的问题,请参考以下文章

带有空格的Java枚举元素?

如何在Java中仅删除字符串的尾随空格并保留前导空格?

JAVA中如何去除字符串前后的全角空格(当中保留)?

CSS:如何在元素内容之前添加空格?

粘贴到 Web 表单时如何保留 Word 文档格式?

如何解析pyspark中的空格分隔数据?