xpath后代和后代或自我的工作完全不同

时间:2015-07-29 08:51:28

标签: python-2.7 xpath lxml descendant descendant-or-self

我尝试在div的后代中找到具有指定id的所有秒tds,即22和222.我想到的第一个解决方案是:

//div[@id='indicator']//td[2]

但它只选择第一个表格单元格,即22个而不是22和222。 然后我用/ descendant-or-self :: node()/替换//得到了相同的结果(显然)。但是,当我删除' - 或 - 自我' xpath表达式开始按预期工作

 test1 = test_tree.xpath(u"//div[@id='indicator']/descendant-or-self::node()/td[2]")
 print len(test1) #prints 1 (first one: 22)

 test1 = test_tree.xpath(u"//div[@id='indicator']/descendant::node()/td[2]")
 print len(test1) #prints 2 (22 and 222)

这是测试HTML

<html>
    <body>
        <div id='indicator'>
            <table>
               <tbody>
                    <tr>
                        <th>1</th>
                        <th>2</th>
                        <th>3</th>
                    </tr>
                    <tr>
                        <td>11</td>
                        <td>22</td>
                        <td>33</td>
                    </tr>
                    <tr>
                        <td>111</td>
                        <td>222</td>
                        <td>333</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </body>
</html>

我想知道为什么两个表达式都不相同,因为所有tds都是div元素的后代,无论是否包含div。

3 个答案:

答案 0 :(得分:1)

我认为您在XPath处理器中发现了一个错误。

答案 1 :(得分:0)

我开发了一个网页,其中包含您在问题中提供的HTML。

使用此xpath时:

.//div[@id='indicator']//tr/td[2]

它按预期工作,结果是:

[u'<td>22</td>', u'<td>222</td>']

然而,according to your comment,您问.//td[2]何时无效。原因是.//td为您提供了DOM中所有td(s)的列表。添加[2]等索引将导致列表中的第二个td

总结: 这些是分别应用.//td.//td[2]的结果:

enter image description here

如果你想在这些tds中加入文字,你应该添加/text()如下:

enter image description here

更新

OP说:

So why then //div[@id='indicator']/descendant::node()/td[2] produces ['22', '222']? According to your comment: "Adding an index such as [2] will result in the second td in that list" it should populate only ['22'].

我将尝试解释这里发生了什么:

  1. descendant:node()不等于//
  2. 等于//是:descendant-or-self::node()
  3. W3C specification
  4. 解释了这一点

    enter image description here

    我希望此代码可以帮助您: enter image description here

答案 2 :(得分:0)

我想我已经找到了这个问题的原因:

http://www.w3.org/TR/xpath20/#id-errors-and-opt

&#34;在某些情况下,处理器可以在不访问正式表达式语义隐含的所有数据的情况下确定表达式的结果。例如,过滤器表达式的正式描述建议应通过检查序列$s[1]中的所有项目并选择满足谓词$s的所有项目来评估position()=1。在实践中,许多实现将认识到他们可以通过获取序列中的第一个项目然后退出来评估此表达式。&#34;

所以没有补救措施。它的xpath处理器实现依赖,但我仍然不明白为什么//div[@id='indicator']/descendant-or-self::node()/td[2]//div[@id='indicator']/descendant::node()/td[2]会产生不同的结果。