[python]使用ElementTree解析XML【译】
19.7 The ElementTree XML API
源码:Lib/xml/etree/ElementTree.py
Element类型是一个灵活的容器对象,设计出来是用于存储有层次的数据结构到内存中。这个类型可以描述为是列表与字典之间的交叉。
警告:
xml.etree.ElementTree模块对于恶意构造的数据不是安全的。如果你需要解析不可信和未经身份验证的数据请查看XML vulnerabilities.
每个元素都有一系列与其关联的属性:
1. 标签,用于标识该元素表示哪种数据(即元素类型)
2. 一些属性,存储在Python dictionary中
3. 一个文本字符串
4. 一个可选的尾字符串
5. 一些孩子elements,存储在Python sequence中
为了创建一个element实例,使用Element 构造函数或者SubElement()工厂函数。
ElementTree 类可以用来包裹一个element结构,用于与XML进行相互转换。
一个 C语言实现的可用 API : xml.etree.cElementTree.
Changed in version 2.7: The ElementTree API is updated to 1.3. For more information, see Introducing ElementTree 1.3.
19.7.1. 综述
这是关于使用xml.etree.ElementTree (ET)的简要综述,目的是演示如何创建block和模块的基本概念。
19.7.1.1. XML树和elements
XML是一个固有层次的数据格式,最自然的方式代表他就是用tree. ET有两个类来实现这个目的。ElementTree表示整个XML文档,
Element表示树中的一个节点。 遍历整个文档(读写文件)通常使用 ElementTree, 遍历单独的节点或者子节点通常使用element。
19.7.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。
一个Element, 根节点 有一个tag以及一些列属性(保存在dictionary中)
>>> 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'
19.7.1.3. 查找感兴趣的element
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直接的孩子属于某个tag的elements
Element.find() 查找属于某个tag的第一个element
Element.text 访问element的文本内容
Element.get()获取element的属性
>>> 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.可以更加巧妙的访问element。
19.7.1.4. 修改XML文件
ElementTree 提供了一个简单的方法来建立XML文档并将其写入文件。 ElementTree.write() 提供了这个功能。
一旦被建立,一个 Element 对象可能会进行以下操作:改变文本(比如Element.text), 添加或修改属性 (Element.set() ), 添加孩子(例如 Element.append()).
假设我们想将每个国家的排名+1,并且增加一个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>
19.7.1.5. 创建XML文档:
SubElement() 函数也提供了一个为已有element创建子element的简便方法:
>>> 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>
19.7.1.6. 解析带有命名空间的xml
如果一个xml中有命名空间,标签和有前缀形式的属性,比如prefix:sometag,利用{uri}sometag 格式来代替整个uri.
如果有默认的命名空间,则整个的uri使用没有前缀的标签。
下面这个例子是两种命名空间的结合,一个是带有前缀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到每个标签或属性中在xpath的 find()或者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
19.7.1.7. Additional resources
See http://effbot.org/zone/element-index.htm for tutorials and links to other docs.
19.7.2. XPath support
该模块提供了对XPath expressions 的有限的支持。 目的是支持 其中的一部分句法;完整的XPath工程超出了这个模块的范畴。
19.7.2.1. Example
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]")
19.7.2.2. 支持的 XPath 语法
tag
选中给定标签的子元素,举个例子:
spam-表示选择所有叫做spam的子元素
spam/egg-表示选择所有命名为egg的所有孙子,在命名为spam的子元素中。
*
选中全部孩子elements。 For example, */egg selects all grandchildren named egg.
.
选中当前element。 This is mostly useful at the beginning of the path, to indicate that it’s a relative path.
//
选中同一级别的全部子element. For example, .//egg selects all egg elements in the entire tree.
..
选中父亲节点;
[@attrib]
选中含有给定属性的全部节点。
[@attrib='value']
选中含有给定属性以及给定属性值的全部节点。The value cannot contain quotes.
[tag]
选中所有拥有一个叫做tag的孩子的elements。 Only immediate children are supported.
[tag='text']
选中所有拥有一个叫做tag的孩子的elements,该elements包含值为text
[position]
选中所有位于指定位置的elements。 The position can be either an integer
(1 is the first position), the expression last() (for the last position), or a position relative to the last position (e.g. last()-1).
Predicates (expressions within square brackets) must be preceded by a tag name, an asterisk, or another predicate. position predicates must be preceded by a tag name.
未完待续
[python]使用ElementTree解析XML【译】的更多相关文章
- ZH奶酪:Python使用ElementTree解析XML【译】
19.7. xml.etree.ElementTree — The ElementTree XML API 源代码: Lib/xml/etree/ElementTree.py Element类型是一种 ...
- python 使用ElementTree解析xml
以country.xml为例,内容如下: <?xml version="1.0"?> <data> <country name="Liech ...
- Python中使用ElementTree解析xml
在Python中,ElementTree是我们常用的一个解析XML的模块 1.导入ElementTree模块 from xml.etree import ElementTree as ET 2.初始化 ...
- python xml.etree.ElementTree解析xml文件获取节点
<?xml version = "1.0" encoding = "utf-8"?> <root> <body name=&quo ...
- python练习三—解析xml
使用python解析xml,主要使用sax的ContentHandler中的标签开始和标签结束的方法驱动,然后在开始(或者结束)事件中决定使用什么处理方法,使用dispatcher来决定并分发到指定方 ...
- Python requests模块解析XML
检查QQ是否在线(api感觉不准) import requests from xml.etree import ElementTree qq_str = input('please input the ...
- python使用SAX解析xml
python 标准库包含SAX解析器,SAX用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件 在python中使用sax方式处理xml要先引入xml.s ...
- ElementTree 解析xml(minidom解析xml大文件时,MemoryError)
在使用minido解析xml文件时,因为文件过大,结果报错MemoryError.查询后得知是因为minidom在解析时是将所有文件放到内存里的,很占用内存,所以要考虑换一种方法来处理xml文件. ...
- python XML文件解析:用ElementTree解析XML
Python标准库中,提供了ET的两种实现.一个是纯Python实现的xml.etree.ElementTree,另一个是速度更快的C语言实现xml.etree.cElementTree.请记住始终使 ...
随机推荐
- MySQL如何选择float, double, decimal
http://yongxiong.leanote.com/post/mysql_float_double_decimal
- 利用QT开发一个记事本
区别于之前创建爱的各个工程,这次我们在这里选择基类为QMainWindow. 然后默认目录就是 直接到对应文件中进行代码的书写: main.cpp: #include "mainwindow ...
- Spring中bean的scope
Spring容器中的bean具备不同的scope,最开始只有singleton和prototype,但是在2.0之后,又引入了三种类型:request.session和global session,不 ...
- Leetcode 102. Binary Tree Level Order Traversal(二叉树的层序遍历)
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...
- [phpmyadmin] phpmyadmin select command denied to user
phpmyadmin 在查看一个数据库中Table的数据的时候,会提示 select command denied to user 在Ubuntu下,我是使用重装Phpmyadmin的方式解决的 卸载 ...
- SSO单点登录之跨域问题
第一次写博客,与大家共勉. 这里用到的原理其实非常简单,将cookie存在一个公共的站点的页面上就可以了,这里我们管那个站点叫主站S. 先说说所谓的跨域 环境1:a.xxx.com需要跟b.xxx.c ...
- android webview乱码问题
使用 loadData方法是中文部分会出现乱码,即使指定“utf-8”.“gbk”.“gb2312”也一样. webView.getSettings().setDefaultTextEncodingN ...
- 在shell的if条件里,判断 a>0 且 (b>0 或 c>0) ,如何编写?
if [ $b -gt 0 -o $c -gt 0 -a $a -gt 0 ]; then.fi对shell中的关系运算符说明如下:-gt 表示greater than,大于-lt 表示less th ...
- php连接Access数据库的三种方法
http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2009/1115/3524.html 虽然不是一个类但先放这儿吧 最近想把一个asp的网站改成 ...
- tomcat 6 不支持jsf2.2,仅支持jsf2.0及以下版本
tomcat 6 不支持jsf2.2,仅支持jsf2.0及以下版本 安装tomcat8即可.