2

所以我必须编写一个“重复检查器”来比较两个 XML,看看它们是否相同(包含相同的数据)。现在因为它们来自同一个类并且是从 XSD 生成的,所以结构内部元素的顺序很可能是相同的。

我能想到的进行重复检查的最佳方法是设置两个字典(dictLeft、dictRight)并将 xpath#value 保存为键和它出现的次数。像这样的东西:

剩下:

{ 'my/path/to/name#greg': 1, 'my/path/to/name#john': 2, 'my/path/to/car#toyota': 1}

{ 'my/path/to/name#greg': 1, 'my/path/to/name#bill': 1, 'my/path/to/car#toyota': 1}

比较这两个字典会给我一个相当准确的指示,表明这两个 XML 是否相同(我可能会得到错误的结果,但它非常遥远)。

还有其他人有更好的主意吗?也许 ElementTree 中有一个我不知道的函数?

编辑:为了更好地解释:

<root><person><name>Bob</name><surname>marley</surname></root>

<root><person><surname>marley</surname><name>Bob</name></root>

将被视为相同。我忽略了属性。这个想法是让代码尽可能简单,同时又不会过多地影响性能。

4

4 回答 4

1

好的,所以我必须做出决定,然后这样做:

foreach path in xpathlist
  find entries for path for both xml1 and xml2
  foreach entry in xmlentries1
    dict1[path#entry.value]++
  foreach entry in xmlentries2
    dict2[path#entry.value]++

  if dict1 and dict2 are not equal
    return false
return true

我希望这是有道理的。这使我可以测试特定/所有 xpath。如果有人有更好的算法,我会全神贯注:)

于 2011-03-16T09:30:09.517 回答
0

从您的示例中,您似乎应该能够使用 iterparse 并使用 collections.Counter 来计算每个标签的外观及其属性作为计数器的键。例子:

from xml.etree import cElementTree as ElementTree
from collections import Counter

your_xml = get_xml()
count = Counter()
parser = ElementTree.iterparse(your_xml)
for event, element in parser:
    #joining string as key for ease of debugging, strictly speaking,
    #one could use a tuple and save the str() on the attrib dict
    key = "".join((element.tag, str(element.attrib), element.text))
    count[element.tag] += 1

或者,让 count 成为一个普通的字典,然后比较两个字典的相等性(对我来说在概念上似乎更简单)。

于 2011-03-14T15:56:57.750 回答
0

如果从相同的代码生成两个 XML 并包含相同的值(以相同的顺序),那么您可以简单地对 XML 数据进行字符串比较。

如果可行,那么它可能是最简单的解决方案,但可能有一些原因导致它对您不起作用。

于 2011-03-14T16:21:52.983 回答
0

这个问题从定义“相同”的含义开始。

例如,对于 XML 元素,相等的简单定义是两个 XML 元素相等,如果:

  • 它们在同一个命名空间中,
  • 它们具有相同的标签名称,
  • 它们具有相同的属性集,具有相同的值,
  • 它们各自的子节点列表(不包括注释和处理指令)以及纯空格文本节点以相同的顺序包含相同的值。

这个微不足道的定义可能不够用的原因有很多:

  • 您可能希望忽略不在您知道的命名空间中的元素 - 即您不希望您的应用程序的相等性测试因为其他应用程序在 XML 中存储数据而失败
  • 子元素排序可能不重要,或者(更糟)可能对某些元素重要,而对其他元素不重要
  • 注释、处理指令和纯空白文本节点可能很重要
  • 在比较它们之前,您可能需要normalize-space()在文本节点中规范化空格(参见 XSLT 中的函数)

一旦定义了相等性,实现一个方法来测试它就相对简单了。但是你需要先定义平等。

于 2011-03-14T19:29:28.277 回答