2014-06-30 156 views
2

我是python编程的新手,'我对理解这个概念有些麻烦。我希望比较两个XML文件。这些XML文件非常大。 我将给出一个我希望比较的文件类型的例子。比较python中的两个xml文件

xmlfile1:

<xml> 
    <property1> 
      <property2>  
       <property3> 

       </property3> 
      </property2>  
    </property1>  
</xml> 

XML文件2:

<xml> 
    <property1> 
     <property2>  
      <property3> 
       <property4> 

       </property4>  
      </property3> 
     </property2>  
    </property1> 

</xml> 

的property1,property2我已经命名是从实际是在文件中的有所不同。 xml文件中有很多属性。 和我想比较两个XML文件。

我正在使用lxml解析器试图比较两个文件并打印出它们之间的差异。

我不知道如何解析它并自动比较它。

我试着通过lxml解析器阅读,但我无法理解如何使用它来解决我的问题。

有人可以告诉我该怎么处理这个问题。

代码片段是非常有用的

还有一个问题,我是按照正确的概念还是我失去了一些东西别的吗?请纠正我所有你所知道的新概念

+0

你在输出的需求 - 如果它只是一个差异则可能需要在Windows Linux或FC使用DIFF – gkusner

+0

其实我想知道文件的哪一部分已经变了。 – sankar

回答

4

这实际上是一个相当具有挑战性的问题(由于在这里,“差异”意味着经常在旁观者的眼中,因为会有语义上“等价”的信息你可能不想标记为差异)。

您可以尝试使用xmldiff,这是基于Change Detection in Hierarchically Structured Information论文中的工作。

+0

xmldiff是GPL。这是否意味着我必须开源我的源代码,如果我使用它? – guettli

1

我对这个问题的处理方法是将每个XML转换为xml.etree.ElementTree并遍历每个图层。 我还包括在进行比较时忽略属性列表的功能。

第一个代码块保存使用该类:

import xml.etree.ElementTree as ET 
import logging 

class XmlTree(): 

    def __init__(self): 
     self.hdlr = logging.FileHandler('xml-comparison.log') 
     self.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') 

    @staticmethod 
    def convert_string_to_tree(xmlString): 

     return ET.fromstring(xmlString) 

    def xml_compare(self, x1, x2, excludes=[]): 
     """ 
     Compares two xml etrees 
     :param x1: the first tree 
     :param x2: the second tree 
     :param excludes: list of string of attributes to exclude from comparison 
     :return: 
      True if both files match 
     """ 

     if x1.tag != x2.tag: 
      self.logger.debug('Tags do not match: %s and %s' % (x1.tag, x2.tag)) 
      return False 
     for name, value in x1.attrib.items(): 
      if not name in excludes: 
       if x2.attrib.get(name) != value: 
        self.logger.debug('Attributes do not match: %s=%r, %s=%r' 
           % (name, value, name, x2.attrib.get(name))) 
        return False 
     for name in x2.attrib.keys(): 
      if not name in excludes: 
       if name not in x1.attrib: 
        self.logger.debug('x2 has an attribute x1 is missing: %s' 
           % name) 
        return False 
     if not self.text_compare(x1.text, x2.text): 
      self.logger.debug('text: %r != %r' % (x1.text, x2.text)) 
      return False 
     if not self.text_compare(x1.tail, x2.tail): 
      self.logger.debug('tail: %r != %r' % (x1.tail, x2.tail)) 
      return False 
     cl1 = x1.getchildren() 
     cl2 = x2.getchildren() 
     if len(cl1) != len(cl2): 
      self.logger.debug('children length differs, %i != %i' 
         % (len(cl1), len(cl2))) 
      return False 
     i = 0 
     for c1, c2 in zip(cl1, cl2): 
      i += 1 
      if not c1.tag in excludes: 
       if not self.xml_compare(c1, c2, excludes): 
        self.logger.debug('children %i do not match: %s' 
           % (i, c1.tag)) 
        return False 
     return True 

    def text_compare(self, t1, t2): 
     """ 
     Compare two text strings 
     :param t1: text one 
     :param t2: text two 
     :return: 
      True if a match 
     """ 
     if not t1 and not t2: 
      return True 
     if t1 == '*' or t2 == '*': 
      return True 
     return (t1 or '').strip() == (t2 or '').strip() 

的第二个代码块容纳一对夫妇的XML实例和他们的比较:

xml1 = "<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>" 

xml2 = "<note><to>Tove</to><from>Daniel</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>" 

tree1 = XmlTree.convert_string_to_tree(xml1) 
tree2 = XmlTree.convert_string_to_tree(xml2) 

comparator = XmlTree() 

if comparator.xml_compare(tree1, tree2, ["from"]): 
    print "XMLs match" 
else: 
    print "XMLs don't match" 

大部分的贷款,用于该代码必须给予syawar

+0

这段代码需要在Python3.5上进行如下的调整: 'def __init __(self): self.logger = logging。getLogger('xml_compare') self.logger.setLevel(logging.DEBUG) self.hdlr = logging.FileHandler('xml-comparison.log') self.formatter = logging.Formatter('%(asctime)s - %(levelname)s-%(message)s') self.hdlr.setLevel(logging.DEBUG) self.hdlr.setFormatter(self.formatter) self.logger.addHandler(self.hdlr)' –

+0

也许我错过了一些东西,但是这种方法一旦发现一个区别就停止检查XML,这是一个很好的开始方式,但它不能按预期工作...... – ivoruJavaBoy

0

另一个脚本使用xml.etree。它的可怕,但它的工作原理:)

#!/usr/bin/env python 

import sys 
import xml.etree.ElementTree as ET 

from termcolor import colored 

tree1 = ET.parse(sys.argv[1]) 
root1 = tree1.getroot() 

tree2 = ET.parse(sys.argv[2]) 
root2 = tree2.getroot() 

class Element: 
    def __init__(self,e): 
     self.name = e.tag 
     self.subs = {} 
     self.atts = {} 
     for child in e: 
      self.subs[child.tag] = Element(child) 

     for att in e.attrib.keys(): 
      self.atts[att] = e.attrib[att] 

     print "name: %s, len(subs) = %d, len(atts) = %d" % (self.name, len(self.subs), len(self.atts)) 

    def compare(self,el): 
     if self.name!=el.name: 
      raise RuntimeError("Two names are not the same") 
     print "----------------------------------------------------------------" 
     print self.name 
     print "----------------------------------------------------------------" 
     for att in self.atts.keys(): 
      v1 = self.atts[att] 
      if att not in el.atts.keys(): 
       v2 = '[NA]' 
       color = 'yellow' 
      else: 
       v2 = el.atts[att] 
       if v2==v1: 
        color = 'green' 
       else: 
        color = 'red' 
      print colored("first:\t%s = %s" % (att, v1), color) 
      print colored("second:\t%s = %s" % (att, v2), color) 

     for subName in self.subs.keys(): 
      if subName not in el.subs.keys(): 
       print colored("first:\thas got %s" % (subName), 'purple') 
       print colored("second:\thasn't got %s" % (subName), 'purple') 
      else: 
       self.subs[subName].compare(el.subs[subName]) 



e1 = Element(root1) 
e2 = Element(root2) 

e1.compare(e2)