使用, 假设a
和b
是顶部元素的子元素:
for $href in /*/a/@href,
$b in /*/b[@id = $href and not(. = preceding-sibling::b)]
return
string($href)
基于 XSLT-2 的验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:sequence select=
"for $href in /*/a/@href,
$b in /*/b[@id = $href and not(. = preceding-sibling::b)]
return
string($href)
"/>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<html>
<a href="h1" />
<a href="h2" />
<a href="h3" />
<b id="h1">E1</b>
<b id="h2">E1</b>
<b id="h3">E2</b>
</html>
计算 XPath 表达式,并将计算结果复制到输出:
h1 h3
更新:
正如 Michael Kay 所指出的,上述解决方案是 O(N^2) 并且在有很多b
兄弟姐妹的情况下可能会很慢。
这是一个至少是线性(或更快)的 XSLT 2.0 解决方案:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kReferrer" match="b" use="@id"/>
<xsl:template match="/*">
<xsl:for-each-group select="key('kReferrer', a/@href)" group-by=".">
<xsl:sequence select="string(@id)"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
同样,当此转换应用于同一个 XML 文档(如上)时,会产生所需的正确结果:
h1 h3