XPath选择元素及其后续元素

3

我有一个大型数据表格,大致布局如下。如下所示,这是一个完整的样本而不是简化版。

<table class="grid resultRaceGrid" id="mainGrid">
<tr>
    <th width="10">&nbsp;</th>
    <th>&nbsp;</th>
    <th>&nbsp;</th>
    <th>HORSE/SP</th>
    <th>AGE</th>
    <th>WGT</th>
    <th>TRAINER/JOCKEY</th>
    <th>OR</th>
    <th>TS</th>
    <th>RPR</th>
    <th width="10">&nbsp;</th>
</tr>
<tr>
    <td colspan="11" class="separator">&nbsp;</td>
</tr>
<tr>
    <td rowspan="2" class="last"><a href="/horses/result_home.sd?race_id=443557&amp;r_date=2007-11-21&amp;popup=yes" class="bull"><b>&laquo;</b></a></td>
    <td rowspan="2" class="nowrap noPad"><h3>1 </h3></td>
    <td rowspan="2" class="dstDesc"></td>
    <td class="nowrap"><span class="black"><a href="#" id="noteIcon_673823" class="pencil" onclick="return false;"><!-- --></a><b><a href="/horses/horse_home.sd?horse_id=673823" onclick="return popup(this, {width:695, height:800})" title="Full details about this HORSE">Andytown</a></b> (IRE) 6/4F <img src="http://ui.racingpost.com/ico/tipping-success.gif" class="shilda" title="Tipped by Topspeed" alt="" /></span></td>
    <td class="black">5</td>
    <td class="nowrap black"><span>11-1&nbsp;<span class="lightGray"></span></span></td>
    <td class="nowrap black"><a href="/horses/trainer_home.sd?trainer_id=13176" onclick="return popup(this, {width:695, height:800})" title="Full details about this TRAINER">N G Richards</a></td>
    <td rowspan="2" class="lightGray">&mdash;</td>
    <td rowspan="2" class="lightGray"><span class="red bold">*</span></td>
    <td rowspan="2" class="last"><span class="red bold">*</span></td>
    <td rowspan="2" class="last"><a href="/horses/result_home.sd?race_id=450083&amp;r_date=2008-03-08&amp;popup=yes" class="bull"><b>&raquo;</b></a></td>
</tr>
<tr>
    <td colspan="3"><span class="pedigrees">ch g <a href="/bloodstock/stallionbook/stallion_home.sd?horse_id=42337&amp;popup=1" onclick="return popup(this, {width:734, height:800})" title="Full details about this STALLION">Old Vic</a> - <a href="/bloodstock/dam_home.sd?horse_id=519458" onclick="return popup(this, {width:695, height:800})" title="Full details about this DAM ">Pitfire (IRE)</a> (<a href="/bloodstock/stallionbook/stallion_home.sd?horse_id=303796&amp;popup=1" onclick="return popup(this, {width:734, height:800})" title="Full details about this STALLION">Parliament</a>)</span></td>
    <td class="lightGray"><a href="/horses/jockey_home.sd?jockey_id=82320" onclick="return popup(this, {width:695, height:800})" title="Full details about this JOCKEY">Fearghal Davis</a><sup>5</sup></td>
</tr>
<tr class="rowComment hideComment">
    <td colspan="3">&nbsp;</td>
    <td colspan="7"><div class="commentText">   Went prominent 6th, challenged 2 out, soon ridden, narrow advantage last, forged clear towards finish (tchd 7-4)</div></td>
    <td>&nbsp;</td>
</tr>
<tr>
    <td colspan="11" class="separator">&nbsp;</td>
</tr>

我有以下XPath,可以正确匹配感兴趣的整行。
我的问题是:如何选择这个tr以及它后面的两个tr元素?
$xpath->query("//table[@id='mainGrid']//tr[descendant::a[contains(@href,'horse_home')]]"

你的示例中没有 <a> 元素,请提供一个可以应用 XPath 的样本。 - Gordon
1
@gordon。代码示例已更新。 - user137621
完全没有问题!另外,“我也想匹配以下两行。”这句话毫无意义。哪两行?什么两行?你遇到了什么问题?请澄清。 - Dimitre Novatchev
@dimitre,表格中的以下两行。tr. - user137621
1
好问题,+1。看看我的答案,目前为止这是唯一正确的解决方案 -- 当前被接受的方案并没有选择你想要的节点。 - Dimitre Novatchev
4个回答

3

用途:

//table[@id='mainGrid']
      //tr[descendant::a
              [contains(@href,'horse_home')]
          ]
 |
    //table[@id='mainGrid']
          //tr[descendant::a
                  [contains(@href,'horse_home')]
              ]
               /following-sibling::tr[not(position() > 2)]

