我可以让XmlTextWriter写<element/>而不是<element />吗?

4 投票
5 回答
515 浏览
提问于 2025-04-17 06:36

我遇到了一种情况,XML数据正在通过两种不同的方式进行处理。在一个地方,我使用Python的xml.dom.minidom库来处理。在另一个地方,则是在.NET中通过XmlTextWriter进行类似的处理。

在Python代码生成的输出中,空元素的写法是<ElementName/>(元素关闭前没有空格)。而在.NET代码中,插入了一个空格(变成了<ElementName />)。这对XML的有效性或含义没有任何影响,但在比较这两种输出时,会被检测为不同。

有没有办法告诉XmlTextWriter不要加这个多余的空格?如果不行,有没有办法在Python生成的输出中加上这个空格(除了修改库的源代码,虽然可以,但我觉得这样做不太好;-))?

更新:也许我应该解释一下我真正想做的,而不是只描述问题。可能我把事情搞得比应该的更复杂/痛苦了。

我真正需要的是一种机制来确定XML表示的结构没有被修改。我最开始是把XML扁平化(这样在.NET环境中处理时就消除了空格问题),然后计算数据的一个合适的哈希值。有没有更好的机制我可以/应该使用?

5 个回答

0

我会在输出结果出来后再进行处理,做一些查找和替换,而不是去修改这个库的内容。

1

你会发现,只有当你把 XmlWriterSettings 中的 Indent 属性设置为 true 时,问题才会出现。当 Indent == false 时,就不会插入空格。但如果你想要缩进,就得接受这个空格。

所以,也许解决你程序的问题就是在两个工具中都关闭缩进?

这有点遗憾,因为几乎可以改变这种行为。

XmlWriter 的实现实际上是调用 XmlWriterSettings.CreateWriter 来根据你传入的设置创建一个写入器。如果 Indent == true,那么它会创建一个 XmlEncodedRawTextWriterIndent,这是一个内部类,继承自抽象类 XmlWriter。它重写了 WriteFullEndElement 方法,并插入了那个空格。

理论上,你可以创建一个自己的类,继承自 XmlEncodedRawTextWriterIndent,并重写 WriteFullEndElement。如果能做到这一点,就可以轻松防止缩进。但你无法这样做,因为它是一个 internal 类(只在 System.Xml 内部可用)。即使你能子类化 XmlEncodedRawTextWriterIndent,你也会遇到问题,因为 XmlWriterSettings.CreateXmlWriter 没有办法实例化你的类,而 XmlWriterSettingssealed 的。

我想,阻止创建自定义 XmlWriter 类是有充分理由的,尽管我现在想不起来是什么原因。

5

可能这不是你想要的答案:不要把XML输出当作纯文本来比较。我们在单元测试中这样做(两个通过XML消息通信的应用),结果很脆弱,容易出错,麻烦,而且需要很多维护。你应该解析XML输出,比较它的结构。虽然写这样一个工具可能需要更多的工作(也许已经有现成的工具了),但当任何库的下一个版本输出稍微改变时,它仍然可以正常工作。

编辑:好吧,现在你更详细地解释了你的问题,让我看看我是否理解正确:你有一些数据要生成XML输出。有时是通过.NET,有时是通过Python。假设你通过.NET生成输出,然后计算一个哈希值并存储它。后来你通过Python生成输出,内容应该是相同的,你也计算一个哈希值。结果这两个哈希值不相等,因为空格的问题。

如果是这样的话,你可以遍历XML文档,根据看到的节点及其属性和值来计算哈希值。一个更简单的方法是去掉输出中所有不相关的空格(无论输出来自哪里),然后再进行哈希计算。你可以在Python中做到这一点;)

撰写回答