xml.etree.ElementTree

xml.etree.ElementTree - ElementTree XML API

2.5版本中的新功能。

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

Element类型是一个灵活的容器对象,用于在内存中存储分层数据结构。该类型可以被描述为列表和字典之间的交叉。

警告

xml.etree.ElementTree模块对恶意构建的数据不安全。如果您需要解析不可信或未经身份验证的数据,请参阅XML漏洞。

每个元素都有一些与之相关的属性:

  • 一个标识符,它是一个字符串,用于标识此元素表示什么类型的数据(换句话说,元素类型)。

  • 一些存储在Python字典中的属性。

  • 一个文本字符串。

  • 一个可选尾部字符串。

  • 一些以Python序列存储的子元素

要创建元素实例,请使用Element构造函数或SubElement()厂函数。

ElementTree类可以用来包装的元件结构,并且它从和向XML转换。

此API的AC实现可用xml.etree.cElementTree

有关教程和其他文档的链接,请参阅http://effbot.org/zone/element-index.htm。Fredrik Lundh的页面也是xml.etree.ElementTree开发版本的位置。

版本2.7中更改:ElementTree API更新为1.3。有关更多信息,请参见ElementTree 1.3简介

1.教程

这是一个简短的教程xml.etree.ElementTree(简而言之为ET)。目标是展示模块的一些构建模块和基本概念。

1.1 XML树和元素

XML是一种固有的分层数据格式,用树来表示它是最自然的方式。 ET有两个类用于此目的 - ElementTree将整个XML文档表示为树,Element表示此树中的单个节点。 与整个文档的交互(读取和写入文件)通常在ElementTree级别完成。 与单个XML元素及其子元素的交互是在元素级别完成的。

1.2 解析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'

1.3 寻找有趣的元素

元素有一些有用的方法可以递归地遍历它下面的所有子树(子元素,子元素等等)。 例如,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,可以查找哪些元素的更复杂的规范。

1.4 修改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'): ... rank = int(country.find('rank').text) ... if rank > 50: ... root.remove(country) ... >>> 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> </data>

1.5 构建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>

1.6 用命名空间解析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()或xpath中的每个标记或属性findall()

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

1.7 其他资源

有关教程和其他文档的链接,请参阅http://effbot.org/zone/element-index.htm

2. XPath支持

此模块为XPath表达式在树中定位元素提供了有限的支持。目标是支持缩写语法的一小部分; 完整的XPath引擎不在该模块的范围内。

2.1 例

下面是一个演示模块的一些XPath功能的示例。我们将使用countrydataParsing XML部分中的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]")

2.2 支持的XPath语法

句法含义
tag选择具有给定标签的所有子元素。例如,垃圾邮件会选择所有名为垃圾邮件的子元素,而垃圾邮件/邮件会在所有名为垃圾邮件的孩子中选择名为egg的所有孙子。
*选择所有子元素。例如,* /鸡蛋选择所有名为鸡蛋的孙子。
.选择当前节点。这在路径开始时最有用,表明它是相对路径。
//选择当前元素下所有级别的所有子元素。例如,// egg选择整棵树中的所有蛋元素。
..选择父元素。
@attrib选择具有给定属性的所有元素。
@attrib='value'选择给定属性具有给定值的所有元素。该值不能包含引号。
tag选择具有子名称标签的所有元素。只支持直接的孩子。
tag='text' 选择具有子名称标签的所有元素,其完整文本内容(包括后代)等于给定文本。
position选择位于给定位置的所有元素。该位置可以是整数(1是第一个位置),表达式last()(用于最后一个位置)或相对于最后位置(例如last() - 1)的位置。

谓词(方括号内的表达式)必须以标记名称,星号或其他谓词开头。position谓词必须以标签名称开头。

3.参考

3.1 功能

xml.etree.ElementTree.Comment(text=None)

