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。请查阅文档以确保。

作为 Elementroot 有一个标签和属性字典

>>> 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 语法

语法

含义

标签

选择所有具有给定标签的子元素。例如,spam 选择所有名为 spam 的子元素,spam/egg 选择所有名为 spam 的子元素中所有名为 egg 的孙元素。{namespace}* 选择给定命名空间中的所有标签,{*}spam 选择任何(或无)命名空间中名为 spam 的标签,{}* 仅选择不在命名空间中的标签。

3.8 版本中的更改: 增加了对星号通配符的支持。

*

选择所有子元素,包括注释和处理指令。例如,*/egg 选择所有名为 egg 的孙元素。

.

选择当前节点。这在路径开头最有用,表示这是一个相对路径。

//

选择所有子元素,在当前元素下的所有级别上。例如,.//egg 选择整个树中所有 egg 元素。

..

选择父元素。如果路径尝试访问起始元素(调用 find 的元素)的祖先,则返回 None

[@attrib]

选择所有具有给定属性的元素。

[@attrib='value']

选择给定属性具有给定值的所有元素。该值不能包含引号。

[@attrib!='value']

选择给定属性不具有给定值的所有元素。该值不能包含引号。

在 3.10 版本加入。

[tag]

选择所有具有名为 tag 的子元素的元素。仅支持直接子元素。

[.='text']

选择其完整文本内容(包括后代)等于给定 text 的所有元素。

在 3.7 版本加入。

[.!='text']

选择其完整文本内容(包括后代)不等于给定 text 的所有元素。

在 3.10 版本加入。

[tag='text']

选择所有具有名为 tag 的子元素,且其完整文本内容(包括后代)等于给定 text 的元素。

[tag!='text']

选择所有具有名为 tag 的子元素,且其完整文本内容(包括后代)不等于给定 text 的元素。

在 3.10 版本加入。

[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 以在文本内容前后去除空白

    (默认值: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 版本中的更改: 添加了 commentpi 事件。

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_declarationdefault_namespaceshort_empty_elements 的含义与 ElementTree.write() 中相同。返回包含 XML 数据的(可选)编码字符串。

3.4 版本中的更改: 添加了 short_empty_elements 参数。

3.8 版本中的更改: 添加了 xml_declarationdefault_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_declarationdefault_namespaceshort_empty_elements 的含义与 ElementTree.write() 中相同。返回包含 XML 数据的(可选)编码字符串列表。它不保证任何特定的序列,除了 b"".join(tostringlist(element)) == tostring(element)

在 3.2 版本加入。

3.4 版本中的更改: 添加了 short_empty_elements 参数。

3.8 版本中的更改: 添加了 xml_declarationdefault_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 映射到元素的字典。text 是包含 XML 数据的字符串。parser 是可选的解析器实例。如果未给出,则使用标准 XMLParser 解析器。返回包含 Element 实例和字典的元组。

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 是根 ElementElementTree 实例,用于查找此类元素。loader 是可选的资源加载器。如果省略,则默认为 default_loader()。如果给出,它应该是一个可调用对象,实现与 default_loader() 相同的接口。base_url 是原始文件的基本 URL,用于解析相对包含文件引用。max_depth 是递归包含的最大数量。限制以减少恶意内容爆炸的风险。传递 None 以禁用此限制。

3.9 版本中的更改: 添加了 base_urlmax_depth 参数。

元素对象

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)

元素类。此类定义了元素接口,并提供了此接口的参考实现。

元素名称、属性名称和属性值可以是字节字符串或 Unicode 字符串。tag 是元素名称。attrib 是可选的字典,包含元素属性。extra 包含作为关键字参数给出的附加属性。

tag

一个字符串,用于标识此元素代表的数据类型(换句话说,元素类型)。

text
tail

这些属性可用于保存与元素关联的附加数据。它们的值通常是字符串,但可以是任何特定于应用程序的对象。如果元素是从 XML 文件创建的,则 text 属性保存元素起始标签与其第一个子元素或结束标签之间的文本,或者 Nonetail 属性保存元素结束标签与下一个标签之间的文本,或者 None。对于 XML 数据

<a><b>1<c>2<d/>3</c></b>4</a>

a 元素的 texttail 属性均为 Noneb 元素的 text"1"tail"4"c 元素的 text"2"tailNoned 元素的 textNonetail"3"

要收集元素的内部文本,请参阅 itertext(),例如 "".join(element.itertext())

应用程序可以在这些属性中存储任意对象。

attrib

包含元素属性的字典。请注意,虽然 attrib 值始终是真正的可变 Python 字典,但 ElementTree 实现可以选择使用另一种内部表示,并且仅当有人请求时才创建字典。为了利用此类实现,请尽可能使用下面的字典方法。

以下类字典方法适用于元素属性。

clear()

重置一个元素。此函数删除所有子元素,清除所有属性,并将文本和尾部属性设置为 None

get(key, default=None)

获取名为 key 的元素属性。

返回属性值,如果未找到属性,则返回 default

items()

将元素属性作为 (名称, 值) 对的序列返回。属性以任意顺序返回。

keys()

将元素属性名称作为列表返回。名称以任意顺序返回。

set(key, value)

将元素上属性 key 的值设置为 value

以下方法适用于元素的子元素。

append(subelement)

将元素 subelement 添加到此元素的子元素内部列表的末尾。如果 subelement 不是 Element,则引发 TypeError

extend(subelements)

从元素的可迭代对象中附加 subelements。如果子元素不是 Element,则引发 TypeError

在 3.2 版本加入。

find(match, namespaces=None)

查找与 match 匹配的第一个子元素。match 可以是标签名称或 路径。返回元素实例或 Nonenamespaces 是从命名空间前缀到完整名称的可选映射。传递 '' 作为前缀,将表达式中所有未加前缀的标签名称移动到给定命名空间中。

findall(match, namespaces=None)

通过标签名称或 路径 查找所有匹配的子元素。返回一个列表,其中包含按文档顺序排列的所有匹配元素。namespaces 是从命名空间前缀到完整名称的可选映射。传递 '' 作为前缀,将表达式中所有未加前缀的标签名称移动到给定命名空间中。

findtext(match, default=None, namespaces=None)

查找与 match 匹配的第一个子元素的文本。match 可以是标签名称或 路径。返回第一个匹配元素的文本内容,如果没有找到元素,则返回 default。请注意,如果匹配元素没有文本内容,则返回空字符串。namespaces 是从命名空间前缀到完整名称的可选映射。传递 '' 作为前缀,将表达式中所有未加前缀的标签名称移动到给定命名空间中。

insert(index, subelement)

在元素的给定位置插入 subelement。如果 subelement 不是 Element,则引发 TypeError

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 对象

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)

