本文在上两篇文章的基础上,更进一步,谈一谈lxml的封装,博主下面的代码涵盖了lxml的一些常用功能,包括增、删、改、查、读取、输出等。
提示:以下是本篇文章正文内容,下面案例可供参考
转载记得标明出处哦
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Author: craftsman2020 # @Date : 2020/08/11 13:30 from __future__ import print_function from lxml import etree class XML(object): def __init__(self): self.et = etree.ElementTree() self.root = self.et.getroot() self.parser = etree.XMLParser(remove_blank_text=True) # def read_file(self, file_path): """ 解析xml文件 :param file_path: xml文件的路径 :return: 返回根节点,Element对象。 """ self.et = etree.parse(file_path, self.parser) self.root = self.et.getroot() return self.root def read_str(self, text): """ 解析字符串为xml :param text: 字符串 :return: 返回根节点,Element对象 """ self.root = etree.fromstring(text) self.et = etree.ElementTree(self.root, parser=self.parser) # 或者 self.et = self.root.getroottree() return self.root def find_direct_child(self, tag): """ 找直接子元素中的第一个标签为tag的节点 :param tag: 节点的tag、或tag的路径。字符串类型 :return:返回Element对象 """ return self.root.find(tag) def find_direct_nodes(self, tag): """ 找直接子元素中的所有的标签为tag的节点 :param tag: 节点的tag、或tag的路径。字符串类型 :return: 返回包含Element对象的list """ return self.root.findall(tag) def match_all_nodes(self, tag, att_dic=None): """ 匹配所有子孙节点中,符合条件的所有节点 :param tag: 节点的tag :param att_dic: 属性dict :return: 返回匹配到的节点,Element对象 """ if att_dic is None: att_dic = {} match_res = [] not_match_dic = {} for elem in self.root.getiterator(): if elem.tag == tag: match_res.append(elem) if att_dic: for att in att_dic: if att_dic.get(att) != elem.get(att): not_match_dic.update({elem: False}) for d in not_match_dic: match_res.remove(d) return match_res def is_exist(self, tag, att_dic=None): """ 判断所有子孙节点中,符合条件的节点是否存在 :param tag: 节点的tag :param att_dic: 属性dict :return: 存在则返回True,反之返回False """ if self.match_all_nodes(tag, att_dic): return True else: return False def add_child_nodes(self, node, site=-1): """ 添加子节点 :param node: Element对象 :param site: 插入节点的位置,默认-1,表示在尾部追加 :return: """ if site == -1: self.root.append(node) elif site >= 0: self.root.insert(site, node) def add_node_to_parent(self, parent, child, site=-1): """ 给父节点增加子节点 :param parent: 父节点 :param child: 子节点 :param site: append :return: """ parent_node = self.match_all_nodes(parent.tag, parent.attrib)[0] if site == -1: parent_node.append(child) elif site >= 0: parent_node.insert(site, child) @staticmethod def update_nodes_properties(nodelist, attrib, delete=False): """ 增加/修改/删除 节点的属性 :param nodelist: 节点list :param attrib: 属性dict :param delete: 是否删除,默认False :return: """ for node in nodelist: for att in attrib: if delete: del node.attrib[att] else: node.set(att, attrib[att]) @staticmethod def update_nodes_texts(nodelist, text, add=False, delete=False): """ 增加/修改/删除 节点的文本 :param nodelist: 节点list :param text: text :param add: 是否增加,默认False :param delete: 是否删除,默认False :return: """ for node in nodelist: if add: if not node.text: node.text = text else: node.text += text if delete: node.text = "" else: node.text = text def del_nodes(self, tag, att_dic=None): """ 删除所有符合要求的节点 :param tag: 节点的tag :param att_dic: 属性dict """ node_list = self.match_all_nodes(tag, att_dic) for node in node_list: parent_node = node.getparent() try: parent_node.remove(node) except: pass def del_nodes_by_tag(self, tag): """ 删除所有子孙节点中标签为tag的节点 :param tag 标签名,字符串类型 """ etree.strip_elements(self.root, tag) def del_all_attrib(self, attrib_name): """ 删除所有子孙节点中具有该属性名的属性 :param attrib_name: 属性名 """ etree.strip_attributes(self.root, attrib_name) def write(self, out_path): """ 写入xml文件 :param out_path: 写入的xml文件名 """ self.et.write(out_path, pretty_print=True, with_tail=False, encoding="utf-8", xml_declaration=True)代码如下(示例):
xml = XML() # 读取xml文件 xml.read_file('./sample.xml') # 打印根节点 print(xml.root) <Element TradingAccounts at 0x4b1fc88> # 查找tag为Constants的节点,返回Element对象 Constants = xml.find_direct_child('Constants') # 打印Constants的属性 print(Constants.attrib) {'cpu': '10', 'path': '/home/DOTA/Trade', 'ProjectName': 'DOTA'} # 查找Constants节点的cpu属性的值 print(xml.find_direct_child('Constants').get('cpu')) 10 # 查找匹配到的第一个路径Strategies/Strategy, 并打印其属性 print(xml.find_direct_child('Strategies/Strategy').attrib) {'commission': 'flase', 'name': 'CTA01', 'trade': 'true'} # 查找目标tag或路径下的所有直接子元素 Accounts = xml.find_direct_nodes('Accounts/Account') print(Accounts) [<Element Account at 0x4b7fe08>, <Element Account at 0x4b7fb48>, <Element Account at 0x4b15188>] # 打印匹配到的第一个节点 print(Accounts[0]) <Element Account at 0x4b7fe08> # 匹配到的所有符合条件的节点 xx = xml.match_all_nodes(tag="Strategy", att_dic={'num': "2", 'prior': "1"}) print([i.attrib for i in xx]) [{'prior': '1', 'name': 'CTA01', 'id': '999', 'num': '2'}] # 判断所有子孙节点中,某节点是否存在 print("xml.is_exist('Strategy') = ", xml.is_exist('Strategy')) print("xml.is_exist('xxxxxx') = ", xml.is_exist('xxxxxx')) xml.is_exist('Strategy') = True xml.is_exist('xxxxxx') = False # 增加子节点 child1 = etree.SubElement(_parent=xml.root, _tag='add_sub1', attrib={'id': '1'}) child1.text = 'girl' xml.add_child_nodes(child1) child2 = etree.Element(_tag='add_element1', attrib={'id': '2'}) child2.text = 'i am a boy' xml.add_child_nodes(child2) # 给指定节点增加子节点 grandson1 = etree.Element(_tag='add_grandson1', attrib={'id': '3'}) grandson1.text = 'my name is grandson' xml.add_node_to_parent(parent=xml.match_all_nodes('add_sub1', att_dic={'id': '1'})[0], child=grandson1) grandson2 = etree.Element(_tag='add_grandson2', attrib={'id': '4'}) grandson2.text = 'i like play piano' xml.add_node_to_parent(parent=xml.match_all_nodes('Strategy', att_dic={'name': "CTA01", 'num': "3", 'prior': "1", 'id': "997"})[0], child=grandson2) # 匹配所有符合条件的节点,返回list target_list = xml.match_all_nodes('Strategy', att_dic={'name': "CTA01"}) print('target_list = ', target_list) target_list = [<Element Strategy at 0x6012408>, <Element Strategy at 0x6012808>, <Element Strategy at 0x60115c8>, <Element Strategy at 0x60127c8>] # 删除指定节点的的属性 xml.update_nodes_properties(target_list, attrib={'name': "CTA01"}, delete=True) # 给指定节点增加text xml.update_nodes_texts(target_list, text='### 2020 ###', add=True) # 删除符合条件的节点 xml.del_nodes(tag='Strategy', att_dic={'name': "CTA02"}) # 根据tag直接删除所有节点 xml.del_nodes_by_tag('Strategy') # 删除所有节点的指定属性 xml.del_all_attrib('name') # 写入xml xml.write('./lxml_example.xml') xml_str = """ <root> <a x='123'>aText <b/> <c/> </a>hello <a y='3'>Text <b/> <b/> </a> </root> """ # 解析字符串 my_xml = XML() my_xml.read_str(xml_str) # 打印根节点 print(my_xml.root) print(type(my_xml.root)) <Element root at 0x6012848> <class 'lxml.etree._Element'> # 删除所有tag为a的节点 etree.strip_elements(my_xml.root, 'a') etree.dump(my_xml.root) <root> </root>点击下方链接下载,或评论下方留言@博主发送 代码及xml文件下载
XML基础速成 彻底掌握python中的lxml (一)