python --- ElementTree解析xml 增删改查

直接上代码

python 中xml库 ElementTree的使用

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : xml.py
# @Author: shadow
# @Date  : 2020/10/30
# @Desc  : xml 

import time, os
import xml.etree.ElementTree as ET


# 处理XML缩进和换行
def pretty_xml(element, indent='\t', newline='\n', level=0):  # elemnt为传进来的Elment类,参数indent用于缩进,newline用于换行
    if element:  # 判断element是否有子元素
        if (element.text is None) or element.text.isspace():  # 如果element的text没有内容
            element.text = newline + indent * (level + 1)
        else:
            element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1)
            # else:  # 此处两行如果把注释去掉,Element的text也会另起一行
            # element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
    temp = list(element)  # 将element转成list
    for subelement in temp:
        if temp.index(subelement) < (len(temp) - 1):  # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
            subelement.tail = newline + indent * (level + 1)
        else:  # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
            subelement.tail = newline + indent * level
        pretty_xml(subelement, indent, newline, level=level + 1)  # 对子元素进行递归操作


class Param:
    def __init__(self, param_file, root_node=""):
        self.file = param_file
        if os.path.exists(param_file):
            self.tree = ET.parse(param_file)
            self.root = self.tree.getroot()
        else:   # 新建xml文件
            if not root_node:
                print("No root_node")
                raise NameError
            self.root = ET.Element(root_node)
            self.tree = ET.ElementTree(self.root)

    # 修改节点
    def set_note(self, param, node):
        if param.get('text'): node.text = param['text']
        if param.get('attrib'): node.attrib = param['attrib']

    # 添节点
    def add_note(self, param, parent):
        '''
        param: 节点信息字典,(key:节点名,value:节点内容包括text和attrib)
        parent: 添加位置(父节点)
        '''
        for name, value in param.items():
            node = parent.find(name)
            if isinstance(node, ET.Element):    # 注意:使用 if node判断不能得到是否有节点 ???, 可以使用findall + for
                self.set_note(value, node)
            else:
                node = ET.Element(name)
                if value.get('text'): node.text = value['text']
                if value.get('attrib'): node.attrib = value['attrib']
                parent.append(node)
        self.update()

    # 删除节点,可以匹配属性参数
    def del_node(self, name, parent, param={}):
        '''
        name: 节点名
        parent: 添加位置(父节点)
        param: key:属性名,value:属性值
        '''
        nodes = parent.findall(name)
        for node in nodes:
            if param:
                for k, v in param.items():
                    if node.get(k) != v:   # 给的属性参数有不匹配,不删除
                        break
                else:
                    parent.remove(node)
            else:
                parent.remove(node)
        self.update()

    # 查找节点
    def find_node(self, name):
        nodes = self.root.iter(name)
        return self.get_note(nodes)

    # 获取节点信息,转成字典
    def get_note(self, start=''):
        '''
        tag: 保存数据字典
        start: 起始节点(默认根节点)
        '''
        
        tag = {}
        if not start:
            start = self.root
        # print(start)
        for node in start:
            if list(node):  # 有子节点
                # print(node, node.tag, tag)
                tag[node.tag] = self.get_note(node)  # 递归执行
            else:
                tag[node.tag] = {}
                if node.text:
                    tag[node.tag]['text'] = node.text
                if node.attrib:
                    tag[node.tag]['attrib'] = node.attrib
        return tag

    # 更新xml
    def update(self):
        # save_path = 'camera_params_' + self.time.split()[0] + '.xml'
        pretty_xml(self.root)
        # print(list(self.root))
        self.tree.write(self.file, 'UTF-8', xml_declaration=True)


if __name__ == '__main__':
    param = Param('./camera_params1.xml', "shadow")
    param.add_note({'shadow': {'attrib': {'age': '30', 'sex': 'male'}}}, param.root)
    # param.add_note({'about': {'attrib': {'author': 'shadow', 'email': 'yinlu@flyaudio.cn',
    #     'date': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}}}, param.root)
    # param.del_node('shadow', param.root, {'age': 30, 'sex': 'male'})

    # param.update()
    tag = param.get_note()
    print(tag)
    print(param.find_node('eason'))

xml文件

<?xml version='1.0' encoding='UTF-8'?>
<student>
	<test>
		<test1>
			<eason> shadow eason </eason>
		</test1>
		<test2> test2 </test2>
		<test3> test3 </test3>
	</test>
	<shadow age="30" sex="male"> handsome boy </shadow>
</student>

执行结果

{'test': {'test1': {'eason': {'text': ' shadow eason '}}, 'test2': {'text': ' test2 '}, 'test3': {'text': ' test3 '}}, 'shadow': {'text': ' handsome boy ', 'attrib': {'age': '30', 'sex': 'male'}}}
{'eason': {'text': ' shadow eason '}}

代码中将节点信息转成了字典,方便后续使用

常用函数说明
  • ET.ElementTree(xxx.xml):生成文档对象
  • tag:标签名
  • text:子节点的内容
  • attrib:子节点的属性
  • append(son):为当前节点添加个子节点
  • get(aa):获取当前节点xx中属性aa(key)的值
  • set(key,value):设置当前节点的属性值,最后再write写入文件
  • keys():获取当前节点所有属性的keys,返回列表
  • items():获取当前节点的所有属性值,每对属性都是键值对
  • find(xxx):获取第一个寻找到的xxx子节点
  • findtext(xxx):获取到第一个找到的子节点xxx的内容
  • findall(xxx):获取所有的xxx节点
  • iter(xxx):遍历获取指定节点xxx,并返回一个迭代器
  • iterfind(xxx):遍历获取指定节点xxx,并返回一个迭代器
  • itertext():获取当前节点中子孙节点的所有内容,并返回一个迭代器
  • makeelement(xxx):创建一个新的节点xxx,仅为创建
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值