注释元素工厂。该工厂函数创建一个特殊元素,该元素将被标准串行器序列化为XML注释。注释字符串可以是字符串或Unicode字符串。文本是包含注释字符串的字符串。返回表示评论的元素实例。

xml.etree.ElementTree.dump(elem)

将元素树或元素结构写入sys.stdout。该功能只能用于调试。

确切的输出格式是依赖于实现的。在这个版本中,它被写成普通的XML文件。

elem 是元素树或个别元素。

xml.etree.ElementTree.fromstring(text)

从字符串常量中解析XML部分。 与XML()相同。 文本是一个包含XML数据的字符串。 返回一个Element实例。

xml.etree.ElementTree.fromstringlist(sequence, parser=None)

从一系列字符串片段中解析XML文档。序列是包含XML数据片段的列表或其他序列解析器是一个可选的解析器实例。如果没有给出,XMLParser则使用标准解析器。返回一个Element实例。

2.7版本的新功能。

xml.etree.ElementTree.iselement(element)

检查对象是否是有效的元素对象。元素是一个元素实例。如果这是一个元素对象,则返回一个真值。

xml.etree.ElementTree.iterparse(source, events=None, parser=None)

逐步将XML部分解析为元素树,并向用户报告发生了什么。 源是包含XML数据的文件名或文件对象。 事件是要回报的事件列表。 如果省略,则仅报告“结束”事件。 解析器是一个可选的解析器实例。 如果没有给出,则使用标准的XMLParser解析器。 解析器不被cElementTree支持。 返回提供(event,elem)对的迭代器。

注意

iterparse()只保证它在发出“开始”事件时已经看到了开始标记的“>”字符,因此定义了属性,但是文本和尾部属性的内容在此处未定义。这同样适用于子元素; 他们可能会或可能不会在场。

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

xml.etree.ElementTree.parse(source, parser=None)

将XML部分解析为元素树。是包含XML数据的文件名或文件对象。解析器是一个可选的解析器实例。如果没有给出,XMLParser则使用标准解析器。返回一个ElementTree实例。

xml.etree.ElementTree.ProcessingInstruction(target, text=None)

PI元件工厂。这个工厂函数创建一个特殊的元素,它将被序列化为XML处理指令。target是包含PI目标的字符串。文本是包含PI内容的字符串(如果给出)。返回一个表示处理指令的元素实例。

xml.etree.ElementTree.register_namespace(prefix, uri)

注册一个名称空间前缀。注册表是全局的,任何现有的给定前缀或名称空间URI映射都将被删除。前缀是一个名称空间前缀uri是一个命名空间uri。如果可能的话,该命名空间中的标签和属性将与给定的前缀一起序列化。

2.7版本的新功能。

xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)

子元素工厂。此函数创建一个元素实例,并将其附加到现有元素。

元素名称,属性名称和属性值可以是字节串或Unicode字符串。父母父母的元素。标记是子元素名称。attrib是一个可选字典,包含元素属性。extra包含其他属性,作为关键字参数给出。返回一个元素实例。

xml.etree.ElementTree.tostring(element, encoding="us-ascii", method="xml")

生成一个XML元素的字符串表示,包括所有子元素。 元素是元素实例。 encoding [1]是输出编码(默认是US-ASCII)。 方法是“xml”,“html”或“text”(默认为“xml”)。 返回包含XML数据的编码字符串。

xml.etree.ElementTree.tostringlist(element, encoding="us-ascii", method="xml")

生成一个XML元素的字符串表示,包括所有子元素。 元素是元素实例。 encoding [1]是输出编码(默认是US-ASCII)。 方法是“xml”,“html”或“text”(默认为“xml”)。 返回包含XML数据的编码字符串列表。 它不保证任何特定的顺序,除了“”.join(tostringlist(element))== tostring(element)。

2.7版本的新功能。

xml.etree.ElementTree.XML(text, parser=None)

