在浏览python的lxml教程中的xpath之后,我发现很难理解2个看起来像我的bug的行为。首先,lxml似乎返回一个列表,即使我的xpath表达式只清楚地选择了一个元素,其次.xpath似乎返回元素的父级而不是由直接的xpath搜索表达式选择的元素本身。
我对XPath的理解是错还是lxml确实有错误?
复制我正在谈论的行为的脚本:
from lxml.html.soupparser import fromstring
doc = fromstring("""
<html>
<head></head>
<body>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</body>
</html>
""")
print doc.xpath("//html")
#[<Element html at 1f385e0>]
#(This makes sense - return a list of all possible matches for html)
print doc.xpath("//html[1]")
#[<Element html at 1f385e0>]
#(This doesn't make sense - why do I get a list when there
#can clearly only be 1 element returned?)
print doc.xpath("body")
#[<Element body at 1d003e8>]
#(This doesn't make sense - according to
#http://www.w3schools.com/xpath/xpath_syntax.asp if I use a tag name
#without any leading / I should get the *child* nodes of the named
#node, which in this case would mean I get a list of
#p tags [<Element p at ...>, <Element p at ...>]
答案 0 :(得分:3)
这是因为doc
的上下文节点是'html'
节点。当您使用doc.xpath('body')
时,请选择'body'
的子元素'html'
。这符合XPath 1.0 standard
答案 1 :(得分:0)
所有p标签应为doc.findall(".//p")
根据指南,表达式nodename
选择命名节点 的所有子节点。
因此,要仅使用nodename(不带尾随/),必须选择一个命名节点(选择父节点作为命名节点,使用点)。
答案 2 :(得分:0)
实际上var testtest = encodeImageUri(imageData);
可以返回多个节点,其中包含与您的示例不同的输入文档。那个路径选择匹配// html的第一个兄弟。如果有匹配的非兄弟元素,它将选择每个元素的第一个兄弟
XPath:doc.xpath("//html[1]")
强制执行不同的评估顺序。它选择文档中的所有匹配元素,然后选择第一个。
但是,无论如何,总是返回列表是一个更好的API设计。否则,在处理列表之前,代码总是必须测试单值或无值。