xml.etree.ElementTree
— ElementTree XML API¶
源代码: Lib/xml/etree/ElementTree.py
xml.etree.ElementTree
模块实现了用于解析和创建 XML 数据的简单高效的 API。
3.3 版本中的更改: 此模块将在可用时使用快速实现。
自 3.3 版本弃用: xml.etree.cElementTree
模块已弃用。
备注
如果您需要解析不受信任或未经身份验证的数据,请参阅 XML 安全。
教程¶
这是使用 xml.etree.ElementTree
(简称 ET
)的简短教程。目的是演示模块的一些构建块和基本概念。
XML 树和元素¶
XML 是一种固有的层次化数据格式,最自然的表示方式是树。ET
为此提供了两个类——ElementTree
表示整个 XML 文档的树,而 Element
表示树中的单个节点。与整个文档的交互(从文件读取和写入)通常在 ElementTree
级别进行。与单个 XML 元素及其子元素的交互在 Element
级别进行。
解析 XML¶
我们将使用虚构的 country_data.xml
XML 文档作为本节的示例数据
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
我们可以通过从文件读取来导入此数据
import xml.etree.ElementTree as ET
tree = ET.parse('country_data.xml')
root = tree.getroot()
或者直接从字符串中读取
root = ET.fromstring(country_data_as_string)
fromstring()
直接将字符串中的 XML 解析为 Element
,它是解析树的根元素。其他解析函数可能会创建 ElementTree
。请查阅文档以确保。
作为 Element
,root
有一个标签和属性字典
>>> root.tag
'data'
>>> root.attrib
{}
它也有子节点,我们可以迭代它们
>>> for child in root:
... print(child.tag, child.attrib)
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}
子节点是嵌套的,我们可以通过索引访问特定的子节点
>>> root[0][1].text
'2008'
备注
并非所有 XML 输入的元素都会成为解析树的元素。目前,此模块跳过输入中的任何 XML 注释、处理指令和文档类型声明。然而,使用此模块的 API 而不是从 XML 文本解析构建的树可以包含注释和处理指令;它们将在生成 XML 输出时包含在内。可以通过将自定义 TreeBuilder
实例传递给 XMLParser
构造函数来访问文档类型声明。
用于非阻塞解析的 Pull API¶
此模块提供的大多数解析函数都需要一次性读取整个文档才能返回任何结果。可以使用 XMLParser
并逐步向其馈送数据,但它是一个推式 API,在回调目标上调用方法,这对于大多数需求来说太底层且不方便。有时用户真正想要的是能够增量解析 XML,而无需阻塞操作,同时享受完全构建的 Element
对象的便利。
实现此目的最强大的工具是 XMLPullParser
。它不需要阻塞读取来获取 XML 数据,而是通过 XMLPullParser.feed()
调用逐步馈送数据。要获取解析的 XML 元素,请调用 XMLPullParser.read_events()
。这是一个示例
>>> parser = ET.XMLPullParser(['start', 'end'])
>>> parser.feed('<mytag>sometext')
>>> list(parser.read_events())
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
>>> parser.feed(' more text</mytag>')
>>> for event, elem in parser.read_events():
... print(event)
... print(elem.tag, 'text=', elem.text)
...
end
mytag text= sometext more text
显而易见的用例是应用程序以非阻塞方式运行,其中 XML 数据正在从套接字接收或从某些存储设备增量读取。在这种情况下,阻塞读取是不可接受的。
由于其高度灵活性,XMLPullParser
对于简单用例可能不方便使用。如果您不介意应用程序在读取 XML 数据时阻塞,但仍然希望具有增量解析功能,请查看 iterparse()
。当您正在读取大型 XML 文档并且不想将其完全保存在内存中时,它会很有用。
如果需要通过事件获得 即时 反馈,调用方法 XMLPullParser.flush()
可以帮助减少延迟;请务必研究相关的安全说明。
查找感兴趣的元素¶
Element
有一些有用的方法,可以帮助递归迭代其下的所有子树(其子元素、孙元素等)。例如,Element.iter()
>>> for neighbor in root.iter('neighbor'):
... print(neighbor.attrib)
...
{'name': 'Austria', 'direction': 'E'}
{'name': 'Switzerland', 'direction': 'W'}
{'name': 'Malaysia', 'direction': 'N'}
{'name': 'Costa Rica', 'direction': 'W'}
{'name': 'Colombia', 'direction': 'E'}
Element.findall()
仅查找标签是当前元素的直接子元素的元素。Element.find()
查找具有特定标签的 第一个 子元素,Element.text
访问元素的文本内容。Element.get()
访问元素的属性
>>> for country in root.findall('country'):
... rank = country.find('rank').text
... name = country.get('name')
... print(name, rank)
...
Liechtenstein 1
Singapore 4
Panama 68
通过使用 XPath 可以进行更复杂的元素查找规范。
修改 XML 文件¶
ElementTree
提供了一种构建 XML 文档并将其写入文件的简单方法。ElementTree.write()
方法用于此目的。
一旦创建,Element
对象可以通过直接更改其字段(例如 Element.text
)、添加和修改属性(Element.set()
方法)以及添加新子元素(例如使用 Element.append()
)来操作。
假设我们希望将每个国家的排名加一,并向排名元素添加一个 updated
属性
>>> for rank in root.iter('rank'):
... new_rank = int(rank.text) + 1
... rank.text = str(new_rank)
... rank.set('updated', 'yes')
...
>>> tree.write('output.xml')
我们的 XML 现在看起来像这样
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>
我们可以使用 Element.remove()
删除元素。假设我们想要删除所有排名高于 50 的国家
>>> for country in root.findall('country'):
... # using root.findall() to avoid removal during traversal
... rank = int(country.find('rank').text)
... if rank > 50:
... root.remove(country)
...
>>> tree.write('output.xml')
请注意,迭代时并发修改可能会导致问题,就像迭代和修改 Python 列表或字典时一样。因此,示例首先使用 root.findall()
收集所有匹配的元素,然后才迭代匹配列表。
我们的 XML 现在看起来像这样
<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
</data>
构建 XML 文档¶
SubElement()
函数还提供了一种方便的方式为给定元素创建新的子元素
>>> a = ET.Element('a')
>>> b = ET.SubElement(a, 'b')
>>> c = ET.SubElement(a, 'c')
>>> d = ET.SubElement(c, 'd')
>>> ET.dump(a)
<a><b /><c><d /></c></a>
使用命名空间解析 XML¶
如果 XML 输入具有命名空间,则形式为 prefix:sometag
的带有前缀的标签和属性将扩展为 {uri}sometag
,其中 prefix 被完整的 URI 替换。此外,如果存在默认命名空间,则该完整 URI 将添加到所有未加前缀的标签中。
这是一个包含两个命名空间的 XML 示例,一个带前缀“fictional”,另一个用作默认命名空间
<?xml version="1.0"?>
<actors xmlns:fictional="http://characters.example.com"
xmlns="http://people.example.com">
<actor>
<name>John Cleese</name>
<fictional:character>Lancelot</fictional:character>
<fictional:character>Archie Leach</fictional:character>
</actor>
<actor>
<name>Eric Idle</name>
<fictional:character>Sir Robin</fictional:character>
<fictional:character>Gunther</fictional:character>
<fictional:character>Commander Clement</fictional:character>
</actor>
</actors>
搜索和浏览此 XML 示例的一种方法是在 find()
或 findall()
的 xpath 中手动将 URI 添加到每个标签或属性
root = fromstring(xml_text)
for actor in root.findall('{http://people.example.com}actor'):
name = actor.find('{http://people.example.com}name')
print(name.text)
for char in actor.findall('{http://characters.example.com}character'):
print(' |-->', char.text)
搜索带命名空间的 XML 示例的更好方法是使用您自己的前缀创建一个字典并在搜索函数中使用这些前缀
ns = {'real_person': 'http://people.example.com',
'role': 'http://characters.example.com'}
for actor in root.findall('real_person:actor', ns):
name = actor.find('real_person:name', ns)
print(name.text)
for char in actor.findall('role:character', ns):
print(' |-->', char.text)
这两种方法都输出
John Cleese
|--> Lancelot
|--> Archie Leach
Eric Idle
|--> Sir Robin
|--> Gunther
|--> Commander Clement
XPath 支持¶
此模块对 XPath 表达式 提供了有限的支持,用于在树中定位元素。目标是支持缩写语法的一小部分;完整的 XPath 引擎超出模块的范围。
示例¶
这是一个演示模块某些 XPath 功能的示例。我们将使用 解析 XML 部分中的 countrydata
XML 文档
import xml.etree.ElementTree as ET
root = ET.fromstring(countrydata)
# Top-level elements
root.findall(".")
# All 'neighbor' grand-children of 'country' children of the top-level
# elements
root.findall("./country/neighbor")
# Nodes with name='Singapore' that have a 'year' child
root.findall(".//year/..[@name='Singapore']")
# 'year' nodes that are children of nodes with name='Singapore'
root.findall(".//*[@name='Singapore']/year")
# All 'neighbor' nodes that are the second child of their parent
root.findall(".//neighbor[2]")
对于带命名空间的 XML,请使用通常的合格 {namespace}tag
符号
# All dublin-core "title" tags in the document
root.findall(".//{http://purl.org/dc/elements/1.1/}title")
支持的 XPath 语法¶
语法 |
含义 |
---|---|
|
选择所有具有给定标签的子元素。例如, 3.8 版本中的更改: 增加了对星号通配符的支持。 |
|
选择所有子元素,包括注释和处理指令。例如, |
|
选择当前节点。这在路径开头最有用,表示这是一个相对路径。 |
|
选择所有子元素,在当前元素下的所有级别上。例如, |
|
选择父元素。如果路径尝试访问起始元素(调用 |
|
选择所有具有给定属性的元素。 |
|
选择给定属性具有给定值的所有元素。该值不能包含引号。 |
|
选择给定属性不具有给定值的所有元素。该值不能包含引号。 在 3.10 版本加入。 |
|
选择所有具有名为 |
|
选择其完整文本内容(包括后代)等于给定 在 3.7 版本加入。 |
|
选择其完整文本内容(包括后代)不等于给定 在 3.10 版本加入。 |
|
选择所有具有名为 |
|
选择所有具有名为 在 3.10 版本加入。 |
|
选择所有位于给定位置的元素。位置可以是整数(1 是第一个位置),表达式 |
谓词(方括号内的表达式)必须后跟标签名、星号或另一个谓词。position
谓词必须后跟标签名。
参考¶
函数¶
- xml.etree.ElementTree.canonicalize(xml_data=None, *, out=None, from_file=None, **options)¶
C14N 2.0 转换函数。
规范化是一种标准化 XML 输出的方式,允许逐字节比较和数字签名。它减少了 XML 序列化器所拥有的自由,而是生成更受限制的 XML 表示。主要限制涉及命名空间声明的位置、属性的顺序和可忽略的空白。
此函数以 XML 数据字符串(xml_data)或文件路径或类文件对象(from_file)作为输入,将其转换为规范形式,并使用 out 类文件对象(如果提供)将其写入,否则将其作为文本字符串返回。输出文件接收文本,而不是字节。因此,它应该以文本模式并使用
utf-8
编码打开。典型用途
xml_data = "<root>...</root>" print(canonicalize(xml_data)) with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file: canonicalize(xml_data, out=out_file) with open("c14n_output.xml", mode='w', encoding='utf-8') as out_file: canonicalize(from_file="inputfile.xml", out=out_file)
配置 options 如下
with_comments:设置为 true 以包含注释(默认值:false)
- strip_text:设置为 true 以在文本内容前后去除空白
(默认值:false)
- rewrite_prefixes:设置为 true 以将命名空间前缀替换为“n{number}”
(默认值:false)
- qname_aware_tags:一组 qname 感知标签名,其中前缀
应在文本内容中替换(默认值:空)
- qname_aware_attrs:一组 qname 感知属性名,其中前缀
应在文本内容中替换(默认值:空)
exclude_attrs:一组不应序列化的属性名
exclude_tags:一组不应序列化的标签名
在上述选项列表中,“一组”指任何字符串集合或可迭代对象,不期望任何顺序。
在 3.8 版本加入。
- xml.etree.ElementTree.Comment(text=None)¶
注释元素工厂。此工厂函数创建一个特殊元素,该元素将由标准序列化器序列化为 XML 注释。注释字符串可以是字节字符串或 Unicode 字符串。text 是包含注释字符串的字符串。返回表示注释的元素实例。
请注意,
XMLParser
会跳过输入中的注释,而不是为它们创建注释对象。ElementTree
仅当使用Element
方法之一将注释节点插入树中时,才会包含注释节点。
- xml.etree.ElementTree.dump(elem)¶
将元素树或元素结构写入 sys.stdout。此函数仅应用于调试。
确切的输出格式取决于实现。在此版本中,它作为普通 XML 文件写入。
elem 是一个元素树或单个元素。
3.8 版本中的更改:
dump()
函数现在保留用户指定的属性顺序。
- xml.etree.ElementTree.fromstring(text, parser=None)¶
从字符串常量解析 XML 片段。与
XML()
相同。text 是包含 XML 数据的字符串。parser 是可选的解析器实例。如果未给出,则使用标准XMLParser
解析器。返回Element
实例。
- xml.etree.ElementTree.fromstringlist(sequence, parser=None)¶
从字符串片段序列解析 XML 文档。sequence 是包含 XML 数据片段的列表或其他序列。parser 是可选的解析器实例。如果未给出,则使用标准
XMLParser
解析器。返回Element
实例。在 3.2 版本加入。
- xml.etree.ElementTree.indent(tree, space=' ', level=0)¶
向子树添加空白以在视觉上缩进树。这可用于生成漂亮的 XML 输出。tree 可以是 Element 或 ElementTree。space 是每个缩进级别将插入的空白字符串,默认为两个空格字符。对于在已缩进树中缩进部分子树,将初始缩进级别作为 level 传递。
在 3.9 版本中新增。
- xml.etree.ElementTree.iselement(element)¶
检查对象是否似乎是有效的元素对象。element 是一个元素实例。如果是元素对象,则返回
True
。
- xml.etree.ElementTree.iterparse(source, events=None, parser=None)¶
将 XML 片段逐步解析为元素树,并向用户报告正在发生的事情。source 是包含 XML 数据的文件名或 文件对象。events 是要报告的事件序列。支持的事件是字符串
"start"
、"end"
、"comment"
、"pi"
、"start-ns"
和"end-ns"
(“ns”事件用于获取详细的命名空间信息)。如果省略 events,则只报告"end"
事件。parser 是可选的解析器实例。如果未给出,则使用标准XMLParser
解析器。parser 必须是XMLParser
的子类,并且只能使用默认的TreeBuilder
作为目标。返回一个提供(event, elem)
对的 迭代器;一旦 source 完全读取,它就有一个引用结果 XML 树的根元素的root
属性。如果 source 是文件名,迭代器具有close()
方法,用于关闭内部文件对象。请注意,尽管
iterparse()
增量构建树,但它对 source(或其命名的文件)发出阻塞读取。因此,它不适用于无法进行阻塞读取的应用程序。对于完全非阻塞解析,请参阅XMLPullParser
。备注
iterparse()
只保证在发出“start”事件时看到了起始标签的“>”字符,因此属性已定义,但文本和尾部属性的内容在该点未定义。元素子元素也是如此;它们可能存在也可能不存在。如果需要完全填充的元素,请改为查找“end”事件。
自 3.4 版本弃用: parser 参数。
3.8 版本中的更改: 添加了
comment
和pi
事件。3.13 版本中的更改: 添加了
close()
方法。
- xml.etree.ElementTree.parse(source, parser=None)¶
将 XML 片段解析为元素树。source 是包含 XML 数据的文件名或文件对象。parser 是可选的解析器实例。如果未给出,则使用标准
XMLParser
解析器。返回ElementTree
实例。
- xml.etree.ElementTree.ProcessingInstruction(target, text=None)¶
PI 元素工厂。此工厂函数创建一个特殊元素,该元素将序列化为 XML 处理指令。target 是包含 PI 目标的字符串。如果给出 text,则为包含 PI 内容的字符串。返回表示处理指令的元素实例。
请注意,
XMLParser
会跳过输入中的处理指令,而不是为它们创建 PI 对象。ElementTree
仅当使用Element
方法之一将处理指令节点插入树中时,才会包含处理指令节点。
- xml.etree.ElementTree.register_namespace(prefix, uri)¶
注册命名空间前缀。注册表是全局的,任何给定前缀或命名空间 URI 的现有映射都将被删除。prefix 是命名空间前缀。uri 是命名空间 URI。此命名空间中的标签和属性将尽可能使用给定前缀进行序列化。
在 3.2 版本加入。
- xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)¶
子元素工厂。此函数创建元素实例,并将其附加到现有元素。
元素名称、属性名称和属性值可以是字节字符串或 Unicode 字符串。parent 是父元素。tag 是子元素名称。attrib 是可选字典,包含元素属性。extra 包含作为关键字参数给出的附加属性。返回元素实例。
- xml.etree.ElementTree.tostring(element, encoding='us-ascii', method='xml', *, xml_declaration=None, default_namespace=None, short_empty_elements=True)¶
生成 XML 元素的字符串表示,包括所有子元素。element 是一个
Element
实例。encoding [1] 是输出编码(默认为 US-ASCII)。使用encoding="unicode"
生成 Unicode 字符串(否则,生成字节字符串)。method 是"xml"
、"html"
或"text"
之一(默认为"xml"
)。xml_declaration、default_namespace 和 short_empty_elements 的含义与ElementTree.write()
中相同。返回包含 XML 数据的(可选)编码字符串。3.4 版本中的更改: 添加了 short_empty_elements 参数。
3.8 版本中的更改: 添加了 xml_declaration 和 default_namespace 参数。
3.8 版本中的更改:
tostring()
函数现在保留用户指定的属性顺序。
- xml.etree.ElementTree.tostringlist(element, encoding='us-ascii', method='xml', *, xml_declaration=None, default_namespace=None, short_empty_elements=True)¶
生成 XML 元素的字符串表示,包括所有子元素。element 是一个
Element
实例。encoding [1] 是输出编码(默认为 US-ASCII)。使用encoding="unicode"
生成 Unicode 字符串(否则,生成字节字符串)。method 是"xml"
、"html"
或"text"
之一(默认为"xml"
)。xml_declaration、default_namespace 和 short_empty_elements 的含义与ElementTree.write()
中相同。返回包含 XML 数据的(可选)编码字符串列表。它不保证任何特定的序列,除了b"".join(tostringlist(element)) == tostring(element)
。在 3.2 版本加入。
3.4 版本中的更改: 添加了 short_empty_elements 参数。
3.8 版本中的更改: 添加了 xml_declaration 和 default_namespace 参数。
3.8 版本中的更改:
tostringlist()
函数现在保留用户指定的属性顺序。
XInclude 支持¶
此模块通过 xml.etree.ElementInclude
辅助模块为 XInclude 指令 提供有限支持。此模块可用于根据树中的信息将子树和文本字符串插入元素树中。
示例¶
这是一个演示 XInclude 模块用法的示例。要在当前文档中包含 XML 文档,请使用 {http://www.w3.org/2001/XInclude}include
元素并将 parse 属性设置为 "xml"
,并使用 href 属性指定要包含的文档。
<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="source.xml" parse="xml" />
</document>
默认情况下,href 属性被视为文件名。您可以使用自定义加载器覆盖此行为。另请注意,标准助手不支持 XPointer 语法。
要处理此文件,请像往常一样加载它,并将根元素传递给 xml.etree.ElementTree
模块
from xml.etree import ElementTree, ElementInclude
tree = ElementTree.parse("document.xml")
root = tree.getroot()
ElementInclude.include(root)
ElementInclude 模块将 {http://www.w3.org/2001/XInclude}include
元素替换为 source.xml 文档中的根元素。结果可能看起来像这样
<document xmlns:xi="http://www.w3.org/2001/XInclude">
<para>This is a paragraph.</para>
</document>
如果省略 parse 属性,则默认为“xml”。href 属性是必需的。
要包含文本文档,请使用 {http://www.w3.org/2001/XInclude}include
元素,并将 parse 属性设置为“text”
<?xml version="1.0"?>
<document xmlns:xi="http://www.w3.org/2001/XInclude">
Copyright (c) <xi:include href="year.txt" parse="text" />.
</document>
结果可能看起来像
<document xmlns:xi="http://www.w3.org/2001/XInclude">
Copyright (c) 2003.
</document>
参考¶
函数¶
- xml.etree.ElementInclude.default_loader(href, parse, encoding=None)¶
默认加载器。此默认加载器从磁盘读取包含的资源。href 是一个 URL。parse 用于解析模式,“xml”或“text”。encoding 是可选的文本编码。如果未给出,则编码为
utf-8
。返回展开的资源。如果解析模式是"xml"
,则这是一个Element
实例。如果解析模式是"text"
,则这是一个字符串。如果加载器失败,它可以返回None
或引发异常。
- xml.etree.ElementInclude.include(elem, loader=None, base_url=None, max_depth=6)¶
此函数在 elem 指向的树中原地展开 XInclude 指令。elem 是根
Element
或ElementTree
实例,用于查找此类元素。loader 是可选的资源加载器。如果省略,则默认为default_loader()
。如果给出,它应该是一个可调用对象,实现与default_loader()
相同的接口。base_url 是原始文件的基本 URL,用于解析相对包含文件引用。max_depth 是递归包含的最大数量。限制以减少恶意内容爆炸的风险。传递None
以禁用此限制。3.9 版本中的更改: 添加了 base_url 和 max_depth 参数。
元素对象¶
- class xml.etree.ElementTree.Element(tag, attrib={}, **extra)¶
元素类。此类定义了元素接口,并提供了此接口的参考实现。
元素名称、属性名称和属性值可以是字节字符串或 Unicode 字符串。tag 是元素名称。attrib 是可选的字典,包含元素属性。extra 包含作为关键字参数给出的附加属性。
- tag¶
一个字符串,用于标识此元素代表的数据类型(换句话说,元素类型)。
- text¶
- tail¶
这些属性可用于保存与元素关联的附加数据。它们的值通常是字符串,但可以是任何特定于应用程序的对象。如果元素是从 XML 文件创建的,则 text 属性保存元素起始标签与其第一个子元素或结束标签之间的文本,或者
None
;tail 属性保存元素结束标签与下一个标签之间的文本,或者None
。对于 XML 数据<a><b>1<c>2<d/>3</c></b>4</a>
a 元素的 text 和 tail 属性均为
None
;b 元素的 text 为"1"
,tail 为"4"
;c 元素的 text 为"2"
,tail 为None
;d 元素的 text 为None
,tail 为"3"
。要收集元素的内部文本,请参阅
itertext()
,例如"".join(element.itertext())
。应用程序可以在这些属性中存储任意对象。
- attrib¶
包含元素属性的字典。请注意,虽然 attrib 值始终是真正的可变 Python 字典,但 ElementTree 实现可以选择使用另一种内部表示,并且仅当有人请求时才创建字典。为了利用此类实现,请尽可能使用下面的字典方法。
以下类字典方法适用于元素属性。
- clear()¶
重置一个元素。此函数删除所有子元素,清除所有属性,并将文本和尾部属性设置为
None
。
- get(key, default=None)¶
获取名为 key 的元素属性。
返回属性值,如果未找到属性,则返回 default。
- items()¶
将元素属性作为 (名称, 值) 对的序列返回。属性以任意顺序返回。
- keys()¶
将元素属性名称作为列表返回。名称以任意顺序返回。
- set(key, value)¶
将元素上属性 key 的值设置为 value。
以下方法适用于元素的子元素。
- find(match, namespaces=None)¶
查找与 match 匹配的第一个子元素。match 可以是标签名称或 路径。返回元素实例或
None
。namespaces 是从命名空间前缀到完整名称的可选映射。传递''
作为前缀,将表达式中所有未加前缀的标签名称移动到给定命名空间中。
- findall(match, namespaces=None)¶
通过标签名称或 路径 查找所有匹配的子元素。返回一个列表,其中包含按文档顺序排列的所有匹配元素。namespaces 是从命名空间前缀到完整名称的可选映射。传递
''
作为前缀,将表达式中所有未加前缀的标签名称移动到给定命名空间中。
- findtext(match, default=None, namespaces=None)¶
查找与 match 匹配的第一个子元素的文本。match 可以是标签名称或 路径。返回第一个匹配元素的文本内容,如果没有找到元素,则返回 default。请注意,如果匹配元素没有文本内容,则返回空字符串。namespaces 是从命名空间前缀到完整名称的可选映射。传递
''
作为前缀,将表达式中所有未加前缀的标签名称移动到给定命名空间中。
- iter(tag=None)¶
创建一个以当前元素为根的树 迭代器。迭代器按照文档(深度优先)顺序迭代此元素及其下面的所有元素。如果 tag 不是
None
或'*'
,则迭代器仅返回标签等于 tag 的元素。如果在迭代期间修改了树结构,则结果未定义。在 3.2 版本加入。
- iterfind(match, namespaces=None)¶
通过标签名称或 路径 查找所有匹配的子元素。返回一个可迭代对象,按文档顺序生成所有匹配元素。namespaces 是从命名空间前缀到完整名称的可选映射。
在 3.2 版本加入。
- itertext()¶
创建文本迭代器。迭代器遍历此元素和所有子元素,按文档顺序返回所有内部文本。
在 3.2 版本加入。
- makeelement(tag, attrib)¶
创建与此元素相同类型的新元素对象。不要调用此方法,请改用
SubElement()
工厂函数。
- remove(subelement)¶
从元素中删除 subelement。与 find* 方法不同,此方法基于实例标识(而非标签值或内容)比较元素。
Element
对象还支持以下序列类型方法用于处理子元素:__delitem__()
、__getitem__()
、__setitem__()
、__len__()
。注意:没有子元素的元素将测试为
False
。在 Python 的未来版本中,所有元素都将测试为True
,无论是否存在子元素。因此,请优先使用显式len(elem)
或elem is not None
测试。element = root.find('foo') if not element: # careful! print("element not found, or element has no subelements") if element is None: print("element not found")
3.12 版本中的更改: 测试 Element 的真值会发出
DeprecationWarning
。在 Python 3.8 之前,通过按名称对属性进行排序,人为地使元素的 XML 属性的序列化顺序可预测。基于现在保证的字典顺序,此任意重新排序在 Python 3.8 中被删除,以保留属性最初由用户代码解析或创建的顺序。
通常,用户代码不应依赖于特定的属性顺序,因为 XML 信息集 明确排除属性顺序传达信息。代码应准备好处理输入中的任何顺序。在需要确定性 XML 输出的情况下,例如用于加密签名或测试数据集,可以使用
canonicalize()
函数进行规范化序列化。在不适用规范输出但仍希望输出特定属性顺序的情况下,代码应旨在直接以所需顺序创建属性,以避免代码读者感知上的不匹配。如果这难以实现,则可以在序列化之前应用以下方法来强制执行独立于元素创建的顺序
def reorder_attributes(root): for el in root.iter(): attrib = el.attrib if len(attrib) > 1: # adjust attribute order, e.g. by sorting attribs = sorted(attrib.items()) attrib.clear() attrib.update(attribs)
ElementTree 对象¶
- class xml.etree.ElementTree.ElementTree(element=None, file=None)¶
ElementTree 包装类。此类表示整个元素层次结构,并增加了对与标准 XML 之间进行序列化的额外支持。
element 是根元素。如果给定 XML file,则树将使用其内容进行初始化。
- _setroot(element)¶
替换此树的根元素。这将丢弃树的当前内容,并将其替换为给定元素。请谨慎使用。element 是一个元素实例。
- find(match, namespaces=None)¶
与
Element.find()
相同,从树的根开始。
- findall(match, namespaces=None)¶
与
Element.findall()
相同,从树的根开始。
- findtext(match, default=None, namespaces=None)¶
与
Element.findtext()
相同,从树的根开始。
- getroot()¶
返回此树的根元素。
- iter(tag=None)¶
为根元素创建并返回一个树迭代器。迭代器按章节顺序遍历此树中的所有元素。tag 是要查找的标签(默认为返回所有元素)。
- iterfind(match, namespaces=None)¶
与
Element.iterfind()
相同,从树的根部开始查找。在 3.2 版本加入。
- parse(source, parser=None)¶
将外部 XML 部分加载到此元素树中。source 是一个文件名或 文件对象。parser 是可选的解析器实例。如果未给定,则使用标准
XMLParser
解析器。返回该部分的根元素。
- write(file, encoding='us-ascii', xml_declaration=None, default_namespace=None, method='xml', *, short_empty_elements=True)¶
将元素树作为 XML 写入文件。file 是一个文件名,或一个为写入而打开的 文件对象。encoding [1] 是输出编码(默认为 US-ASCII)。xml_declaration 控制是否应将 XML 声明添加到文件中。使用
False
表示从不添加,True
表示始终添加,None
表示仅在非 US-ASCII、UTF-8 或 Unicode 时添加(默认为None
)。default_namespace 设置默认的 XML 命名空间(对于“xmlns”)。method 可以是"xml"
、"html"
或"text"
(默认为"xml"
)。仅限关键字参数 short_empty_elements 控制不包含内容的元素的格式。如果为True
(默认值),它们将作为单个自闭合标签发出,否则它们将作为一对开始/结束标签发出。输出可以是字符串(
str
)或二进制(bytes
)。这由 encoding 参数控制。如果 encoding 是"unicode"
,则输出是字符串;否则,它是二进制。请注意,如果 file 是一个打开的 文件对象,这可能会与 file 的类型冲突;请确保不要尝试将字符串写入二进制流,反之亦然。3.4 版本中的更改: 添加了 short_empty_elements 参数。
3.8 版本发生变更:
write()
方法现在保留用户指定的属性顺序。
这是将要操作的 XML 文件
<html>
<head>
<title>Example page</title>
</head>
<body>
<p>Moved to <a href="http://example.org/">example.org</a>
or <a href="http://example.com/">example.com</a>.</p>
</body>
</html>
更改第一个段落中每个链接的“target”属性的示例
>>> from xml.etree.ElementTree import ElementTree
>>> tree = ElementTree()
>>> tree.parse("index.xhtml")
<Element 'html' at 0xb77e6fac>
>>> p = tree.find("body/p") # Finds first occurrence of tag p in body
>>> p
<Element 'p' at 0xb77ec26c>
>>> links = list(p.iter("a")) # Returns list of all links
>>> links
[<Element 'a' at 0xb77ec2ac>, <Element 'a' at 0xb77ec1cc>]
>>> for i in links: # Iterates through all found links
... i.attrib["target"] = "blank"
...
>>> tree.write("output.xhtml")
QName 对象¶
TreeBuilder 对象¶
- class xml.etree.ElementTree.TreeBuilder(element_factory=None, *, comment_factory=None, pi_factory=None, insert_comments=False, insert_pis=False)¶
通用元素结构构建器。此构建器将一系列 start、data、end、comment 和 pi 方法调用转换为格式良好的元素结构。您可以使用此类别使用自定义 XML 解析器或用于其他类似 XML 格式的解析器构建元素结构。
如果给定 element_factory,它必须是一个可调用对象,接受两个位置参数:标签和属性字典。它应返回一个新的元素实例。
如果给定 comment_factory 和 pi_factory 函数,它们应像
Comment()
和ProcessingInstruction()
函数一样,用于创建注释和处理指令。如果未给定,则使用默认工厂。当 insert_comments 和/或 insert_pis 为真时,如果注释/pi 出现在根元素内(但不在根元素之外),它们将被插入到树中。- data(data)¶
向当前元素添加文本。data 是一个字符串。这应该是一个字节字符串或 Unicode 字符串。
- end(tag)¶
关闭当前元素。tag 是元素名称。返回关闭的元素。
- start(tag, attrs)¶
打开一个新元素。tag 是元素名称。attrs 是一个包含元素属性的字典。返回打开的元素。
- comment(text)¶
使用给定的 text 创建注释。如果
insert_comments
为真,这也会将其添加到树中。在 3.8 版本加入。
- pi(target, text)¶
使用给定的 target 名称和 text 创建处理指令。如果
insert_pis
为真,这也会将其添加到树中。在 3.8 版本加入。
此外,自定义
TreeBuilder
对象可以提供以下方法- doctype(name, pubid, system)¶
处理 doctype 声明。name 是 doctype 名称。pubid 是公共标识符。system 是系统标识符。此方法在默认的
TreeBuilder
类中不存在。在 3.2 版本加入。
- start_ns(prefix, uri)¶
当解析器遇到新的命名空间声明时调用,在定义该声明的起始元素的
start()
回调之前。prefix 对于默认命名空间是''
,否则是声明的命名空间前缀名称。uri 是命名空间 URI。在 3.8 版本加入。
- end_ns(prefix)¶
在一个声明了命名空间前缀映射的元素的
end()
回调之后调用,并带有超出范围的 prefix 名称。在 3.8 版本加入。
- class xml.etree.ElementTree.C14NWriterTarget(write, *, with_comments=False, strip_text=False, rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None, exclude_attrs=None, exclude_tags=None)¶
一个 C14N 2.0 写入器。参数与
canonicalize()
函数的参数相同。此类不构建树,而是使用 write 函数将回调事件直接转换为序列化形式。在 3.8 版本加入。
XMLParser 对象¶
- class xml.etree.ElementTree.XMLParser(*, target=None, encoding=None)¶
此类是模块的低级构建块。它使用
xml.parsers.expat
进行高效、基于事件的 XML 解析。可以使用feed()
方法增量地向其提供 XML 数据,解析事件通过调用 target 对象上的回调函数转换为推式 API。如果省略 target,则使用标准TreeBuilder
。如果给定 encoding [1],则该值将覆盖 XML 文件中指定的编码。3.8 版本发生变更: 参数现在是 仅限关键字。不再支持 html 参数。
- close()¶
完成向解析器提供数据。返回调用构造期间传入的 target 的
close()
方法的结果;默认情况下,这是顶层文档元素。
- feed(data)¶
向解析器提供数据。data 是编码数据。
- flush()¶
触发对所有先前提供的未解析数据的解析,这可用于确保更即时的反馈,特别是对于 Expat >=2.6.0。
flush()
的实现暂时禁用 Expat 的重新解析延迟(如果当前已启用)并触发重新解析。禁用重新解析延迟具有安全隐患;有关详细信息,请参阅xml.parsers.expat.xmlparser.SetReparseDeferralEnabled()
。请注意,
flush()
已作为安全修复程序向后移植到 CPython 的某些早期版本。如果在各种 Python 版本上运行的代码中使用flush()
,请使用hasattr()
检查其可用性。在 3.13 版本加入。
XMLParser.feed()
为每个开始标签调用 target 的start(tag, attrs_dict)
方法,为每个结束标签调用其end(tag)
方法,数据由方法data(data)
处理。有关进一步支持的回调方法,请参阅TreeBuilder
类。XMLParser.close()
调用 target 的方法close()
。XMLParser
不仅可以用于构建树结构。这是一个计算 XML 文件最大深度的示例>>> from xml.etree.ElementTree import XMLParser >>> class MaxDepth: # The target object of the parser ... maxDepth = 0 ... depth = 0 ... def start(self, tag, attrib): # Called for each opening tag. ... self.depth += 1 ... if self.depth > self.maxDepth: ... self.maxDepth = self.depth ... def end(self, tag): # Called for each closing tag. ... self.depth -= 1 ... def data(self, data): ... pass # We do not need to do anything with data. ... def close(self): # Called when all data has been parsed. ... return self.maxDepth ... >>> target = MaxDepth() >>> parser = XMLParser(target=target) >>> exampleXml = """ ... <a> ... <b> ... </b> ... <b> ... <c> ... <d> ... </d> ... </c> ... </b> ... </a>""" >>> parser.feed(exampleXml) >>> parser.close() 4
XMLPullParser 对象¶
- class xml.etree.ElementTree.XMLPullParser(events=None)¶
一个适用于非阻塞应用程序的拉取解析器。其输入端 API 与
XMLParser
类似,但XMLPullParser
不会向回调目标推送调用,而是收集一个内部解析事件列表,并允许用户从中读取。events 是要报告的事件序列。支持的事件是字符串"start"
、"end"
、"comment"
、"pi"
、"start-ns"
和"end-ns"
(“ns”事件用于获取详细的命名空间信息)。如果省略 events,则只报告"end"
事件。- feed(data)¶
向解析器提供给定的字节数据。
- flush()¶
触发对所有先前提供的未解析数据的解析,这可用于确保更即时的反馈,特别是对于 Expat >=2.6.0。
flush()
的实现暂时禁用 Expat 的重新解析延迟(如果当前已启用)并触发重新解析。禁用重新解析延迟具有安全隐患;有关详细信息,请参阅xml.parsers.expat.xmlparser.SetReparseDeferralEnabled()
。请注意,
flush()
已作为安全修复程序向后移植到 CPython 的某些早期版本。如果在各种 Python 版本上运行的代码中使用flush()
,请使用hasattr()
检查其可用性。在 3.13 版本加入。
- close()¶
通知解析器数据流已终止。与
XMLParser.close()
不同,此方法总是返回None
。解析器关闭时尚未检索到的任何事件仍然可以通过read_events()
读取。
- read_events()¶
返回一个迭代器,用于遍历已在提供给解析器的数据中遇到的事件。迭代器产生
(event, elem)
对,其中 event 是表示事件类型(例如"end"
)的字符串,elem 是遇到的Element
对象,或其他上下文值,如下所示。start
,end
: 当前元素。comment
,pi
: 当前注释/处理指令start-ns
: 一个元组(prefix, uri)
,命名声明的命名空间映射。end-ns
:None
(这在未来的版本中可能会改变)
在之前调用
read_events()
中提供的事件将不会再次产生。事件只有在从迭代器中检索时才从内部队列中消耗,因此多个读取器并行迭代从read_events()
获得的迭代器将产生不可预测的结果。
备注
XMLPullParser
仅保证在发出“start”事件时已看到起始标签的“>”字符,因此属性已定义,但文本和尾部属性的内容在该点未定义。元素子元素也适用同样的情况;它们可能存在,也可能不存在。如果需要完全填充的元素,请改为查找“end”事件。
在 3.4 版本加入。
3.8 版本中的更改: 添加了
comment
和pi
事件。
异常¶
- class xml.etree.ElementTree.ParseError¶
XML 解析错误,当解析失败时由本模块中的各种解析方法引发。此异常实例的字符串表示将包含用户友好的错误消息。此外,它将具有以下可用属性
- code¶
来自 expat 解析器的数字错误代码。有关错误代码及其含义的列表,请参阅
xml.parsers.expat
的文档。
- position¶
一个 line、column 数字元组,指定错误发生的位置。
脚注