xml.etree.ElementTree功能介绍

Posted lambda派

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xml.etree.ElementTree功能介绍相关的知识,希望对你有一定的参考价值。

本文约2200字,建议阅读时间11~14分钟

关键字:python,xml,可扩展标记语言,xml.etree.ElementTree

 

假设当前工作目录下存在data.xml文件,其内容如下:


1、XML文件的解析

(1)读取xml文件

import  xml.etree.ElementTree as ET

 

tree=ET.parse('data.xml')

#返回ElementTree对象

 

root=tree.getroot()

#返回Element对象

#亦可通过ET.fromstring(xml_string)来解析xml格式的根元素

 

(2)获取Element对象的标签

root.tag

#返回’data’

 

(3)获取Element对象的属性字典

root.attrib

#返回{}

 

(4)通过节点嵌套索引获取子节点信息

root[1][2].text

#返回’50’

 

注:建议通过API进行解析而不是通过xml文本,通过API解析的文档通常包含注释和处理指令。

 

2、非阻塞解析的Pull API

xml.etree.ElementTree模块提供的许多解析函数在返回结果前需要立刻读取整个文档,但有时我们需要在享受全文档带来便利的同时逐步解析xml文档而不产生阻塞,该模块提供的XMLPullParser.就是满足该条件的最有效的解析工具,它解析xml文档时不需要阻塞读取数据,而是通过feed方法来逐步读取,为了解析xml文档的元素,可以通过read_events方法来实现。

 

如果在读取xml数据不在乎阻塞且仍希望逐步获得逐步解析的能力,可以使用iterparser,它在读取大规模xml文档时且不想整体存入内存时很有用。

 

parser=ET.XMLPullParser(['start','end'])

parser.feed('<a>text1 ')

parser.feed('text2</a>')

for event,elem in parser.read_events():

print(event,elem.tag,elem.text)

#返回:

start a text1 text2

end a text1 text2

 

3、查找感兴趣的元素

(1)获取所有子树的元素

for friend in root.iter('friend'):

print(friend.attrib)

#返回:

{'name': 'Mary', 'relationship': 'lover'}

{'name': 'Peter', 'relationship': 'classmate'}

{'name': 'White', 'relationship': 'neighbour'}

 

(2)获取直接孩子的元素

for people in root.findall('people'):

    name=people.get('name')

    gender=people.find('gender').text

    age=people.find('age').text

    weight=people.find('weight').text

print(name,gender,age,weight)

#返回:

Jack male 30 65

Anna female 20 50

 

4、修改xml文件

ElementTree提供一种生成xml文档并将其写入(write()方法)文件的简单方法。一旦创建,Element对象的文本(Element.text)将可以直接改变,增加和修改属性(Element.set()方法),也可以增加新的孩子节点(Element.append()方法),移除某些节点(Element.remove()方法).

 

修改Element对象的值

for age in root.iter('age'):

    age=int(age.text)+1

age.text=str(age)

 

增加Element对象的属性

for age in root.iter('age'):

age.set('is_modified','yes')

 

移除Element对象的节点

for people in root.findall('people'):

    gender=people.find('gender').text

    if gender=='female':

        root.remove(people)

 

注:当迭代时采用并行修改会像迭代python中列表和字典一样导致一些问题,所以一般采用findall()方法来匹配。

 

5、生成xml文件

SubElement()方法提供了一种简便创建子元素的方法。

 

x=ET.Element('x')

y=ET.SubElement(x,'y',attrib={'yy':'attr_y'})

z=ET.SubElement(x,'z')

m=ET.SubElement(z,'m',attrib={'mm':'attr_m'})

 

ET.dump(x)

#返回<x><y yy="attr_y" /><z><m mm="attr_m" /></z></x>

 

6、解析带命名空间的xml

xml文档中使用命名空间是为了解决处理不同文档时的命名冲突,常常在相同标签和属性前添加前缀,如prefix:tag、prefix:attr等,通常用于URI(统一资源标识符)的替换。

 

xml_text='''<?xml version="1.0"?>

<marks xmlns:other="http://specific.example.com"

        xmlns="http://base.example.com">

    <mark>

        <location>left</location>

        <other:example>something is best</other:example>

    </mark>

    <mark>

        <location>right</location>

        <other:example>something is better</other:example>

        <other:example>something is good</other:example>

    </mark>

</marks>

'''

root_s=ET.fromstring(xml_text)

 

ns={"base":"http://base.example.com",

   "specific":"http://specific.example.com"}

 

for mark in root_s.findall('base:mark',ns):

    location=mark.find('base:location',ns).text

    for example in mark.findall('specific:example',ns):

        print(f'{location}->{example.text}')

#返回:

left->something is best

right->something is better

right->something is good

#注:xmlns名称不能为其他,否则无法解析

 

7、xpath表达式

(1)xpath语法

tag:筛选出名称为tag的所有子元素

tag/tag1:筛选出名称为tag的所有子元素下名称为tag1的所有孙元素

{namespace}*:筛选出命名空间为namespace的所有元素

{*}tag:筛选出在任意命名空间或者无命名空间且名称为tag的元素

{}*:筛选出不在命名空间的元素

注:python3.8增加了星号通配符

 

*:筛选出所有子元素,包括注释与处理指令

 

.:筛选出当前节点

#常用于相对路径

 

//:筛选出当前元素下方所有后代元素

 

..:筛选出父元素

#开始元素的父元素将返回None

 

[@attr]:筛选出属性为attr的所有元素

 

[@attr=’value’]:筛选出属性为attr且值为value的所有元素

#注:value不能够包含引号

 

[tag]:筛选出子元素名称为tag的所有元素

 

[.=’text’]:筛选出当前元素及其后代文本为text的所有元素

 

[tag=’text’]:筛选出孩子名称为tag,且当前元素及其后代文本为text的所有元素

 

[position]:筛选出位置为position的所有元素

#position既可以是整数,也可以是表达式,如last()或者与表达式相关的形式,如last()-1

 

(2)例子

for child in root.findall('./people/friend'):

   print(child.get('name'))

#返回:

Mary

Peter

White

 

for child in root.findall('.//friend[1]'):

   print(child.get('name'))

#返回:

Mary

White

 

8、包含指令

xml.etree.ElementInclude模块可支持包含指令,该模块可被用于向树中添加子树和文本。在当前文件中导入XML或者txt文件,可通过{url}include元素并设置parse属性为xml或者text,并使用href属性来特指包含的文件。

 

xml_text1='''

<?xml version="1.0"?>

<document xmlns:other="http://www.***/XInclude">

  <other:include href="include.xml" parse="xml" />

</document>

'''

 

from xml.etree import ElementInclude

root_s1=ET.fromstring(xml_text1)

ElementInclude.include(root_s1)

 

假设include.xml的内容为’This is included content.’,那么root_s1将转换成如下内容:

<?xml version="1.0"?>

<document xmlns:other="http://www.myweb/XInclude">

  <para>This is included content.</para>

</document>

(完)

欢迎关注【lambda派】!


相关阅读:


以上是关于xml.etree.ElementTree功能介绍的主要内容,如果未能解决你的问题,请参考以下文章

Python解析xml文件

python解析xml文件之xml.etree.cElementTree和xml.etree.ElementTree区别

使用 xml.etree.ElementTree 在 python 中解析 XML

python-23 xml.etree.ElementTree模块

术业有专攻:xml.etree.ElementTree

python - xml.etree.ElementTree.ParseError:格式不正确(无效令牌)