找到所有前面的兄弟节点,直到找到具有特定子节点属性的节点

时间:2012-11-02 16:29:05

标签: xpath

我希望在特定行标识符(行列上的属性)之后获取所有表行,直到找到该特定行标识符。

这是我要解析的HTML:

  <tr>
    <td colspan="4">
      <h3>Header 1</h3>
    </td>
  </tr>
  <tr>
    <td>Item desc - Header 1</td>
    <td>more info</td>
    <td>30</td>
    <td>500</td>
  </tr>
  <tr>
    <td colspan="4">
      <h3>Header 2</h3>
    </td>
  </tr>
  <tr>
    <td>Item desc - header 2</td>
    <td>other</td>
    <td>4</td>
    <td>49</td>
  </tr>
  <tr>
    <td>Item 2 desc - header 2</td>
    <td>other 2</td>
    <td>65</td>
    <td>87</td>
  </tr>

我希望能够抓住标题1下的项目并在找到标题2时停止;然后是标题2下的项目,当它找到标题3时停止;等

这可能在xpath下吗?在找到具有特定属性(colspan =“4”)的子节点之前,我无法找到TR节点。

2 个答案:

答案 0 :(得分:1)

这在XPath 1.0下是不可能的。你不得不修改标题tr,因为你试图找到它的所有下面的兄弟,其第一个前面的标题tr 是原始的。没有引用原始标题,一切皆有可能。但是你可能会使用某种语言来记住价值。

例如,在xsh中:

for my $x in //tr[td/@colspan="4"] {
    echo ($x/td/h3) ;
    for $x/following-sibling::tr[count(td)=4
                                 and preceding-sibling::tr[count(td)=1][1]=$x]
        echo "  " (td) ;
}

输出:

Header 1
   Item desc - Header 1 more info 30 500
Header 2
   Item desc - header 2 other 4 49
   Item 2 desc - header 2 other 2 65 87

答案 1 :(得分:1)

这可能会给你你想要的东西,而不是最正统的方式:

//*/tr/td[not(child::h3)]/ancestor::tr

这将为<td>中的所有<tr>个节点提供不是标头块的节点。

您可以使用以下命令指定标题:

//*/tr/td[not(child::h3/text()='Header 1')]/ancestor::tr

或者更一般:

//*/tr/td[not(child::h3[contains(text(),'Header')])]/ancestor::tr