我有以下 HTML 示例:
<!-- lots of html -->
<h2>Foo bar</h2>
<p>lorem</p>
<p>ipsum</p>
<p>etc</p>
<h2>Bar baz</h2>
<p>dum dum dum</p>
<p>poopfiddles</p>
<!-- lots more html ... -->
我希望提取“Foo bar”标题后的所有段落,直到到达“Bar baz”标题(“Bar baz”标题的文本未知,所以很遗憾我无法使用答案由 bougyman 提供)。现在我当然可以使用 //h2[text()='Foo bar']/following::p
之类的东西,但这当然会抓取此后的所有段落 header 。因此,我可以选择遍历节点集并将段落插入数组,直到文本与下一个 header 的文本相匹配,但老实说,这远不如在 XPath 中完成这件事那么酷。
有没有办法做到这一点我想念的?
最佳答案
使用:
(//h2[. = 'Foo bar'])[1]/following-sibling::p
[1 = count(preceding-sibling::h2[1] | (//h2[. = 'Foo bar'])[1])]
如果保证每个 h2
都有不同的值,这可以简化为:
//h2[. = 'Foo bar']/following-sibling::p
[1 = count(preceding-sibling::h2[1] | ../h2[. = 'Foo bar'])]
这意味着:选择 h2
(文档中的第一个或唯一一个)的兄弟元素之后的所有 p
元素,其字符串值为是 'Foo bar'
并且所有这些 p
元素的第一个前面的兄弟 h2
正是 h2(第一个或唯一一个在文档中)其字符串值为
'Foo bar'`。
这里我们使用一种判断两个节点是否相同的方法:
count($n1 | $n2) = 1
当节点 $n1
和 $n2
是同一节点时,为 true()
。
这个表达式可以泛化:
$x/following-sibling::p
[1 = count(preceding-sibling::node()[name() = name($x)][1] | $x)]
选择 $x 指定的任何节点的所有“紧随其后的兄弟节点”。
关于ruby - XPath 轴,获取所有后续节点直到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4767430/