Python 基于xml.etree.ElementTree实现XML对比示例详解
作者:授客 时间:2022-02-24 12:25:53
测试环境
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]
来源:https://www.cnblogs.com/shouke/p/16975021.html
标签:Python,xml.etree.ElementTree,XML
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Python 生成VOC格式的标签实例
2021-09-09 04:39:07
Python基于scrapy采集数据时使用代理服务器的方法
2022-06-03 08:37:04
Python实现为PDF大文件批量去除水印
2023-04-14 19:59:04
![](https://img.aspxhome.com/file/2023/0/69560_0s.png)
贝聿铭写给年轻设计师的十点忠告
2010-01-24 18:46:00
![](/images/sg_trans.gif)
全方位清理浮动
2009-06-16 14:51:00
教你怎样在Oracle数据库中高速导出/导入
2009-02-04 16:59:00
简单有效上手Python3异步asyncio问题
2022-01-14 02:28:34
![](https://img.aspxhome.com/file/2023/2/68422_0s.gif)
tensorflow实现打印ckpt模型保存下的变量名称及变量值
2021-07-02 21:19:25
Python+OCR实现文档解析的示例代码
2023-11-22 02:34:19
![](https://img.aspxhome.com/file/2023/0/82790_0s.jpg)
5个款MySQL常用维护管理工具
2010-10-25 19:45:00
![](https://img.aspxhome.com/file/UploadPic/201010/25/20101025203549207s.jpg)
PHP概率计算函数汇总
2023-11-19 08:06:19
win10系统配置GPU版本Pytorch的详细教程
2023-07-21 19:30:38
![](https://img.aspxhome.com/file/2023/1/78541_0s.png)
sqlserver 查询数据库大小的方法
2012-08-21 10:22:10
线上问题排查之golang使用json进行对象copy
2023-10-06 05:03:23
![](https://img.aspxhome.com/file/2023/9/97169_0s.png)
python selenium UI自动化解决验证码的4种方法
2022-10-09 20:43:06
在sql Server自定义一个用户定义星期函数
2012-02-12 15:47:28
Python if语句知识点用法总结
2022-01-03 06:43:14
使用python实现对元素的长截图功能
2023-11-20 10:27:44
![](https://img.aspxhome.com/file/2023/3/63923_0s.png)
最新python 字符串数组互转问题
2023-07-07 18:34:06
php数组函数序列之array_unique() - 去除数组中重复的元素值
2023-11-18 11:14:06