测试环境

Python 3.6

Win10

代码实现

#!/usr/bin/env python 3.4.0
#-*- encoding:utf-8 -*- __author__ = 'shouke' import xml.etree.ElementTree as ET def compare_xml_node_attributes(xml_node1, xml_node2):
result = []
node1_attributes_dict = xml_node1.attrib
node2_attributes_dict = xml_node2.attrib
for attrib1, value in node1_attributes_dict.items():
value2 = node2_attributes_dict.get(attrib1)
if value == value2:
node2_attributes_dict.pop(attrib1)
else:
if value2:
attrib2 = attrib1
node2_attributes_dict.pop(attrib2)
else:
attrib2 = '不存在'
result.append('结点1属性:{attrib1} 值:{value1},结点2属性:{attrib1} 值:{value2}'.format(attrib1=attrib1 or '不存在',
value1=value or '不存在',
attrib2=attrib2,
value2=value2 or '不存在')) for attrib2, value2 in node2_attributes_dict.items():
result.append('结点1属性:{attrib1} 值:{value1},结点2属性:{attrib1} 值:{value2}'.format(attrib1='不存在',
value1='不存在',
attrib2=attrib2,
value2=value2))
return result def compare_xml_node_children(xml_node1, xml_node2, node1_xpath, node2_xpath):
def get_node_children(xml_node, node_xpath):
result = {}
for child in list(xml_node):
if child.tag not in result:
result[child.tag] = [{'node':child, 'xpath': '%s/%s[%s]' % (node_xpath, child.tag, 1)}]
else:
result[child.tag].append({'node':child, 'xpath': '%s/%s[%s]' % (node_xpath, child.tag, len(result[child.tag])+1)})
return result result = []
children_of_node1_dict = get_node_children(xml_node1, node1_xpath)
children_of_node2_dict = get_node_children(xml_node2, node2_xpath) temp_list1 = []
temp_list2 = []
for child_tag, child_node_list in children_of_node1_dict.items():
second_child_node_list = children_of_node2_dict.get(child_tag, [])
if not second_child_node_list:
# 获取xml1中比xml2中多出的子结点
for i in range(0, len(child_node_list)):
temp_list1.append('%s/%s[%s]' % (node1_xpath, child_node_list[i]['node'].tag, i+1))
continue for first_child, second_child in zip(child_node_list, second_child_node_list):
result.extend(compare_xml_nodes(first_child['node'], second_child['node'], first_child['xpath'], second_child['xpath'])) # 获取xml2中对应结点比xml1中对应结点多出的同名子结点
for i in range(len(child_node_list), len(second_child_node_list)):
temp_list2.append('%s/%s[%s]' % (node2_xpath, second_child_node_list[i]['node'].tag, i+1))
children_of_node2_dict.pop(child_tag) if temp_list1:
result.append('子结点不一样:xml1结点(xpath:{xpath1})比xml2结点(xpath:{xpath2})多了以下子结点:\n{differences}'.format (xpath1=node1_xpath,
xpath2=node2_xpath,
differences='\n'.join(temp_list1)))
# 获取xml2比xml1中多出的子结点
for child_tag, child_node_list in children_of_node2_dict.items():
for i in range(0, len(child_node_list)):
temp_list2.append('%s/%s[%s]' % (node1_xpath, child_node_list[i]['node'].tag, i+1)) if temp_list2:
result.append('子结点不一样:xml1结点(xpath:{xpath1})比xml2结点(xpath:{xpath2})少了以下子结点:\n{differences}'.format (xpath1=node1_xpath,
xpath2=node2_xpath,
differences='\n'.join(temp_list2)))
return result def compare_xml_nodes(xml_node1, xml_node2, node1_xpath='', node2_xpath=''):
result = []
# 比较标签
if xml_node1.tag != xml_node2.tag:
result.append('标签不一样:xml1结点(xpath:{xpath1}):{tag1},xml2结点(xpath:{xpath2}):{tag2}'.format (xpath1=node1_xpath,
tag1=xml_node1.tag,
xpath2=node2_xpath,
tag2=xml_node2.tag)) # 比较文本
if xml_node1.text != xml_node2.text:
result.append('文本不一样:xml1结点(xpath:{xpath1}):{text1},xml2结点(xpath:{xpath2}):{text2}'.format (xpath1=node1_xpath,
tag1=xml_node1.text or '',
xpath2=node2_xpath,
tag2=xml_node2.text or '')) # 比较属性
res = compare_xml_node_attributes(xml_node1, xml_node2)
if res:
result.append('属性不一样:xml1结点(xpath:{xpath1}),xml2结点(xpath:{xpath2}):\n{differences}'.format (xpath1=node1_xpath,
xpath2=node2_xpath,
differences='\n'.join(res)))
# 比较子结点
res = compare_xml_node_children(xml_node1, xml_node2, node1_xpath, node2_xpath)
if res:
result.extend(res) return result def compare_xml_strs(xml1_str, xml2_str, mode=3):
'''
@param: mode 比较模式,预留,暂时没用。目前默认 xml 子元素如果为列表,则列表有序列表,按序比较
'''
root1 = ET.fromstring(xml1_str.strip())
root2 = ET.fromstring(xml2_str.strip()) return compare_xml_nodes(root1, root2, '/%s' % root1.tag, '/%s' % root2.tag)

