如何检查两个XML文件是否相同?
例如,即使顺序不同,两个XML文件也是相同的。我需要检查两个XML文件是否包含相同的文本信息而不管订单。
<a>
<b>hello</b>
<c><d>world</d></c>
</a>
<a>
<c><d>world</d></c>
<b>hello</b>
</a>
那里有工具吗?
答案 0 :(得分: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())
您甚至可能想要忽略空白节点,执行以下操作:
set(i for i in tree.getroot().itertext() if i.strip())
请注意,使用集合意味着您不会考虑文档中某些文本出现的次数(这可能是您想要的,也可能不是)。如果顺序不重要,但出现的次数是,您可以使用字典而不是集合,并跟踪出现的次数(例如,使用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
注意:为了使示例更简单,我使用了lxml的开发版本,在旧版本中,method='c14n'
没有etree.tostring()
,只有c14n()
方法ElementTree,写入类文件对象。因此,为了让它在那里工作,你必须将每个元素复制到它自己的树中,并使用StringIO()
对象作为虚拟文件)
此外,对于非常大的文件,可能不建议采用这种方式。
但又一次:一个很大的警告:你真的必须知道你需要什么作为“等价物”,并根据这些知识创建你自己的解决方案!
答案 1 :(得分:2)
订购在XML中很重要,因此您提供的的两个文件不同。通常你可以规范化XML,然后简单地将文件作为文本进行比较,但是如果你想要对顺序不敏感的比较,你可能必须自己使用其中一个非常多的XML解析器来实现它(顺便说一句,我会推荐使用lxml) )。