2011-05-04 214 views
0

我想用Python的libxml2使用xpath解析XML内容,我跟着this examplethat tutorial。 XML文件是:Python:libxml2 xpath返回空列表

<?xml version="1.0" encoding="UTF-8"?> 
<feed xmlns="http://purl.org/atom/ns#" version="0.3"> 
<title>Gmail - Inbox for [email protected]</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存储在一个名为“原子”的文件,我尝试以下方法:

>>> 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”节点或判断任何其他:我使用相同的语法毕竟...

任何想法或建议?谢谢。

+1

为什么不使用lxml? – 2011-05-04 22:20:05

+0

为什么我应该? :)我现在正在查看lxml文档。谢谢。 – Benjamin 2011-05-04 22:35:07

+0

它是libxml2的绑定。我甚至不知道有替代绑定,但lxml非常直观。 – 2011-05-04 22:42:38

回答

2

你的XPath是失败的,因为你需要的节点上指定金银丝命名空间

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,它有一个更好的,更高层次的接口)。

+0

工作答案谢谢:)现在,什么是_purl命名空间_?你能解释一下吗? – Benjamin 2011-05-04 22:52:50

+0

@Benjamin它是供稿标签中定义的默认文档名称空间:''。这是将文档中的所有节点分配给该名称空间的快捷方式。因此,无论何时您询问libxml2关于本文档中的节点并未能包含名称空间,都不知道您的意思。 :-) – samplebias 2011-05-04 22:55:04

+0

谢谢,我是新的命名空间的概念。命名空间提供了什么,定义? – Benjamin 2011-05-04 23:15:14

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>