1. xml.etree.ElementTree XML操纵API

ElementTree库提供了一些工具,可以使用基于事件和基于文档的API来解析XML,可以用XPath表达式搜索已解析的文档,还可以创建新文档或修改现有文档。

1.1 解析XML文档

已解析的XML文档在内存中由ElementTree和Element对象表示,这些对象基于XML文档中节点嵌套的方式按树结构互相连接。

用parse()解析一个完整的文档时,会返回一个ElementTree实例。这个树了解输入文档中的所有数据,另外可以原地搜索或操纵树中的节点。基于这种灵活性,可以更方便的处理已解析的文档,不过,与基于事件的解析方法相比,这种方法往往需要更多的内存,因为必须一次加载整个文档。

对于简单的小文档(如下面的播客列表,被表示为一个OPML大纲),内存需求不大。

podcasts.opml:

My Podcasts

Sat, 06 Aug 2016 15:53:26 GMT

Sat, 06 Aug 2016 15:53:26 GMT

text="99% Invisible"type="rss"

xmlUrl="http://feeds.99percentinvisible.org/99percentinvisible"

htmlUrl="http://99percentinvisible.org"/>

text="Talk Python to Me"type="rss"

xmlUrl="https://talkpython.fm/episodes/rss"

htmlUrl="https://talkpython.fm"/>

text="Podcast.__init__"type="rss"

xmlUrl="http://podcastinit.podbean.com/feed/"

htmlUrl="http://podcastinit.com"/>

要解析这个文档,需要向parse()传递一个打开的文件句柄。

fromxml.etreeimportElementTree

withopen('podcasts.opml','rt')asf:

tree=ElementTree.parse(f)

print(tree)

这个方法会读取数据、解析XML,并返回一个ElementTree对象。

1.2 遍历解析树

要按顺序访问所有子节点,可以使用iter()创建一个生成器,该生成器迭代处理这个ElementTree实例。

fromxml.etreeimportElementTree

withopen('podcasts.opml','rt')asf:

tree=ElementTree.parse(f)

fornodeintree.iter():

print(node.tag)

这个例子会打印整个树,一次打印一个标记。

如果只是打印播客的名字组和提要URL,则可以只迭代处理outline节点(而不考虑首部中的所有数据),并且通过查找attrib字典中的值来打印text和xmlUrl属性。

fromxml.etreeimportElementTree

withopen('podcasts.opml','rt')asf:

tree=ElementTree.parse(f)

fornodeintree.iter('outline'):

name=node.attrib.get('text')

url=node.attrib.get('xmlUrl')

ifnameandurl:

print('%s'%name)

print('%s'%url)

else:

print(name)

iter()的'outline'参数意味着只处理标记为'outline'的节点。

1.3 查找文档中的节点

查看整个树并搜索有关的节点可能很容易出错。前面的例子必须查看每一个outline节点,来确定这是一个组(只有一个text属性的节点)还是一个播客(包含text和xmlUrl的节点)。要生成一个简单的播客提要URL列表而不包含名字或组,可以简化逻辑,使用findall()来查找有更多描述性搜索特性的节点。

对以上第一个版本做出第一次修改,用一个XPath参数来查找所有outline节点。

fromxml.etreeimportElementTree

withopen('podcasts.opml','rt')asf:

tree=ElementTree.parse(f)

fornodeintree.findall('.//outline'):

url=node.attrib.get('xmlUrl')

ifurl:

print(url)

这个版本中的逻辑与使用getiterator()的版本并没有显著区别。这里仍然必须检查是否存在URL,只不过如果没有发现URL,它不会打印组名。

outline节点只有两层嵌套,可以利用这一点,把搜索路径修改为.//outline/outline,这意味着循环只处理outline节点的第二层。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