3

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

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

但它只选择第一个表格单元格,即 22 但不是 22 和 222。然后我用 /descendant-or-self::node()/ 替换了 // 并得到了相同的结果(显然)。但是当我删除“-or-self”时,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>

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

4

3 回答 3

1

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

于 2015-07-29T12:23:11.457 回答
0

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

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

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

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

于 2015-07-30T09:27:53.390 回答
0

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

当您使用此 xpath 时:

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

它按预期工作,结果是:

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

但是,根据您的评论,您在问什么时候.//td[2]不起作用。原因是.//td为您提供了 DOM 中所有 td(s)的列表。添加一个索引,例如[2]将导致该列表中的第二个 td

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

在此处输入图像描述

如果要获取这些 td 中的文本,则应添加/text()以下内容:

在此处输入图像描述

更新:

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 规范中有解释:

在此处输入图像描述

我希望这段代码可以帮助你: 在此处输入图像描述

于 2015-07-29T18:50:52.213 回答