我正在尝试使用XPath 1.0(或可能使用Regex)选择元素(a),这些元素遵循特定元素(b)的兄弟,但仅在另一个b元素之前。
<img><b>First</b><br>
<img> <a href="/first-href">First Href</a> - 19:30<br>
<img><b>Second</b><br>
<img> <a href="/second-href">Second Href</a> - 19:30<br>
<img> <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>
任何想法如何实现?谢谢!
答案 0 :(得分:5)
动态创建此XPath:
following-sibling::a[preceding-sibling::b[1][.='xxxx']]
其中'xxxx'被替换为当前<b>
的文本。
这假设实际的所有元素都是兄弟。如果不是,您可以尝试使用preceding
和following
轴,或者编写更具特色的文档结构的XPath。
在XSLT中你也可以使用:
following-sibling::a[
generate-id(preceding-sibling::b[1]) = generate-id(current())
]
答案 1 :(得分:1)
这是一个只有一个XPath表达式的解决方案。
使用两个节点集$ns1
和$ns2
的交叉的Kaysian公式:
$ns1[count(. | $ns2) = count($ns2)]
我们只需将$ns1
替换为跟随当前<a>
节点的<b>
兄弟节点的节点集,然后将$ns2
替换为<a>
兄弟节点的节点集在下一个<b>
节点之前。
以下是使用此的完整转换:
<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 />  
<img/>  
<a href="/first-href">First Href</a> - 19:30
<br />
<img/>
<b>Second</b>
<br />
<img/>  
<a href="/second-href">Second Href</a> - 19:30
<br />
<img/> 
<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>