首页 > 编程语言 >python系列:Python3 XML处理模块详解

python系列:Python3 XML处理模块详解

时间:2024-05-25 19:58:37浏览次数:26  
标签:XML xml python text element __ ET root Python3

Python3 XML处理模块详解




Python3 XML处理模块详解

xml是一种固有的分层数据格式,最自然的表示方式是解析成树状,在配置文件中很多采用xml的形式进行配置存储。在xml的日常维护中,经常会涉及到对xml文件的增删改查,如果从零开始对xml进行硬解析也是一件很麻烦的事情。

Python3内置了xml处理模块xml.etree.ElementTree 可以帮助我们去解析xml,并支持对xml的增删改查。下面我们对该模块从增删改查四个方面进行探索

一:XML文件格式

xml总体看上去就是一个树状的分层结构,下面给出一个xml文件的样例,后面针对xml的增删改查操作就以该xml为例:

<?xml version="1.0" encoding="utf-8"?>
<addr_info id="中国">
   <R1 type="上海">
       <device_type>黄埔区</device_type>
       <username>admin</username>
       <people_num>一百万</people_num>
       <company>zte.com.cn</company>
   </R1>
   <SW3 type="南京">
       <device_type>江宁区</device_type>
       <username>admin</username>
       <people_num>两百万</people_num>
       <company>baidu.com.cn</company>
   </SW3>
</addr_info>

二:ElementTree解析XML文件

我们用ElementTree去解析上面的xml文件,具体用法如下:

import xml.etree.ElementTree as ET
 
 
tree = ET.parse('eg.xml')#直接读取xml文件,形成ElementTree结构
root = tree.getroot() # 获取root tag
print('tag:',root.tag) # 打印root的tag
print('attrib:',root.attrib) # 打印root的attrib
# 使用root索引访问标签的值,[0]是R1标签,[0]是R1标签中的第一个标签device_type, .text是取这个标签的值,自然值就是cisco_ios
print(root[0][0].text)
 
for child in root: # 打印root的child层的tag和attrib
   print(child.tag, child.attrib)

运行结果:

tag: addr_info
attrib: {'id': '中国', 'topic': 'ftz'}
黄埔区
R1 {'type': '上海'}
SW3 {'type': '南京'}

我们可以通过dir来查看root支持的属性

['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__',
 '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', 
'__init_subclass__', '__le__', '__len__', '__lt__', '__ne__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', 
'__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'attrib',
 'clear', 'extend', 'find', 'findall', 'findtext', 'get', 'getchildren', 
'getiterator', 'insert', 'items', 'iter', 'iterfind', 'itertext', 'keys', 
'makeelement', 'remove', 'set', 'tag', 'tail', 'text']

在这里插入图片描述

Element常用属性如下:

1、tag

tagstr对象,表示xml标签,例子中的前后闭合的device_type

2、attrib

attrib是一个dict对象,表示xml属性,例子中的type="上海"

3、text

text就是xml数据标签包裹的内容,也是Element的内容,例子中的 admin,一百万

4、child elements

child elements则是xml一对标签中包含的子集,类似于上面例子中R1SW3标签中包裹的内容

三:Element之查找

Element有很丰富的查找方法,总结如下:

iter(tag=None) 遍历Element的child,可以指定tag精确查找
findall(match) 查找当前元素tag或path能匹配的child节点
find(match) 查找当前元素tag或path能匹配的第一个child节点
get(key, default=None) 获取元素指定key对应的attrib,如果没有attrib,返回default。

我们用iterfindall为例来查找上述例子中的人口

import xml.etree.ElementTree as ET
 
 
tree = ET.parse('eg.xml')
root = tree.getroot()
 
#iter查找
for addr in root.iter():
    if addr.tag == 'people_num':
        print("people_num=",addr.text)
 
#findall查找
for people in root.findall('R1'):
    peopleNum = people.find('people_num').text
    print("people_num=",peopleNum)
 
for people in root.findall('SW3'):
    peopleNum = people.find('people_num').text
    print("people_num=",peopleNum)

