如何检查两个XML文件是否与Python等效?

pro*_*eek 4 python xml

如何检查两个XML文件是否相同?

例如,即使排序不同,两个XML文件也是相同的.我需要检查两个XML文件是否包含相同的文本信息,而忽略了订单.

<a>
   <b>hello</b>
   <c><d>world</d></c>
</a>

<a>
   <c><d>world</d></c>
   <b>hello</b>
</a>
Run Code Online (Sandbox Code Playgroud)

那里有工具吗?

Ste*_*ven 7

这一切都取决于你对"等效"的定义.

假设您真的只关心文本节点(例如:示例中的d标记甚至不重要,您只关心内容word),您可以只创建每个文档的一组文本节点,并比较这些集合.使用lxml,这可能看起来像:

from lxml import etree

tree1 = etree.parse('example1.xml')
tree2 = etree.parse('example2.xml')

print set(tree1.getroot().itertext()) == set(tree2.getroot().itertext())
Run Code Online (Sandbox Code Playgroud)

您甚至可能想要忽略空白节点,执行以下操作:

set(i for i in tree.getroot().itertext() if i.strip())
Run Code Online (Sandbox Code Playgroud)

请注意,使用集合意味着您不会考虑文档中某些文本出现的次数(这可能是您想要的,也可能不是).如果顺序不重要,但事件发生的次数是,您可以使用字典而不是集合,并跟踪出现的次数(例如,使用collections.defaultdict()collections.Counter在python 2.7中)

但是,如果它只是根元素的直接子元素的顺序(在您的情况下,a元素的子元素)可能被忽略,并且这些元素中的所有内容都非常重要,那么您将需要另一种方法.例如,您可以对每个子元素执行xml规范化,以获得每个子元素的规范化版本(同样,我不知道这是否足以满足您的需要).

from lxml import etree

tree1 = etree.parse('example1.xml')
tree2 = etree.parse('example2.xml')

set1 = set(etree.tostring(i, method='c14n') for i in tree1.getroot())
set2 = set(etree.tostring(i, method='c14n') for i in tree2.getroot())

print set1 == set2
Run Code Online (Sandbox Code Playgroud)

注意:保持例子简单,我用lxml的开发版本,在旧版本中,没有method='c14n'etree.tostring(),只有c14n()上了ElementTree,写入到一个类文件对象的方法.因此,为了让它在那里工作,你必须将每个元素复制到它自己的树,并使用一个StringIO()对象作为一个虚拟文件)

此外,对于非常大的文件,可能不建议这样做.

但同样:一个大警告:你真的必须知道需要什么"等同",并根据这些知识创建自己的解决方案!