测试运行

xml_str1 = '''
<?xml version = "1.0" encoding="utf-8" ?>
<data>
<country name="Liechtenstein">
<rangk>1</rangk>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E" ></neighbor>
<neighbor name="Switzerland" direction="W" ></neighbor>
</country>
<country name="Singpore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N" ></neighbor>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W" ></neighbor>
<neighbor name="Colombia" direction="W" ></neighbor>
</country>
</data>
'''
xml_str2 = '''
<?xml version = "1.0" encoding="utf-8" ?>
<data>
<country name="Liechtenstein">
<rangk>1</rangk>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E" ></neighbor>
<neighbor name="Switzerland" direction="W" ></neighbor>
</country>
<country name="Singpore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N" ></neighbor>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W" ></neighbor>
<neighbor name="Colombia" direction="W" ></neighbor>
</country>
</data>
''' xml_str3 = '''
<?xml version = "1.0" encoding="utf-8" ?>
<data>
<class name="computer">
<rangk>1</rangk>
<year>unknow</year>
<addr>sz</addr>
<book name="java programming" price="10" ></book>
<book name="python programming" price="10" ></book>
</class>
<class name="philosophy">
<rangk>2</rangk>
<year>unknown</year>
<book name="A little history of philosophy" price="15" ></book>
<book name="contemporary introduction" price="15" ></book>
</class>
<class name="history">
<rangk>3</rangk>
<year>unknown</year>
<addr>other addr</addr>
<book name="The South China Sea" price="10" ></book>
<book name="Chinese Among Others" price="10" ></book>
</class>
</data>
''' xml_str4 = '''
<?xml version = "1.0" encoding="utf-8" ?>
<data>
<class name="computer">
<year>unknow</year>
<addr>sz</addr>
<book name="java programming" price="10" ></book>
<book name="python programming" price="10" ></book>
</class>
<class name="philosophy">
<year>unknown</year>
<addr>other addr</addr>
<book name="A little history of philosophy" price="15" ></book>
<book name="contemporary introduction" price="16" ></book>
</class>
</data>
''' if __name__ == '__main__':
res_list = compare_xml_strs(xml_str1, xml_str2)
if res_list:
print('xml1和xml2不一样:\n%s' % '\n'.join(res_list))
else:
print('xml1和xml2一样') res_list = compare_xml_strs(xml_str3, xml_str4)
if res_list:
print('xml3和xml4不一样:\n%s' % '\n'.join(res_list))
else:
print('xml3和xml4一样')

运行结果

xml1和xml2一样
xml3和xml4不一样:
子结点不一样:xml1结点(xpath:/data/class[1])比xml2结点(xpath:/data/class[1])多了以下子结点:
/data/class[1]/rangk[1]
属性不一样:xml1结点(xpath:/data/class[2]/book[2]),xml2结点(xpath:/data/class[2]/book[2]):
结点1属性:price 值:15,结点2属性:price 值:16
子结点不一样:xml1结点(xpath:/data/class[2])比xml2结点(xpath:/data/class[2])多了以下子结点:
/data/class[2]/rangk[1]
子结点不一样:xml1结点(xpath:/data/class[2])比xml2结点(xpath:/data/class[2])少了以下子结点:
/data/class[2]/addr[1]

