代码之家  ›  专栏  ›  技术社区  ›  prosseek

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

  •  3
  • prosseek  · 技术社区  · 14 年前

    例如,尽管顺序不同,但这两个XML文件是相同的。我需要检查这两个XML文件是否包含相同的文本信息,而不考虑顺序。

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

    2 回复  |  直到 14 年前
        1
  •  7
  •   Steven    14 年前

    这完全取决于你对“等价物”的定义。

    假设您只关心文本节点(例如: d 示例中的标记甚至都不重要,您只关心内容 word

    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 在Python2.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
    

    method='c14n' 对于 etree.tostring() ,只有一个 c14n() 方法,它写入类似文件的对象。因此,要使它在那里工作,您必须将每个元素复制到它自己的树中,并使用 StringIO() 对象作为虚拟文件)

    另外,对于非常大的文件,可能不建议使用这种方法。

    但是再一次:一个重大警告:你 必须知道什么 需要作为“等价物”,并创建自己的解决方案的基础上的知识!

        2
  •  2
  •   Gintautas Miliauskas    14 年前

    排序在XML中很重要,所以您提供的两个文件 不一样。通常,您可以规范化XML,然后简单地将文件作为文本进行比较,但是如果您希望进行顺序不敏感的比较,那么您可能需要自己使用大量的XML解析器之一来实现它(顺便说一句,我推荐使用lxml)。