XPath“跟随兄弟姐妹之前”

html-agility-pack xpath

我正在尝试使用XPath 1.0(或可能与Regex一起)选择元素(a),这些元素遵循特定元素(b)的兄弟,但仅在另一个b元素之前。

<img><b>First</b><br>&nbsp;&nbsp;
<img>&nbsp;&nbsp;<a href="/first-href">First Href</a> - 19:30<br>
<img><b>Second</b><br>&nbsp;&nbsp;
<img>&nbsp;&nbsp;<a href="/second-href">Second Href</a> - 19:30<br>
<img>&nbsp;&nbsp;<a href="/third-href">Third Href</a> - 19:30<br>

我试图使样本尽可能接近现实世界。所以在这种情况下,当我在元素

<b>First</b>

我需要选择

<a href="/first-href">First Href</a> 

当我在

<b>Second</b> 

我需要选择

<a href="/second-href">Second Href</a> 
<a href="/third-href">Third Href</a>

知道怎么做到这一点?谢谢!

一般承认的答案

动态创建此XPath:

following-sibling::a[preceding-sibling::b[1][.='xxxx']]

其中'xxxx'被替换为当前<b>的文本。

这假设所有元素实际上都是兄弟姐妹。如果不是,你可以尝试用上班precedingfollowing坐标轴,或者你写一个更具体的XPath更好酷似文档结构。

在XSLT中,您还可以使用:

following-sibling::a[
  generate-id(preceding-sibling::b[1]) = generate-id(current())
]

热门答案

这是一个只有一个XPath表达式的解决方案

使用Kaysian公式来交叉两个节点集$ns1$ns2

  $ns1[count(. | $ns2) = count($ns2)]

我们简单地将$ns1替换$ns1跟随当前<b>节点的<a>兄弟节点的节点集,并且我们将$ns2替换$ns2在下一个<b>节点之前的<a>兄弟节点的节点集。

这是一个使用它的完整转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
   <xsl:apply-templates select="*/b"/>
  </xsl:template>

  <xsl:template match="b">
    At: <xsl:value-of select="."/>

    <xsl:variable name="vNextB" select="following-sibling::b[1]"/>

    <xsl:variable name="vA-sAfterCurrentB" select="following-sibling::a"/>

    <xsl:variable name="vA-sBeforeNextB" select=
    "$vNextB/preceding-sibling::a
    |
     $vA-sAfterCurrentB[not($vNextB)]
    "/>

    <xsl:copy-of select=
     "$vA-sAfterCurrentB
              [count(.| $vA-sBeforeNextB)
              =
               count($vA-sBeforeNextB)
               ]
    "/>
  </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档时

<t>
    <img/>
    <b>First</b>
    <br />&#xA0;&#xA0;
    <img/>&#xA0;&#xA0;
    <a href="/first-href">First Href</a> - 19:30
    <br />
    <img/>
    <b>Second</b>
    <br />
    <img/>&#xA0;&#xA0;
    <a href="/second-href">Second Href</a> - 19:30
    <br />
    <img/>&#xA0;
    <a href="/third-href">Third Href</a> - 19:30
    <br />
</t>

产生了正确的结果

   At: First <a href="/first-href">First Href</a>
    At: Second <a href="/second-href">Second Href</a>
<a href="/third-href">Third Href</a>



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因