Python:libxml2 xpath 返回空列表
我想用Python的libxml2库通过xpath来解析XML内容。我参考了这个例子和那个教程。我的XML文件是:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://purl.org/atom/ns#" version="0.3">
<title>Gmail - Inbox for myemailaddress@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>1</fullcount>
<link rel="alternate" href="http://mail.google.com/mail" type="text/html"/>
<modified>2011-05-04T18:56:19Z</modified>
</feed>
这个XML文件保存在一个叫“atom”的文件里,我尝试了以下操作:
>>> import libxml2
>>> myfile = open('/pathtomyfile/atom', 'r').read()
>>> xmldata = libxml2.parseDoc('myfile')
>>> data.xpathEval('/fullcount')
[]
>>>
现在你可以看到,它返回了一个空列表。不管我给xpath什么,它都返回空列表。不过,如果我使用*
这个通配符,我就能得到所有节点的列表:
>>>> data.xpathEval('//*')
[<xmlNode (feed) object at 0xb73862cc>, <xmlNode (title) object at 0xb738650c>, <xmlNode (tagline) object at 0xb73865ec>, <xmlNode (fullcount) object at 0xb738660c>, <xmlNode (link) object at 0xb738662c>, <xmlNode (modified) object at 0xb738664c>]
现在我不明白,按照上面的工作示例,为什么xpath找不到“fullcount”节点或其他任何节点:毕竟我用的是相同的语法……
有什么想法或建议吗?谢谢。
2 个回答
0
首先:
/fullcount
是一个绝对路径,这意味着它在文档的根部寻找 <fullcount>
元素,但实际上这个元素是在 <feed>
元素里面的。
其次:
你需要指定命名空间。下面是使用 lxml 的方法:
import lxml.etree as etree
tree = etree.parse('/pathtomyfile/atom')
fullcounts = tree.xpath('//ns:fullcount',
namespaces={'ns': "http://purl.org/atom/ns#"})
print etree.tostring(fullcounts[0])
这样做会得到:
<fullcount xmlns="http://purl.org/atom/ns#">1</fullcount>
2
你的XPath出错了,因为你需要在节点上指定purl命名空间:
import libxml2
tree = libxml2.parseDoc(data)
xp = tree.xpathNewContext()
xp.xpathRegisterNs("purl", "http://purl.org/atom/ns#")
print xp.xpathEval('//purl:fullcount')
结果:
[<xmlNode (fullcount) object at 0x7fbbeba9ef80>]
(另外:可以看看lxml,它有一个更好用、更高级的接口)。