Python模块xml.etree.ElementTree

将使用以下XML文档作为本节的示例数据:

<?xml version="1.0"?> 1 2008 141100 4 2011 59900 68 2011 13600 我们可以通过从文件中读取来导入此数据:

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 构造函数来访问文档类型声明。
Pull API进行非阻塞解析
此模块提供的大多数解析功能要求在返回任何结果之前立即读取整个文档。可以使用和增量地向其中输入 数据,但这是一个推送API,它在回调目标上调用方法,对于大多数需求而言,它太底层且不方便。有时,用户真正想要的是能够逐步解析XML ,而不会阻塞操作,同时又能享受到完全构造对象的便利。XMLParserElement

最强大的工具是。它不需要阻塞读取即可获取XML数据,而是通过调用以增量方式馈送数据。要获取已解析的XML 元素,请调用。这是一个例子:XMLPullParserXMLPullParser.feed()XMLPullParser.read_events()

parser = ET.XMLPullParser([‘start’, ‘end’])
parser.feed(‘sometext’)
list(parser.read_events())
[(‘start’, <Element ‘mytag’ at 0x7fa66db2be58>)]

parser.feed(’ more text’)
for event, elem in parser.read_events():
… print(event)
… print(elem.tag, ‘text=’, elem.text)

end
显而易见的用例是以非阻塞方式运行的应用程序,其中XML数据是从套接字接收或从某个存储设备递增读取的。在这种情况下,阻止读取是不可接受的。

由于它非常灵活,因此在更简单的用例中可能会带来不便。如果您不介意应用程序阻止读取XML 数据,但仍希望具有增量解析功能,请查看参考资料。当您阅读大型XML文档并且不想将其完全保存在内存中时,此功能很有用。XMLPullParseriterparse()

寻找有趣的元素
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.text 访问元素的属性:

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() 添加新的子元素。

假设我们要在每个国家/地区的中添加一个排名,并在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"?> 2 2008 141100 5 2011 59900 69 2011 13600 可以使用 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"?> 2 2008 141100 5 2011 59900 构建XML文档 SubElement() 函数还提供了一种便捷方法来为给定元素创建新的子元素:

a = ET.Element(‘a’)
b = ET.SubElement(a, ‘b’)
c = ET.SubElement(a, ‘c’)
d = ET.SubElement(c, ‘d’)
ET.dump(a)

使用命名空间解析XML
如果XML输入具有名称空间,标签与形式的前缀属性prefix:sometag得到扩展到 {uri}sometag其中的前缀是由完全代替URI。另外,如果存在默认的名称空间,则完整的URI会优先添加到所有非前缀的标签中。

这是一个XML示例,其中包含两个名称空间,一个带有前缀“ fictional”,另一个用作默认名称空间:

<?xml version="1.0"?>



John Cleese
fictional:characterLancelot</fictional:character>
fictional:characterArchie Leach</fictional:character>


Eric Idle
fictional:characterSir Robin</fictional:character>
fictional:characterGunther</fictional:character>
fictional:characterCommander Clement</fictional:character>


搜索和浏览此XML示例的一种方法是将URI手动添加到afind()或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

参考:
https://docs.python.org/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值