Python 如何使用 ElementTree 在 XML 中查找特定元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16419673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to find specific elements in XML using ElementTree
提问by Nawaz
I'm trying to parse XML string which I get from youtube video feeds, using Python 3.3.1. Here is the code:
我正在尝试解析从 youtube 视频提要获得的 XML 字符串,使用Python 3.3.1. 这是代码:
import re
import sys
import urllib.request
import urllib.parse
import xml.etree.ElementTree as element_tree
def get_video_id(video_url):
return re.search(r'watch\?v=.*', video_url).group(0)[8:]
def get_video_feed(video_url):
video_feed = "http://gdata.youtube.com/feeds/api/videos/" + get_video_id(video_url)
return urllib.request.urlopen(video_feed).read()
def get_media_info(video_url):
content = get_video_feed(video_url)
content = str(content, 'ascii')
media = {}
e = element_tree.XML(content);
print ( "CONTENT: \n" + content )
print ( "\n\nELEMENTS : \n")
for i in list(e):
print (i)
media['title'] = e.findall('title') //NOTE THIS!
return media
def main():
video_url = 'http://youtube.com/watch?v=q5sOLzEerwA'
print ( get_media_info(video_url) )
if __name__ == '__main__':
main()
I've no idea why the forloop in get_media_info()prints elements as
我不知道为什么for循环get_media_info()打印元素为
<Element '{http://www.w3.org/2005/Atom}title' at 0x0000000002BF7D18>
instead of this:
而不是这个:
<Element 'title' at 0x0000000002BF7D18>
Frankly, I don't care what it prints. All I care is that I want to pass 'title'to findall()and expect a list of element(s) as returned value. But it returns empty list, even though there is one element with name titlein the xml.
坦率地说,我不在乎它打印什么。我只关心我想传递'title'给findall()并期望元素列表作为返回值。但它返回空列表,即使titlexml 中有一个带名称的元素。
So I tried this:
所以我试过这个:
media['title'] = e.findall('{http://www.w3.org/2005/Atom}title')
And it did return a list of one element. I'm sure this is not the way to do it, and I feel I'm missing something.
它确实返回了一个元素的列表。我确定这不是这样做的方法,我觉得我错过了一些东西。
How to fix this?
如何解决这个问题?
This is the output of the above code:
这是上面代码的输出:
CONTENT:
内容:
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:yt='http://gdata.youtube.com/schemas/2007'>
<id>http://gdata.youtube.com/feeds/api/videos/q5sOLzEerwA</id>
<published>2011-12-01T18:18:36.000Z</published>
<updated>2013-05-07T03:20:04.000Z</updated>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>
<category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' term='Music' label='Music'/>
<title type='text'>Kala Bazaar - Khoya Khoya Chand Khula Aasman - Mohd Rafi.flv</title>
<content type='text'>tanhayi me akele me khoya khoya chand.........</content>
<link rel='alternate' type='text/html' href='http://www.youtube.com/watch?v=q5sOLzEerwA&feature=youtube_gdata'/>
<link rel='http://gdata.youtube.com/schemas/2007#video.responses' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/q5sOLzEerwA/responses'/>
<link rel='http://gdata.youtube.com/schemas/2007#video.related' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/q5sOLzEerwA/related'/>
<link rel='http://gdata.youtube.com/schemas/2007#mobile' type='text/html' href='http://m.youtube.com/details?v=q5sOLzEerwA'/>
<link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/q5sOLzEerwA'/>
<author>
<name>a1a2a3a4a786</name>
<uri>http://gdata.youtube.com/feeds/api/users/a1a2a3a4a786</uri>
</author>
<gd:comments>
<gd:feedLink rel='http://gdata.youtube.com/schemas/2007#comments' href='http://gdata.youtube.com/feeds/api/videos/q5sOLzEerwA/comments' countHint='6'/>
</gd:comments>
<media:group>
<media:category label='Music' scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>Music</media:category>
<media:content url='http://www.youtube.com/v/q5sOLzEerwA?version=3&f=videos&app=youtube_gdata' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='293' yt:format='5'/>
<media:content url='rtsp://v6.cache3.c.youtube.com/CiILENy73wIaGQkArx4xLw6bqxMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='293' yt:format='1'/>
<media:content url='rtsp://v6.cache3.c.youtube.com/CiILENy73wIaGQkArx4xLw6bqxMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='293' yt:format='6'/>
<media:description type='plain'>tanhayi me akele me khoya khoya chand.........</media:description>
<media:keywords/>
<media:player url='http://www.youtube.com/watch?v=q5sOLzEerwA&feature=youtube_gdata_player'/>
<media:thumbnail url='http://i.ytimg.com/vi/q5sOLzEerwA/0.jpg' height='360' width='480' time='00:02:26.500'/>
<media:thumbnail url='http://i.ytimg.com/vi/q5sOLzEerwA/1.jpg' height='90' width='120' time='00:01:13.250'/>
<media:thumbnail url='http://i.ytimg.com/vi/q5sOLzEerwA/2.jpg' height='90' width='120' time='00:02:26.500'/>
<media:thumbnail url='http://i.ytimg.com/vi/q5sOLzEerwA/3.jpg' height='90' width='120' time='00:03:39.750'/>
<media:title type='plain'>Kala Bazaar - Khoya Khoya Chand Khula Aasman - Mohd Rafi.flv</media:title>
<yt:duration seconds='293'/>
</media:group>
<gd:rating average='4.733333' max='5' min='1' numRaters='30' rel='http://schemas.google.com/g/2005#overall'/>
<yt:statistics favoriteCount='0' viewCount='8140'/>
</entry>
ELEMENTS :
元素:
<Element '{http://www.w3.org/2005/Atom}id' at 0x0000000002BF79F8>
<Element '{http://www.w3.org/2005/Atom}published' at 0x0000000002BF7B88>
<Element '{http://www.w3.org/2005/Atom}updated' at 0x0000000002BF7A48>
<Element '{http://www.w3.org/2005/Atom}category' at 0x0000000002BF7C78>
<Element '{http://www.w3.org/2005/Atom}category' at 0x0000000002BF7CC8>
<Element '{http://www.w3.org/2005/Atom}title' at 0x0000000002BF7D18>
<Element '{http://www.w3.org/2005/Atom}content' at 0x0000000002BF7D68>
<Element '{http://www.w3.org/2005/Atom}link' at 0x0000000002BF7DB8>
<Element '{http://www.w3.org/2005/Atom}link' at 0x0000000002BF7E08>
<Element '{http://www.w3.org/2005/Atom}link' at 0x0000000002BF7E58>
<Element '{http://www.w3.org/2005/Atom}link' at 0x0000000002BF7EA8>
<Element '{http://www.w3.org/2005/Atom}link' at 0x0000000002BF7EF8>
<Element '{http://www.w3.org/2005/Atom}author' at 0x0000000002BF7F48>
<Element '{http://schemas.google.com/g/2005}comments' at 0x0000000002C0B0E8>
<Element '{http://search.yahoo.com/mrss/}group' at 0x0000000002C0B1D8>
<Element '{http://schemas.google.com/g/2005}rating' at 0x0000000002C0B778>
<Element '{http://gdata.youtube.com/schemas/2007}statistics' at 0x0000000002C0B7C8>
{'title': []}
回答by gsmaker
Actually I have tried the following way using xml.dom.minidom, Just in case it helps you anyway.
实际上,我已经尝试了以下使用方法xml.dom.minidom,以防万一它对您有所帮助。
#!/usr/bin/python
from xml.dom.minidom import parseString
import re
import urllib
def get_video_id(video_url):
return re.search(r'watch\?v=.*', video_url).group(0)[8:]
def get_video_feed(video_url):
video_feed = "http://gdata.youtube.com/feeds/api/videos/" + get_video_id(video_url)
print video_feed
return urllib.urlopen(video_feed).read()
def get_media_info(video_url):
content = get_video_feed(video_url)
dom = parseString(content)
media = {}
media['title'] = dom.getElementsByTagName('title')[0].firstChild.nodeValue
return media
def main():
video_url = 'http://youtube.com/watch?v=q5sOLzEerwA'
print ( get_media_info(video_url) )
if __name__ == '__main__':
main()
回答by Mark Tolonen
The namespace of an XML document is significant. ElementTree requires tags to be fully qualified to find the right element. Here's an example of three elements with the same tag in different namespaces:
XML 文档的名称空间很重要。ElementTree 需要完全限定标签才能找到正确的元素。下面是在不同命名空间中具有相同标记的三个元素的示例:
data = '''\
<root xmlns="xyz" xmlns:name="abc">
<object name="one" />
<name:object name="two" />
<object xmlns="def" name="three" />
</root>
'''
Here's the elements that ElementTree sees:
这是 ElementTree 看到的元素:
>>> from xml.etree import ElementTree as et
>>> tree = et.fromstring(data)
>>> print(tree.findall('.//*'))
>>> et.dump(tree)
[<Element '{xyz}object' at 0x0000000003B07BD8>,
<Element '{abc}object' at 0x0000000003B07C28>,
<Element '{def}object' at 0x0000000003B07C78>]
So you have it right. Given the default namespace definition of:
所以你说得对。鉴于默认命名空间定义:
<entry xmlns='http://www.w3.org/2005/Atom' ...
To access the 'title' tag, which uses the default namespace:
要访问使用默认命名空间的“title”标签:
media['title'] = e.findall('{http://www.w3.org/2005/Atom}title')
to access the 'media:group' tag, refer to the media namespace definition:
要访问“media:group”标签,请参考媒体命名空间定义:
<entry ... xmlns:media='http://search.yahoo.com/mrss/' ...
And use:
并使用:
e.findall('{http://search.yahoo.com/mrss/}group')
Note the different ways a namespace can be specified:
请注意可以指定命名空间的不同方式:
<root xmlns="xyz" xmlns:name="abc"> # default namespace and
# 'abc' namespace with id 'name'.
<object name="one" /> # Uses default namespace 'xyz'.
<name:object name="two" /> # uses 'abc' namespace (specified by id).
<object xmlns="def" name="three" /> # change the default namespace to 'def'.
</root>
To read a specific tag from a specific namespace:
从特定命名空间读取特定标签:
>>> print(tree.find('{abc}object').attrib['name'])
'two'
Note the namespace IDs are just shortcuts. Here's what happens when you dump the parsed XML tree. ElementTree doesn't bother to save the original namespace IDs and generates its own in the format ns#:
请注意,命名空间 ID 只是快捷方式。以下是转储解析的 XML 树时发生的情况。ElementTree 不会费心保存原始命名空间 ID 并以以下格式生成自己的命名空间 ID ns#:
>>> et.dump(tree)
<ns0:root xmlns:ns0="xyz" xmlns:ns1="abc" xmlns:ns2="def">
<ns0:object name="one" />
<ns1:object name="two" />
<ns2:object name="three" />
</ns0:root>
If you want specific shortcuts defined, use `register_namespace':
如果您想定义特定的快捷方式,请使用“register_namespace”:
>>> et.register_namespace('','xyz') # default namespace
>>> et.register_namespace('name','abc')
>>> et.register_namespace('custom','def')
>>> et.dump(tree)
<root xmlns="xyz" xmlns:custom="def" xmlns:name="abc">
<object name="one" />
<name:object name="two" />
<custom:object name="three" />
</root>

