Python ElementTree重复检查器

时间:2011-03-14 15:23:46

标签: python xml elementtree

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

我能想到进行重复检查的最好方法是设置两个字典(dictLeft,dictRight)并将xpath#值保存为密钥及其出现的次数。像这样:

左:

{ '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 个答案:

答案 0 :(得分: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。如果有人有更好的算法,我会全力以赴:)

答案 1 :(得分: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

或者,将数量计算为正常的dict并且只比较两个dicts的相等性(在概念上对我来说似乎更简单)。

答案 2 :(得分:0)

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

如果可行,则可能是简单的解决方案,但可能有理由说明为什么这对您不起作用。

答案 3 :(得分:0)

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

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

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

为什么这个微不足道的定义可能不够,有各种各样的原因:

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

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