xml.etree.ElementTree — ElementTree XML API — Python 文档
xml.etree.ElementTree — ElementTree XML API
源代码: :source:`Lib/xml/etree/ElementTree.py`
xml.etree.ElementTree 模块实现了一个简单高效的 API,用于解析和创建 XML 数据。
3.3 版更改: 该模块将在可用时使用快速实现。 xml.etree.cElementTree
模块已弃用。
教程
这是使用 xml.etree.ElementTree(简称 ET
)的简短教程。 目标是演示模块的一些构建块和基本概念。
XML 树和元素
XML 是一种固有的分层数据格式,最自然的表示方式是使用树。 ET
有两个用于此目的的类 - ElementTree 将整个 XML 文档表示为一棵树,而 Element 表示该树中的单个节点。 与整个文档的交互(读写文件)通常在 ElementTree 级别上完成。 与单个 XML 元素及其子元素的交互是在 元素 级别上完成的。
解析 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 构造函数来访问文档类型声明。
用于非阻塞解析的拉取 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
明显的用例是以非阻塞方式运行的应用程序,其中 XML 数据从套接字接收或从某个存储设备增量读取。 在这种情况下,阻塞读取是不可接受的。
因为它非常灵活,XMLPullParser 可能不方便用于更简单的用例。 如果您不介意您的应用程序在读取 XML 数据时被阻塞,但仍希望具有增量解析功能,请查看 iterparse()。 当您正在阅读大型 XML 文档并且不想将其全部保存在内存中时,它会很有用。
寻找有趣的元素
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() 找到具有特定标签的 first 子元素,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.text)、添加和修改属性(Element.set())来操作 Element 对象方法),以及添加新子项(例如使用 Element.append())。
假设我们要为每个国家/地区的排名添加一个,并向 rank 元素添加一个 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
,其中 前缀 被替换为完整的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 示例的一种方法是手动将 URI 添加到 find() 或 findall() 的 xpath 中的每个标签或属性:
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 功能。 我们将使用 Parsing 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 语法
句法 | 意义 |
---|---|
tag
|
选择具有给定标签的所有子元素。 例如, 3.8 版更改: 增加了对星形通配符的支持。
|
*
|
选择所有子元素,包括注释和处理指令。 例如,*/egg 选择所有名为 egg 的孙子。
|
.
|
选择当前节点。 这在路径的开头非常有用,以表明它是一个相对路径。 |
//
|
选择当前元素下所有级别的所有子元素。 例如,.//egg 选择整个树中的所有 egg 元素。
|
..
|
选择父元素。 如果路径试图到达起始元素的祖先(元素 find 被调用),则返回 None 。
|
[@attrib]
|
选择具有给定属性的所有元素。 |
[@attrib='value']
|
选择给定属性具有给定值的所有元素。 该值不能包含引号。 |
[tag]
|
选择所有具有名为 tag 的子元素的元素。 仅支持直系子女。
|
[.='text']
|
选择其完整文本内容(包括后代)等于给定 3.7 版中的新功能。
|
[tag='text']
|
选择所有具有名为 tag 的子元素的元素,其完整文本内容(包括后代)等于给定的 text 。
|
[position]
|
选择位于给定位置的所有元素。 位置可以是整数(1 是第一个位置)、表达式 last() (对于最后一个位置)或相对于最后一个位置的位置(例如 last()-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 以去除文本内容前后的空白
(默认:假)
- rewrite_prefixes:设置为 true 以用“n{number}”替换命名空间前缀
(默认:假)
- qname_aware_tags:一组qname感知标签名称,其中前缀
应该在文本内容中替换(默认:空)
- qname_aware_attrs:一组qname感知属性名称,其中前缀
应该在文本内容中替换(默认:空)
exclude_attrs:一组不应序列化的属性名
exclude_tags:一组不应序列化的标签名称
在上面的选项列表中,“a set”是指任何集合或字符串的可迭代对象,不需要排序。
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.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)
对。请注意,虽然 iterparse() 以增量方式构建树,但它会在 source(或其命名的文件)上发出阻塞读取。 因此,它不适合无法进行阻塞读取的应用程序。 对于完全非阻塞的解析,请参阅 XMLPullParser。
笔记
iterparse() 只保证它在发出“start”事件时看到了起始标签的“>”字符,所以定义了属性,但未定义text和tail属性的内容在那时候。 这同样适用于元素孩子; 它们可能存在也可能不存在。
如果您需要一个完全填充的元素,请改为查找“结束”事件。
自 3.4 版起已弃用: 解析器 参数。
3.8 版更改: 添加了
comment
和pi
事件。
- 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 跳过输入中的处理指令,而不是为它们创建注释对象。 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() 函数现在保留用户指定的属性顺序。
- xml.etree.ElementTree.XML(text, parser=None)
- 从字符串常量解析 XML 部分。 此函数可用于在 Python 代码中嵌入“XML 文字”。 text 是一个包含 XML 数据的字符串。 parser 是一个可选的解析器实例。 如果没有给出,则使用标准的 XMLParser 解析器。 返回一个 Element 实例。
- xml.etree.ElementTree.XMLID(text, parser=None)
- 从字符串常量解析 XML 部分,并返回从元素 id:s 映射到元素的字典。 text 是一个包含 XML 数据的字符串。 parser 是一个可选的解析器实例。 如果没有给出,则使用标准的 XMLParser 解析器。 返回一个包含 Element 实例和字典的元组。
X包括支持
该模块通过 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"
,则这是一个 ElementTree 实例。 如果解析模式为“文本”,则这是一个 Unicode 字符串。 如果加载器失败,它可以返回 None 或引发异常。
- xml.etree.ElementInclude.include(elem, loader=None)
- 此函数扩展 XInclude 指令。 elem 是根元素。 loader 是一个可选的资源加载器。 如果省略,则默认为 default_loader()。 如果给定,它应该是一个实现与 default_loader() 相同接口的可调用对象。 返回扩展的资源。 如果解析模式为
"xml"
,则这是一个 ElementTree 实例。 如果解析模式为“文本”,则这是一个 Unicode 字符串。 如果加载器失败,它可以返回 None 或引发异常。
元素对象
- class xml.etree.ElementTree.Element(tag, attrib={}, **extra)
元素类。 该类定义了 Element 接口,并提供了该接口的参考实现。
元素名称、属性名称和属性值可以是字节字符串或 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[ X125X]"1"
和 tail"4"
,c 元素有 text [X212X][X212X] tailNone
,d 元素有 textNone
和 tail [X334X][X349X].X3要收集元素的内部文本,请参阅 itertext(),例如
"".join(element.itertext())
。应用程序可以在这些属性中存储任意对象。
- attrib
包含元素属性的字典。 请注意,虽然 attrib 值始终是一个真正的可变 Python 字典,但 ElementTree 实现可能会选择使用另一种内部表示,并且仅在有人要求时才创建字典。 要利用此类实现,请尽可能使用下面的字典方法。
以下类似字典的方法适用于元素属性。
- clear()
重置一个元素。 该函数移除所有子元素,清除所有属性,并将text和tail属性设置为
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 是从命名空间前缀到全名的可选映射。 将
作为前缀传递以将表达式中所有不带前缀的标签名称移动到给定的命名空间中。
- getchildren()
- getiterator(tag=None)
- iter(tag=None)
创建一个以当前元素为根的树 iterator。 迭代器以文档(深度优先)顺序迭代此元素及其下方的所有元素。 如果 tag 不是
None
或'*'
,则迭代器只返回标签等于 tag 的元素。 如果在迭代过程中修改了树结构,结果是不确定的。3.2 版中的新功能。
- iterfind(match, namespaces=None)
按标记名称或 路径 查找所有匹配的子元素。 返回一个可迭代的,以文档顺序产生所有匹配的元素。 namespaces 是从命名空间前缀到全名的可选映射。
3.2 版中的新功能。
- itertext()
创建一个文本迭代器。 迭代器按文档顺序遍历此元素和所有子元素,并返回所有内部文本。
3.2 版中的新功能。
- makeelement(tag, attrib)
创建与此元素类型相同的新元素对象。 不要调用此方法,而是使用 SubElement() 工厂函数。
- remove(subelement)
从元素中移除 子元素 。 与 find* 方法不同,此方法基于实例标识而不是标记值或内容比较元素。
Element 对象还支持以下用于处理子元素的序列类型方法:__delitem__()、__getitem__()、__setitem__()、 __len__()。
注意:没有子元素的元素将测试为
False
。 此行为将在未来版本中更改。 请改用特定的len(elem)
或elem is 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")
在 Python 3.8 之前,元素的 XML 属性的序列化顺序是通过按名称对属性进行排序来人为地预测的。 基于现在保证的 dict 排序,在 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)
元素树对象
- class xml.etree.ElementTree.ElementTree(element=None, file=None)
ElementTree 包装类。 此类表示整个元素层次结构,并为标准 XML 的序列化添加了一些额外的支持。
element 是根元素。 如果给定,则使用 XML 文件 的内容初始化树。
- _setroot(element)
替换此树的根元素。 这会丢弃树的当前内容,并用给定的元素替换它。 小心使用。 element 是一个元素实例。
- find(match, namespaces=None)
与 Element.find() 相同,从树的根开始。
- findall(match, namespaces=None)
与 Element.findall() 相同,从树的根开始。
- findtext(match, default=None, namespaces=None)
与 Element.findtext() 相同,从树的根开始。
- getiterator(tag=None)
- 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 是一个文件名,或者一个 file object 为写入而打开。 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"
,则输出为字符串; 否则,它是二进制的。 请注意,如果它是一个打开的 文件对象 ,这可能与 文件 的类型冲突; 确保您不要尝试将字符串写入二进制流,反之亦然。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>
更改第一段中每个链接的属性“目标”的示例:
>>> 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 对象
- class xml.etree.ElementTree.QName(text_or_uri, tag=None)
- QName 包装器。 这可用于包装 QName 属性值,以便对输出进行正确的命名空间处理。 text_or_uri 是一个包含 QName 值的字符串,格式为 {uri}local,或者,如果给定了 tag 参数,则为 QName 的 URI 部分。 如果给出 tag,第一个参数被解释为一个 URI,这个参数被解释为一个本地名称。 QName 实例是不透明的。
TreeBuilder 对象
- class xml.etree.ElementTree.TreeBuilder(element_factory=None, *, comment_factory=None, pi_factory=None, insert_comments=False, insert_pis=False)
通用元素结构构建器。 此构建器将开始、数据、结束、注释和 pi 方法调用的序列转换为格式良好的元素结构。 您可以使用此类来构建使用自定义 XML 解析器或其他类似 XML 格式的解析器的元素结构。
element_factory,当给定时,必须是一个接受两个位置参数的可调用对象:一个标签和一个属性字典。 预计会返回一个新的元素实例。
comment_factory 和 pi_factory 函数,当给出时,应该像 Comment() 和 ProcessingInstruction() 函数来创建注释和处理指示。 如果没有给出,将使用默认工厂。 当 insert_comments 和/或 insert_pis 为真时,如果注释/pis 出现在根元素内(但不在根元素之外),它们将被插入到树中。
- close()
刷新构建器缓冲区,并返回顶级文档元素。 返回一个 Element 实例。
- data(data)
向当前元素添加文本。 data 是一个字符串。 这应该是字节字符串或 Unicode 字符串。
- end(tag)
关闭当前元素。 tag 是元素名称。 返回关闭的元素。
- start(tag, attrs)
打开一个新元素。 tag 是元素名称。 attrs 是一个包含元素属性的字典。 返回打开的元素。
- comment(text)
使用给定的 文本 创建评论。 如果
insert_comments
为真,这也会将其添加到树中。3.8 版中的新功能。
- pi(target, text)
使用给定的 target 名称和 text 创建注释。 如果
insert_pis
为真,这也会将其添加到树中。3.8 版中的新功能。
此外,自定义的 TreeBuilder 对象可以提供以下方法:
- doctype(name, pubid, system)
处理文档类型声明。 name 是文档类型名称。 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 数据,并且解析事件被转换为推送 API - 通过调用 target 对象上的回调。 如果省略 target,则使用标准的 TreeBuilder。 如果给出 encoding 1,则该值会覆盖 XML 文件中指定的编码。
3.8 版更改: 参数现在是 仅关键字 。 不再支持 html 参数。
- close()
完成向解析器提供数据。 返回调用构造时传递的target的
close()
方法的结果; 默认情况下,这是顶级文档元素。
- feed(data)
将数据提供给解析器。 data 是编码数据。
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)
将给定的字节数据提供给解析器。
- close()
向解析器发出数据流终止的信号。 与 XMLParser.close() 不同,此方法始终返回 None。 解析器关闭时尚未检索到的任何事件仍然可以使用 read_events() 读取。
- read_events()
在提供给解析器的数据中遇到的事件上返回一个迭代器。 迭代器产生
(event, elem)
对,其中 event 是表示事件类型的字符串(例如"end"
) 和 elem 是遇到的 Element 对象,或其他上下文值,如下所示。start
、end
:当前元素。comment
、pi
:当前注释/处理指令start-ns
:一个元组(prefix, uri)
命名声明的命名空间映射。end-ns
:无(这可能会在未来版本中改变)
先前调用 read_events() 中提供的事件将不会再次产生。 事件仅在从迭代器中检索时才从内部队列中使用,因此多个读取器并行迭代从 read_events() 获得的迭代器将产生不可预测的结果。
笔记
XMLPullParser 只保证它在发出“start”事件时看到了起始标签的“>”字符,因此定义了属性,但此时text和tail属性的内容未定义观点。 这同样适用于元素孩子; 它们可能存在也可能不存在。
如果您需要一个完全填充的元素,请改为查找“结束”事件。
3.4 版中的新功能。
3.8 版更改: 添加了
comment
和pi
事件。
例外
- class xml.etree.ElementTree.ParseError
XML 解析错误,解析失败时由本模块中的各种解析方法引发。 此异常实例的字符串表示将包含用户友好的错误消息。 此外,它将具有以下可用属性:
- code
来自 expat 解析器的数字错误代码。 有关错误代码及其含义的列表,请参阅 xml.parsers.expat 的文档。
- position
line, column 数字的元组,指定错误发生的位置。
脚注
- 1(1,2,3,4)
- XML 输出中包含的编码字符串应符合相应的标准。 例如,“UTF-8”有效,但“UTF8”无效。 参见 https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl 和 https://www.iana.org/assignments/character-sets /character-sets.xhtml。