这个XPath表达式细化了你之前的选择,指定它与最多两个tr后续兄弟元素的并集(在你之前选择的tr元素中)应该被选择。


1
非常好。我以为我可以不指定原始的tr匹配。这绝对是完美的,非常感谢。 - user137621
1
@esryl:它可能只是一个紧凑的表达式,不需要使用union,但不幸的是XPath没有“following-sibling-or-self ::”轴。 - Dimitre Novatchev
+1 很好的回答。关于 following-sibling-or-self:请查看我的答案。 - user357812

1

只是为了好玩,没有将两个绝对表达式联合起来:

//table[@id='mainGrid'] 
   //tr[(self::tr|preceding-sibling::tr[not(position() > 2)])
              [descendant::a 
                  [contains(@href,'horse_home')] 
              ]
       ] 

作为证明,假设这是一个减少输入样本:

<table id="mainGrid">
    <tr>1</tr>
    <tr>2</tr>
    <tr>3</tr>
    <tr>
        <a href="/horses/horse_home.sd"/>
    </tr>
    <tr>5</tr>
    <tr>6</tr>
    <tr>7</tr>
    <tr>
        <a href="/horses/horse_home.sd"/>
    </tr>
    <tr>8</tr>
    <tr>9</tr>
    <tr>10</tr>
</table>

这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
  <xsl:copy-of select="
//table[@id='mainGrid']
   //tr[(self::tr|preceding-sibling::tr[not(position() > 2)])
              [descendant::a
                  [contains(@href,'horse_home')]
              ]
       ]
"/>
</xsl:template>
</xsl:stylesheet>

输出:

<tr>
    <a href="/horses/horse_home.sd" />
</tr>
<tr>5</tr>
<tr>6</tr>
<tr>
    <a href="/horses/horse_home.sd" />
</tr>
<tr>8</tr>
<tr>9</tr>

@Alejandro:好答案,+1。但请注意您仍然有一个联合。此外,它必须是following-sibling::tr,而不是preceding-sibling::tr - Dimitre Novatchev
@Dimitre:这个选择恰好符合OP的要求:我或者我的两个前面的兄弟姐妹中有一个满足条件。 - user357812
@Alejandro:您的XPath表达式可能会选择三个“tr”元素,其中只有最后一个满足条件。但是OP希望第一个符合条件。 - Dimitre Novatchev
@Dimitre:好的,我并不是说这个表达式完全遵循问题的“语法”(?)意义,但它在语义上是等价的。你没有理解第二步骤//tr的含义。 - user357812
@Alejandro:你认为你提出的表达式会选择三个兄弟tr元素,其中只有最后一个满足条件,你同意吗? - Dimitre Novatchev
显示剩余3条评论

0

$xpath->query("//table[@id='mainGrid']//tr[descendant::a[contains(@href,'horse_home')] | //table[@id='mainGrid']//tr[descendant::a[contains(@href,'horse_home')]/following-sibling::tr[position() < 3]"] 是一种方式(我认为不太高效)。

使用 XPath 2.0(可能不受您的 PHP API 支持),您可以使用 $xpath->query("//table[@id='mainGrid']//tr[descendant::a[contains(@href,'horse_home')]/(., following-sibling::tr[position() < 3])


honnen,我已经更新了代码示例。你的代码可以很好地匹配以下行,但是没有返回匹配的行。 - user137621

0

那么你一定应该考虑使用XPath轴。 following-siblingprevious-sibling

你的表达式应该像这样:

$xpath->query("//table[@id='mainGrid']/tr[descendant::a[contains(@href,'horse_home')]/following-sibling::tr[2]")

我一直在尝试使用XPath轴,但无法使其返回自身和兄弟节点。 - user137621
1
@esryl:我在你的示例代码中看到你使用了//table//tr.. 请注意:避免使用//tr,因为你基本上是在说“在表格中出现任何地方的tr”。这不是一个好主意。 - Robin Maben
很好,轴的使用恰到好处。当我遍历匹配的行时,现在我使用following-sibling连接到原始节点进行另一个查询。这个方法真的很管用。你指导我的方法实际上给了我更多的控制权。另外感谢你提供的//提示。 - user137621

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接