Python?基于xml.etree.ElementTree實現(xiàn)XML對比示例詳解
測試環(huán)境
Python 3.6
Win10
代碼實現(xiàn)
#!/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('結(jié)點1屬性:{attrib1} 值:{value1},結(jié)點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('結(jié)點1屬性:{attrib1} 值:{value1},結(jié)點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中多出的子結(jié)點 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中對應(yīng)結(jié)點比xml1中對應(yīng)結(jié)點多出的同名子結(jié)點 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('子結(jié)點不一樣:xml1結(jié)點(xpath:{xpath1})比xml2結(jié)點(xpath:{xpath2})多了以下子結(jié)點:\n{differences}'.format (xpath1=node1_xpath, xpath2=node2_xpath, differences='\n'.join(temp_list1))) # 獲取xml2比xml1中多出的子結(jié)點 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('子結(jié)點不一樣:xml1結(jié)點(xpath:{xpath1})比xml2結(jié)點(xpath:{xpath2})少了以下子結(jié)點:\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結(jié)點(xpath:{xpath1}):{tag1},xml2結(jié)點(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結(jié)點(xpath:{xpath1}):{text1},xml2結(jié)點(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結(jié)點(xpath:{xpath1}),xml2結(jié)點(xpath:{xpath2}):\n{differences}'.format (xpath1=node1_xpath, xpath2=node2_xpath, differences='\n'.join(res))) # 比較子結(jié)點 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 比較模式,預(yù)留,暫時沒用。目前默認 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一樣')
運行結(jié)果
xml1和xml2一樣 xml3和xml4不一樣: 子結(jié)點不一樣:xml1結(jié)點(xpath:/data/class[1])比xml2結(jié)點(xpath:/data/class[1])多了以下子結(jié)點: /data/class[1]/rangk[1] 屬性不一樣:xml1結(jié)點(xpath:/data/class[2]/book[2]),xml2結(jié)點(xpath:/data/class[2]/book[2]): 結(jié)點1屬性:price 值:15,結(jié)點2屬性:price 值:16 子結(jié)點不一樣:xml1結(jié)點(xpath:/data/class[2])比xml2結(jié)點(xpath:/data/class[2])多了以下子結(jié)點: /data/class[2]/rangk[1] 子結(jié)點不一樣:xml1結(jié)點(xpath:/data/class[2])比xml2結(jié)點(xpath:/data/class[2])少了以下子結(jié)點: /data/class[2]/addr[1]
到此這篇關(guān)于Python 基于xml.etree.ElementTree實現(xiàn)XML對比的文章就介紹到這了,更多相關(guān)Python 實現(xiàn)XML對比內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Tensorflow訓(xùn)練MNIST手寫數(shù)字識別模型
這篇文章主要為大家詳細介紹了Tensorflow訓(xùn)練MNIST手寫數(shù)字識別模型,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-02-02opencv-python圖像配準(匹配和疊加)的實現(xiàn)
圖像配準需是指對不同條件下得到的兩幅或多幅圖像進行匹配、疊加的過程。本文詳細的介紹了如何使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-06-06Python使用Appium在移動端抓取微博數(shù)據(jù)的實現(xiàn)
Appium是移動端的自動化測試工具,讀者可以類比為PC端的selenium。通過它,我們可以驅(qū)動App完成自動化的一系列操作,同樣也可以爬取需要的內(nèi)容,本文就來介紹一下如何在移動端抓取微博數(shù)據(jù),感興趣的可以了解一下2021-08-08Python Lambda函數(shù)使用總結(jié)詳解
這篇文章主要介紹了Python Lambda函數(shù)使用總結(jié)詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12