如何从python中的xmlNode获取xpathContext

3 投票
2 回答
1761 浏览
提问于 2025-04-15 12:41

我非常喜欢在 .net 中使用 xpath,也喜欢在 python 中使用 sax,但这是我第一次在 python 中使用 xpath。

我有一个小脚本,它使用 xpath 从一个文档中选择一些节点,然后遍历这些节点,理想情况下再用 xpath 从中获取相关数据。不过我在最后一步遇到了问题,一旦我得到了 xmlNode,就无法从中获取上下文。

import libxml2
import urllib

doc = libxml2.parseDoc(
        urllib.urlopen('http://somemagicwebservice.com/').read())
ctxt = doc.xpathNewContext()
listitems = ctxt.xpathEval('//List/ListItem')
for item in listitems:
    itemctxt = item.xpathNewContext()
    title = itemctxt.xpathEval('//ItemAttributes/Title')
    asin = itemctxt.xpathEval('//Item/ASIN')
    itemctxc.xpathFreeContext()
ctxt.xpathFreeContext()
doc.freeDoc()

不过,itemctxt = item.xpathNewContext() 这一部分出错了,错误信息是

itemctxt = item.xpathNewContext()
AttributeError: xmlNode instance has no attribute 'xpathNewContext'

有没有什么办法可以在 xmlNode 上使用 xpath?我找不到好的在线资料。谢谢!

2 个回答

2

在这个链接中,有人建议在新创建的上下文上调用 setContextNode(..)

itemctxt = doc.xpathNewContext()

for item in listitems:
    itemctxt.setContextNode(item)
    title = itemctxt.xpathEval('.//ItemAttributes/Title')

    ...

itemctxt.xpathFreeContext()

我现在使用的python libxml版本是2.9.1,发现其实可以直接调用:

item.xpathEval('.//ItemAttributes/Title')

需要注意的是,在写xpath表达式时,开头要加一个点,也就是用 .//(而不是 //),否则你得到的搜索结果会是相对于文档根节点的。

2

我觉得在一个元素上使用XPathContext没有什么意义。你可以试着创建一个新的XPathContext,然后把它的节点设置为当前的元素。

不过,我并没有直接使用libxml2,所以这有点像是在猜测。我通常使用的是lxml,它是基于libxml2和libxslt的一个更简单的API。使用起来要容易得多,而且确实可以在元素上使用xpath()。当然,如果你已经有很多代码在用libxml2,可能不想切换,但在这种情况下,你可以看看lxml的源代码,看看它是怎么实现的。

http://codespeak.net/svn/lxml/trunk/src/lxml/xpath.pxi

http://codespeak.net/svn/lxml/trunk/src/lxml/_elementpath.py

这些链接看起来是个不错的起点。

撰写回答