选择所有节点,直到特定的给定节点/标记

时间:2015-10-17 15:03:17

标签: xpath

给出以下标记:

<div id="about">
    <dl>
        <dt>Date</dt>
        <dd>1872</dd>
        <dt>Names</dt>
        <dd>A</dd>
        <dd>B</dd>
        <dd>C</dd>
        <dt>Status</dt>
        <dd>on</dd>
        <dt>Another Field</dt>
        <dd>X</dd>
        <dd>Y</dd>
    </dl>
</div>

我尝试提取<dd>之后的所有<dt>Names</dt>个节点,但只是在另一个<dt>开始之前。在这种情况下,我在以下节点之后:

<dd>A</dd>
<dd>B</dd>
<dd>C</dd>

我正在尝试以下XPath代码,但它没有按预期工作。

xpath("//div[@id='about']/dl/dt[contains(text(),'Names')]/following-sibling::dd[not(following-sibling::dt)]/text()")

有关如何修复它的任何想法?

非常感谢。

2 个答案:

答案 0 :(得分:3)

更新:更简单的解决方案

在您的情况下有一个先决条件,即锚项始终是具有特定属性的第一个前一个兄弟。因此,这是编写以下复杂表达式的一种更简单的方法:

/div/dl/dd[preceding-sibling::dt[1][. = 'Names']]

换句话说:

  • 选择任何dd
  • 具有第一个前一个兄弟dt(前一个兄弟轴向后计数)
  • 本身的值为&#34;名称&#34;

从oXygen的以下屏幕截图中可以看出,它选择了您想要选择的节点(如果您更改&#34;名称&#34;到&#34;状态&#34;或&#34;另一个字段&#34;,它也会在下一个dt之前仅选择以下内容。

screenshot from oXygen of selected nodes

原始复杂解决方案(留待参考)

这在XPath 2.0中要容易得多,但我们假设您只能使用XPath 1.0。诀窍是计算你的锚元素中的前一个兄弟姐妹的数量(其中包含&#34;姓名&#34;在其中),并忽略任何错误计数(即,当我们越过<dt>Status</dt>时,先前兄弟姐妹的数量增加了。)

对于XPath 1.0,删除(::)之间的注释(在XPath中,空白是无关紧要的,为了便于阅读,可以使其成为多行XPath,但在1.0中,注释是不可能的)< / p>

/div/dl/dd

    (: any dd having a dt before it with "Names" :)
    [preceding-sibling::dt[. = 'Names']]

    (: count the preceding siblings up to dt with "Names", add one to include 'self' :)
    [count(preceding-sibling::dt[. = 'Names']/preceding-sibling::dt) + 1 
    = 

    (: compare with count of all preceding siblings :)
    count(preceding-sibling::dt)]

作为一个单行:

/div/dl/dd[preceding-sibling::dt[. = 'Names']][count(preceding-sibling::dt[. = 'Names']/preceding-sibling::dt) + 1 = count(preceding-sibling::dt)]

答案 1 :(得分:0)

这个怎么样:

//dd[preceding-sibling::dt[contains(., 'Names')]][following-sibling::dt]