.xpath中的lxml错误?

时间:2012-03-19 02:44:13

标签: python xpath lxml

在浏览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 ...>]

3 个答案:

答案 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设计。否则,在处理列表之前,代码总是必须测试单值或无值。