Python libxml2 XPath/命名空间帮助

3 投票
1 回答
3223 浏览
提问于 2025-04-16 07:47

我正在尝试学习如何在Python中使用XPath查询,参考这个示例XML文件:http://pastie.org/1333021。我刚刚给它添加了一个命名空间,因为我实际的应用程序中用到了这个。

基本上,我想执行一个顶层查询,返回一部分节点,然后对这部分节点进行查询(这比这个例子要大得多)。

所以这是我的代码,首先找到所有的<food>节点,然后遍历每个节点的描述。

#!/usr/bin/python2

import libxml2

doc = libxml2.parseFile("simple.xml")
context = doc.xpathNewContext()

context.xpathRegisterNs("db", "http://examplenamespace.com")
res = context.xpathEval("//db:food")

for node in res:
    # Query xmlNode here
    print "Got Food Node:"
    desc = node.xpathEval('db:description') # this is wrong?
    print desc

所以这实际上是一个命名空间的问题,如果我从XML文件中移除xlns属性,只用基本的XPath查询而不加db:前缀,那就能正常工作。顶层查询//db:food可以正常运行,但第二个查询在评估时失败了。

请问有人能帮我纠正一下我的命名空间/查询语法吗?

非常感谢!

1 个回答

5

我一般不太使用libxml2,更喜欢用lxml.etree。

我试了一下。你在节点上使用的xpathEval方法每次都会创建一个新的上下文,似乎没有你注册的命名空间。

你可以像这样重置你的上下文到不同的位置:

>>> import libxml2
>>> from urllib2 import urlopen
>>> data = urlopen('http://pastie.org/pastes/1333021/download').read()
>>>
>>> doc = libxml2.parseMemory(data,len(data))
>>>
>>> context = doc.xpathNewContext()
>>> context.xpathRegisterNs("db", "http://examplenamespace.com")
0
>>>
>>> for res in context.xpathEval("//db:food"):
...     context.setContextNode(res)
...     print "Got Food Node:"
...     desc = context.xpathEval('./db:description')[0]
...     print desc
...
Got Food Node:
<description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
Got Food Node:
<description>light Belgian waffles covered with strawberries and whipped cream</description>
Got Food Node:
<description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
Got Food Node:
<description>thick slices made from our homemade sourdough bread</description>
Got Food Node:
<description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>

撰写回答