运行结果:
在这里插入图片描述

四:Element之修改

Element的修改方法如下:

Element.text 直接修改字段
Element.remove() 删除字段
Element.set() 添加或修改属性attrib
with Element.append() 添加新的child 

我们将上海黄浦区的人口数从一百万改成一千万,首先需要找到R1节点,然后找到R1节点下的people_num的子节点,找到子节点对其内容进行修改,这就用到了上面提到的text属性,就是对text进行修改

import xml.etree.ElementTree as ET
 
 
tree = ET.parse('eg.xml')
root = tree.getroot()
 
 
for addr in root.iter('R1'):
    addr.find('people_num').text = '一千万'
 
tree.write('./eg2.xml',encoding='utf-8')

在这里插入图片描述

确认修改完毕后,需要使用ElementTree.write()方法写入,write的使用方法如下:

在这里插入图片描述

五:Element之删除

Element的删除方法如下:

remove  移除节点

我们还是以上面为例,删除整个SW3节点

import xml.etree.ElementTree as ET
 
 
tree = ET.parse('eg.xml')
root = tree.getroot()
 
for addr in root.findall('SW3'):
    root.remove(addr)
 
tree.write('./eg2.xml',encoding='utf-8'

在这里插入图片描述

那如果我想删除R1节点的子节点username呢,还没摸索出来,后续更新

六:Element之增加

Element的增加节点方法如下:

ET.SubElement

我们新增一个节点黄冈的节点,还有节点下面的子节点,方法如下:

import xml.etree.ElementTree as ET
 
 
xmlParse = ET.parse('eg.xml')
root = xmlParse.getroot()
tree = ET.ElementTree(root)
 
#增加R3节点
hubeiNode = ET.SubElement(root,'R3')
hubeiNode.attrib = {'type':'黄冈'}
#增加R3节点的子节点
 
huanggang = ET.SubElement(hubeiNode,'device_type')
huanggang.text = '黄梅县'
 
huanggang2 = ET.SubElement(hubeiNode,'username')
huanggang2.text = 'admin'
 
huanggang3 = ET.SubElement(hubeiNode,'people_num')
huanggang3.text = '五十万'
 
huanggang4 = ET.SubElement(hubeiNode,'company')
huanggang4.text = 'feidadun.com'
 
tree.write('./eg2.xml', encoding='utf-8', xml_declaration=True, short_empty_elements=True)

在这里插入图片描述

虽然达到了我们的目的,但是写入后都挤到一行了,不方便看,用下面的函数进行美化

def pretty_xml(element, indent, newline, 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)  # 对子元素进行递归操作

最后的效果如下:
在这里插入图片描述

附上全部代码:

import xml.etree.ElementTree as ET
 
 
def pretty_xml(element, indent, newline, 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)  # 对子元素进行递归操作
 
xmlParse = ET.parse('eg.xml')
root = xmlParse.getroot()
tree = ET.ElementTree(root)
 
#增加R3节点
hubeiNode = ET.SubElement(root,'R3')
hubeiNode.attrib = {'type':'黄冈'}
#增加R3节点的子节点
 
huanggang = ET.SubElement(hubeiNode,'device_type')
huanggang.text = '黄梅县'
 
huanggang2 = ET.SubElement(hubeiNode,'username')
huanggang2.text = 'admin'
 
huanggang3 = ET.SubElement(hubeiNode,'people_num')
huanggang3.text = '五十万'
 
huanggang4 = ET.SubElement(hubeiNode,'company')
huanggang4.text = 'feidadun.com'
 
pretty_xml(root, '  ', '\n')  # 执行美化方法    缩进为两个空格,'\n'换行
tree.write('./eg2.xml', encoding='utf-8', xml_declaration=True, short_empty_elements=True)

七:Element之排序

import xml.etree.ElementTree as ET
import re
 
 
# 读取XML文件
tree = ET.parse('test.xml')
 
# 获取根元素
root = tree.getroot()
 
def sortkey(child):
    str = child.attrib.get('navtitle')
    if str:
        key = str[:5]
        if key.isdigit:
            return key
    else:
        return '0'
 
# 获取所有子节点并进行排序
root[:] = sorted(root, key=lambda child: sortkey(child))
 
# 输出新的XML文件
tree.write('test_sorted.xml',encoding='utf-8')







ftzchina

Python3 XML处理模块详解

标签:XML,xml,python,text,element,__,ET,root,Python3
From: https://blog.csdn.net/weixin_54626591/article/details/139198773

相关文章

  • 量化交易:海龟交易法则的Python实现
    哈喽,大家好,我是木头左!海龟交易法则是由著名的商品交易大师理查德·丹尼斯(RichardDennis)和威廉·埃克哈特(WilliamEckhardt)在20世纪80年代开发的一套交易策略。海龟交易法则以其简单性和趋势跟踪的核心理念而闻名,它证明了通过一套明确的交易规则,即使是没有交易经验的人也可以在......
  • 用 Python 编写网络爬虫:从网页获取数据并存储到 Excel 文件
    在本篇博客中,我们将介绍如何使用Python编写一个简单的网络爬虫,用于从网页中提取数据,并将这些数据存储到Excel文件中。我们将使用Python中的一些库来实现这个功能,包括urllib.request、BeautifulSoup和openpyxl。1.网络爬虫的基本原理网络爬虫是一种程序,可以自动访问......
  • 基于python+django框架旅游景区景点购票系统设计与实现(源码+LW+安装+基础课)
     博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。项目配有对应开发文档、开题报告、任务书、P......
  • Python一个简单的单元测试
    Python一个简单的单元测试提示:以下内容均为个人原创!文章目录Python一个简单的单元测试一、介绍二、使用1.创建逻辑代码2.生成单元测试3.生成单元测试的方式(1).直接在逻辑代码中添加(2).单独制作4.运行代码总结一、介绍在使用Python制作模块后,总是不确定模块中......
  • VOC数据格式转YOLO(xml转txt)
            近日想训练yolov8模型,在网上找了很久公开数据集,好多都没有数据标注,好不容易找到一篇好的数据集,但是都是xml格式的,因此得想办法把xml格式转为yolo格式。    首先观察xml数据集格式:我圈出来比较重要的几条filename:就是xml标签所对应的图片的名字wid......
  • Python-GEE遥感大数据分析
    随着航空、航天、近地空间遥感平台的持续发展,遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升,呈现出大数据特征。这为相关研究带来了新机遇,但同时也带来巨大挑战。传统的工作站和服务器已无法满足大区域、多尺度海量遥感数据处理需求。为解......
  • 【Python进阶】轻松上手,6种打包Python代码的方法,让你的程序变成exe应用!
    Python是一种高级编程语言,它具有易学易用、跨平台等优点,因此在开发中得到了广泛的应用。然而,Python代码需要在Python解释器中运行,这对于一些用户来说可能不太方便。因此,将Python代码打包成可执行文件(exe)是一种很好的解决方案。本文将介绍6种将Python代码打包成exe应用的方......
  • 通过Python爬取公告内容
    在网络时代,信息获取变得更加便捷。通过网络爬虫技术,我们可以从互联网上快速获取各种信息。本文将介绍如何使用Python爬虫工具从指定网站上获取公告内容,并提取其中的关键信息。1.简介在本文中,我们将使用Python的requests库和BeautifulSoup库来实现网页内容的获取和解......
  • Python--List列表
    list列表⭐⭐1高级数据类型Python中的数据类型可以分为:数字型(基本数据类型)和非数字型(高级数据类型)●数字型包含:整型int、浮点型float、布尔型bool、复数型complex●非数字型包含:字符串str、列表list、元组tuple、集合set、字典dict高级数据类型的特点●都是一个序列se......
  • Java读取word文件 No valid entries or contents found, this is not a valid OOXML (
    有个项目涉及到了操作word文档,当我把一份未加密word文档放在项目resources目录下进行临时开发,读取这个word时报错:Causedby:org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException:Novalidentriesorcontentsfound,thisisnotavalidOOXML(OfficeOpenXML......