xml.etree.ElementTree — ElementTree XML API

源代码: Lib/xml/etree/ElementTree.py


xml.etree.ElementTree 模块实现了一个简单高效的 API,用于解析和创建 XML 数据。

在 3.3 版本中变更: 此模块将在可用时使用快速实现。

自 3.3 版本起弃用: xml.etree.cElementTree 模块已被弃用。

警告

xml.etree.ElementTree 模块对于恶意构造的数据不安全。 如果需要解析不受信任或未经身份验证的数据,请参阅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.text),添加和修改属性(Element.set() 方法),以及添加新的子元素(例如使用 Element.append())来操作 Element 对象。

假设我们想将每个国家的排名加一,并在排名元素中添加一个 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 示例的一种方法是将 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 功能的示例。我们将使用来自 解析 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

选择所有具有给定标签的子元素。 例如, 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 跳过输入中的注释,而不是为它们创建注释对象。只有当使用 Element 方法之一将注释节点插入到树中时,ElementTree 才会包含注释节点。

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) 对的 迭代器;它有一个 root 属性,该属性引用一旦完全读取 source 后生成的 XML 树的根元素。如果 source 是文件名,则迭代器具有关闭内部文件对象的 close() 方法。

请注意,虽然 iterparse() 会增量地构建树,但它会在 source(或它命名的文件)上发出阻塞读取。因此,它不适用于无法进行阻塞读取的应用程序。有关完全非阻塞的解析,请参阅 XMLPullParser

注解

iterparse() 发出 “start” 事件时,它仅保证它已看到开始标记的 “>” 字符,因此属性已定义,但此时文本和 tail 属性的内容未定义。这同样适用于元素子元素;它们可能存在也可能不存在。

如果您需要完全填充的元素,请查找 “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 对象。只有当使用 Element 方法之一将处理指令节点插入到树中时,ElementTree 才会包含处理指令节点。

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 参数。

Element 对象

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

Element 类。此类定义了 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 元素的 texttail 属性均为 Noneb 元素的 text"1"tail"4"c 元素的 text"2"tailNoned 元素的 textNonetail"3"

要收集元素的内部文本,请参阅 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

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

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)

通用元素结构构建器。此构建器将一系列开始、数据、结束、注释和 pi 方法调用转换为格式良好的元素结构。您可以使用此类使用自定义 XML 解析器或某种其他类似 XML 格式的解析器来构建元素结构。

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

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

close()

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

data(data)

将文本添加到当前元素。data 是一个字符串。这应该是一个字节串或一个 Unicode 字符串。

end(tag)

关闭当前元素。tag 是元素名称。返回已关闭的元素。

start(tag, attrs)

打开一个新元素。tag 是元素名称。attrs 是一个包含元素属性的字典。返回打开的元素。

comment(text)

使用给定的 text 创建注释。如果 insert_comments 为 true,则也会将其添加到树中。

在 3.8 版本中添加。

pi(target, text)

使用给定的 target 名称和 text 创建处理指令。如果 insert_pis 为 true,则也会将其添加到树中。

在 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() 回调之后调用,名称是超出作用域的前缀

在 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 版本中运行的代码中使用,请使用 hasattr() 检查 flush() 的可用性。

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 版本中运行的代码中使用,请使用 hasattr() 检查 flush() 的可用性。

3.13 版本新增。

close()

向解析器发出数据流已终止的信号。与 XMLParser.close() 不同,此方法始终返回 None。当解析器关闭时,任何尚未检索到的事件仍然可以使用 read_events() 读取。

read_events()

返回一个迭代器,该迭代器遍历在馈送到解析器的数据中遇到的事件。迭代器生成 (event, elem) 对,其中 event 是表示事件类型的字符串(例如 "end"),而 elem 是遇到的 Element 对象或其他上下文值,如下所示。

  • start, end:当前的 Element。

  • comment, pi:当前注释/处理指令

  • start-ns:一个元组 (prefix, uri),命名声明的命名空间映射。

  • end-nsNone(这可能会在未来版本中更改)

先前调用 read_events() 中提供的事件将不会再次产生。只有当从迭代器中检索事件时,才会从内部队列中消耗事件,因此并行迭代从 read_events() 获取的迭代器的多个读取器将产生不可预测的结果。

注解

XMLPullParser 仅保证当它发出“start”事件时,它已经看到了起始标记的“>”字符,因此属性已定义,但此时文本和 tail 属性的内容未定义。同样适用于元素子节点;它们可能存在也可能不存在。

如果您需要完全填充的元素,请查找 “end” 事件。

3.4版本新增。

在 3.8 版本中更改: 添加了 commentpi 事件。

异常

class xml.etree.ElementTree.ParseError

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

code

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

position

一个 line(行)和 column(列)数字的元组,指定错误发生的位置。

脚注