Python 基于xml.etree.ElementTree实现XML对比的更多相关文章

  1. Python中xml.etree.ElementTree读写xml文件实例

    import osimport xml.etree.ElementTree as ET'''Python 标准库中,提供了6种可以用于处理XML的包,本文举实例说明第6种1.xml.dom2.xml. ...

  2. python3.x中xml.etree.ElementTree解析xml举例

    1.新建xml import xml.etree.ElementTree as ETa=ET.Element('elem')c=ET.SubElement(a,'child1')c.text=&quo ...

  3. python xml.etree.ElementTree解析xml文件获取节点

    <?xml version = "1.0" encoding = "utf-8"?> <root> <body name=&quo ...

  4. python 解析xml遇到xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 4, column 34

    在调试数字驱动用xml文件的方式时,包含读取xml文件的步骤,运行程序报错: d:\test\0629>python XmlUtil.pyTraceback (most recent call ...

  5. python标准库xml.etree.ElementTree的bug

    使用python生成或者解析xml的方法用的最多的可能就数python标准库xml.etree.ElementTree和lxml了,在某些环境下使用xml.etree.ElementTree更方便一些 ...

  6. python模块:xml.etree.ElementTree

    """Lightweight XML support for Python. XML is an inherently hierarchical data format, ...

  7. python xml.etree.ElementTree模块

    使用的XML文件如下:file.xml <?xml version="1.0"?> <data name="ming"> <cou ...

  8. Python 标准库之 xml.etree.ElementTree

    Python 标准库之 xml.etree.ElementTree Python中有多种xml处理API,常用的有xml.dom.*模块.xml.sax.*模块.xml.parser.expat模块和 ...

  9. python解析xml文件之xml.etree.cElementTree和xml.etree.ElementTree区别和基本使用

    1.解析速度:ElementTree在 Python 标准库中有两种实现.一种是纯 Python 实现例如 xml.etree.ElementTree ,另外一种是速度快一点的 xml.etree.c ...

  10. [python 学习] 使用 xml.etree.ElementTree 模块处理 XML

    ---恢复内容开始--- 导入数据(读文件和读字符串) 本地文件 country_data.xml <?xml version="1.0"?> <data> ...

随机推荐

  1. EasyUI框架Datagrid(数据表格)的实现,以及Datagrid的分页显示(详解)

    在前端页面中使用EasyUI框架时,通常会使用EasyUI自带的datagrid(数据表格)样式,下面我们对datagrid样式进行简单的介绍,并且会对datagrid的分页显示进行详细的介绍. Ea ...

  2. SpringMVC在返回JSON数据时出现406错误解决方案

    在SpringMVC框架的使用中常常会使用@ResponseBody注解,修饰"处理器"(Controller的方法),这样在处理器在返回完毕后,就不走逻辑视图,而是将返回的对象转 ...

  3. exe应用程序安装为windows服务

    1.使用instsrv.exe和srvany.exe 当你获取到srvany后并决定将某程序作为服务启动后,请先将srvany安装为系统服务,具体的安装方法有很多,这里使用instsrv,语法如下:安 ...

  4. ES6 ES6变量的声明

      // ES6语法         // 是对js影响最大的一个版本更新         // 在 ES6 语法中 退出了很多新的 语法结构         // 就相当于 js 语言, 换了一个新 ...

  5. 史上最强 AI 翻译诞生了!拳打谷歌,脚踢 DeepL

    CoT 推理范式 默认情况下,大语言模型通常是直接给出问题的最终答案,中间推理过程是隐含的.不透明的,无法发挥出大模型最极致的理解能力.如果你用它来充当翻译,可能效果和传统的机器翻译也差不了太多. 如 ...

  6. LeetCode 208. Implement Trie (Prefix Tree) 实现 Trie (前缀树)(C++/Java)

    题目: Implement a trie with insert, search, and startsWith methods. Example: Trie trie = new Trie(); t ...

  7. kettle从入门到精通 第五十一课 ETL之kettle Avro input

    1.我们在学习nifi的过程中有接触到Avro schema,当时我在想kettle应该也支持Avro,果不其然kettle也是支持Avro文件的读和写的.今天我们一起来学习下kettle中如何使用A ...

  8. 【简写Mybatis-02】注册机的实现以及SqlSession处理

    前言 注意: 学习源码一定一定不要太关注代码的编写,而是注意代码实现思想: 通过设问方式来体现代码中的思想:方法:5W+1H 源代码: https://gitee.com/xbhog/mybatis- ...

  9. MySQL插入中文数据时发生错误或者乱码的一些坑

    最近新入职的工作,火急火燎就下了个mysql,没想到安装时配置没弄好.今天在测试数据时,插入中文数据到mysql都是问号,先后查了半天修改表结构,数据库编码,my.ini文件都没有用. 首先第一步,打 ...

  10. 浅谈 DDD 领域驱动设计

    文章简介 在B端产品研发及项目实施中,DDD带给我们哪些思考?我们是如何应用的?本文不是科普贴,旨在分享我们的经历和思考. 背景 Domain Driven Design(简称 DDD),又称为领域驱 ...