VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Python3标准库:xml.etree.ElementTree XML操纵API

1. xml.etree.ElementTree XML操纵API

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

1.1 解析XML文档

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

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

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

podcasts.opml:


	
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <opml version="1.0">
  3. <head>
  4. <title>My Podcasts</title>
  5. <dateCreated>Sat, 06 Aug 2016 15:53:26 GMT</dateCreated>
  6. <dateModified>Sat, 06 Aug 2016 15:53:26 GMT</dateModified>
  7. </head>
  8. <body>
  9. <outline text="Non-tech">
  10. <outline
  11. text="99% Invisible" type="rss"
  12. xmlUrl="http://feeds.99percentinvisible.org/99percentinvisible"
  13. htmlUrl="http://99percentinvisible.org" />
  14. </outline>
  15. <outline text="Python">
  16. <outline
  17. text="Talk Python to Me" type="rss"
  18. xmlUrl="https://talkpython.fm/episodes/rss"
  19. htmlUrl="https://talkpython.fm" />
  20. <outline
  21. text="Podcast.__init__" type="rss"
  22. xmlUrl="http://podcastinit.podbean.com/feed/"
  23. htmlUrl="http://podcastinit.com" />
  24. </outline>
  25. </body>
  26. </opml>

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


	
  1. from xml.etree import ElementTree
  2.  
  3. with open('podcasts.opml', 'rt') as f:
  4. tree = ElementTree.parse(f)
  5.  
  6. print(tree)

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

1.2 遍历解析树

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


	
  1. from xml.etree import ElementTree
  2.  
  3. with open('podcasts.opml', 'rt') as f:
  4. tree = ElementTree.parse(f)
  5.  
  6. for node in tree.iter():
  7. print(node.tag)

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

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


	
  1. from xml.etree import ElementTree
  2.  
  3. with open('podcasts.opml', 'rt') as f:
  4. tree = ElementTree.parse(f)
  5.  
  6. for node in tree.iter('outline'):
  7. name = node.attrib.get('text')
  8. url = node.attrib.get('xmlUrl')
  9. if name and url:
  10. print(' %s' % name)
  11. print(' %s' % url)
  12. else:
  13. print(name)

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

1.3 查找文档中的节点 

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

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


	
  1. from xml.etree import ElementTree
  2.  
  3. with open('podcasts.opml', 'rt') as f:
  4. tree = ElementTree.parse(f)
  5.  
  6. for node in tree.findall('.//outline'):
  7. url = node.attrib.get('xmlUrl')
  8. if url:
  9. print(url)

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

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