从字符串常量中解析XML部分。 这个函数可以用来在Python代码中嵌入“XML文字”。 文本是一个包含XML数据的字符串。 解析器是一个可选的解析器实例。 如果没有给出,则使用标准的XMLParser解析器。 返回一个Element实例。

xml.etree.ElementTree.XMLID(text, parser=None)

从字符串常量中解析XML部分,并返回一个从元素ID:s映射到元素的字典。 文本是一个包含XML数据的字符串。 解析器是一个可选的解析器实例。 如果没有给出,则使用标准的XMLParser解析器。 返回包含元素实例和字典的元组。

3.2 元素对象

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

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

元素名称,属性名称和属性值可以是字节串或Unicode字符串。标签是元素名称。attrib是一个可选字典,包含元素属性。extra包含其他属性,作为关键字参数给出。

tag

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

texttail

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

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

对于文本和尾部属性,a元素具有None,b元素具有文本“1”和尾部“4”,c元素具有文本“2”和尾部无,并且d元素具有文本None和尾部“3”。

收集的元件的内文,见itertext(),例如"".join(element.itertext())

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

attrib

包含元素属性的字典。请注意,虽然attrib值始终是一个真正可变的Python字典,但ElementTree实现可能会选择使用另一个内部表示,并且只有在有人要求时才创建字典。要利用这些实现,请尽可能使用下面的字典方法。

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

clear()

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

get(key, default=None)

获取名为key的元素属性。

返回属性值,如果未找到该属性,则返回默认值。

items()

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

keys()

以列表形式返回元素属性名称。名称以任意顺序返回。

set(key, value)

将元素上的属性设置为

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

append(subelement)

将元素子元素添加到此元素内部子元素列表的末尾。

extend(subelements)

从零个或多个元素的序列对象追加元素。如果元素不是有效的对象,则引发AssertionError

2.7版本的新功能。

find(match)

查找第一个子元素匹配匹配匹配可以是标签名称或路径。返回一个元素实例或None

findall(match)

按标记名称或路径查找所有匹配的子元素。返回包含文档顺序中所有匹配元素的列表。

findtext(match, default=None)

查找第一个子元素匹配匹配的文本。匹配可以是标签名称或路径。返回第一个匹配元素的文本内容,如果没有找到元素,则返回默认值。请注意,如果匹配元素没有文本内容,则返回空字符串。

getchildren()

从版本2.7开始弃用:使用list(elem)或迭代。

getiterator(tag=None)

自2.7版弃用:Element.iter()改为使用方法。

insert(index, element)

在此元素的给定位置插入一个子元素。

iter(tag=None)

创建一个以当前元素为根的树型迭代器。迭代器以文档(深度优先)顺序遍历此元素及其下的所有元素。如果标签不是None或者'*',则只有标签等于标签的元素从迭代器返回。如果在迭代期间修改了树结构,结果是未定义的。

2.7版本的新功能。

iterfind(match)

按标记名称或路径查找所有匹配的子元素。返回按文档顺序产生所有匹配元素的迭代。

2.7版本的新功能。

itertext()

创建一个文本迭代器。迭代器按照文档顺序遍历此元素和所有子元素,并返回所有内部文本。

2.7版本的新功能。

makeelement(tag, attrib)

创建与此元素相同类型的新元素对象。不要调用这个方法,SubElement()而是使用工厂函数。

remove(subelement)

从元素中删除元素。与find *方法不同,此方法根据实例标识比较元素,而不是标签值或内容。

元素对象还支持以下用于处理子元素的序列类型方法:__delitem __(),__getitem __(),__setitem __(),__len __()。

小心:没有子元素的元素将测试为False。 这种行为在未来的版本中会改变。 使用特定的len(elem)或elem代替无测试。

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.3 ElementTree对象

class xml.etree.ElementTree.ElementTree(element=None, file=None)