通用元素结构构建器。此构建器将一系列 start、data、end、comment 和 pi 方法调用转换为格式良好的元素结构。您可以使用此类别使用自定义 XML 解析器或用于其他类似 XML 格式的解析器构建元素结构。

如果给定 element_factory,它必须是一个可调用对象,接受两个位置参数:标签和属性字典。它应返回一个新的元素实例。

如果给定 comment_factorypi_factory 函数,它们应像 Comment()ProcessingInstruction() 函数一样,用于创建注释和处理指令。如果未给定,则使用默认工厂。当 insert_comments 和/或 insert_pis 为真时,如果注释/pi 出现在根元素内(但不在根元素之外),它们将被插入到树中。

close()

刷新构建器缓冲区,并返回顶层文档元素。返回一个 Element 实例。

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()

完成向解析器提供数据。返回调用构造期间传入的 targetclose() 方法的结果;默认情况下,这是顶层文档元素。

feed(data)

向解析器提供数据。data 是编码数据。

flush()

触发对所有先前提供的未解析数据的解析,这可用于确保更即时的反馈,特别是对于 Expat >=2.6.0。 flush() 的实现暂时禁用 Expat 的重新解析延迟(如果当前已启用)并触发重新解析。禁用重新解析延迟具有安全隐患;有关详细信息,请参阅 xml.parsers.expat.xmlparser.SetReparseDeferralEnabled()

请注意,flush() 已作为安全修复程序向后移植到 CPython 的某些早期版本。如果在各种 Python 版本上运行的代码中使用 flush(),请使用 hasattr() 检查其可用性。

在 3.13 版本加入。

XMLParser.feed() 为每个开始标签调用 targetstart(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 版本中的更改: 添加了 commentpi 事件。

异常

class xml.etree.ElementTree.ParseError

XML 解析错误,当解析失败时由本模块中的各种解析方法引发。此异常实例的字符串表示将包含用户友好的错误消息。此外,它将具有以下可用属性

code

来自 expat 解析器的数字错误代码。有关错误代码及其含义的列表,请参阅 xml.parsers.expat 的文档。

position

一个 linecolumn 数字元组,指定错误发生的位置。

脚注