ElementTree包装类。该类表示整个元素层次结构,并为标准XML序列化和额外支持。

元素 是根元素。如果给定,树会用XML 文件的内容进行初始化。

_setroot(element)

替换此树的根元素。这会丢弃树的当前内容,并用给定的元素替换它。小心使用。元素是一个元素实例。

find(match)

Element.find()相同,从树的根开始。

findall(match)

Element.findall()相同,从树的根开始。

findtext(match, default=None)

Element.findtext()相同,从树的根开始。

getiterator(tag=None)

自2.7版弃用:ElementTree.iter()改为使用方法。

getroot()

返回此树的根元素。

iter(tag=None)

创建并返回根元素的树型迭代器。迭代器按照节的顺序遍历树中的所有元素。标签是要查找的标签(默认是返回所有元素)。

iterfind(match)

按标记名称或路径查找所有匹配的子元素。与getroot()。iterfind(match)相同。返回按文档顺序产生所有匹配元素的迭代。

2.7版本的新功能。

parse(source, parser=None)

将外部XML部分加载到此元素树中。是一个文件名或文件对象。解析器是一个可选的解析器实例。如果没有给出,则使用标准的XMLParser解析器。返回节根元素。

write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml")

将元素树作为XML写入文件文件是一个文件名,或者是一个为写入而打开的文件对象。encoding [1]是输出编码(默认是US-ASCII)。xml_declaration控制是否应该将XML声明添加到文件中。使用False了永远,True为始终,None仅当不US-ASCII或UTF-8(默认为None)。default_namespace设置默认的XML名称空间(对于“xmlns”)。方法是任一"xml""html""text"(默认为"xml")。返回编码的字符串。

这是将要被操纵的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")

3.4 QName对象

class xml.etree.ElementTree.QName(text_or_uri, tag=None)

QName包装。这可以用来包装QName属性值,以便在输出上获得正确的名称空间处理。text_or_uri是一个包含QName值的字符串,格式为{uri} local,或者,如果给出tag参数,则为QName的URI部分。如果给出标签,则第一个参数被解释为URI,并且该参数被解释为本地名称。QName实例是不透明的。

3.5 TreeBuilder对象

class xml.etree.ElementTree.TreeBuilder(element_factory=None)

通用元素结构构建器。该构建器将一系列开始,数据和结束方法调用转换为格式良好的元素结构。您可以使用此类使用自定义XML解析器构建元素结构,或使用其他类似XML的格式的解析器。该element_factory被调用来创建新的Element给药时的情况。

close()

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

data(data)

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

end(tag)

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

start(tag, attrs)

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

另外,一个自定义TreeBuilder对象可以提供以下方法:

doctype(name, pubid, system)

处理文档类型声明。名称是文档的名称pubid是公共标识符。系统系统标识符。此方法在默认TreeBuilder类中不存在。

2.7版本的新功能。

3.6 XMLParser对象

class xml.etree.ElementTree.XMLParser(html=0, target=None, encoding=None)

ElementXML源数据的结构构建器,基于expat分析器。html是预定义的HTML实体。当前实现不支持此标志。目标目标对象。如果省略,构建器将使用标准TreeBuilder类的实例。编码 [1]是可选的。如果给定,则该值将覆盖在XML文件中指定的编码

close()

完成将数据提供给解析器。返回一个元素结构。

doctype(name, pubid, system)

自2.7版弃用:TreeBuilder.doctype()在自定义TreeBuilder目标上定义方法。

feed(data)

数据提供给解析器。数据是编码数据

XMLParser.feed()为每个开始标记调用target的start()方法,为每个结束标记调用end()方法,数据由方法data()处理。 XMLParser.close()调用目标的方法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

脚注

1XML输出中包含的编码字符串应符合相应的标准。例如,“UTF-8”是有效的,但“UTF8”不是。请参阅https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl和https://www.iana.org/assignments/character-sets/character-sets.xhtml。