我有以下XML输入
<a href="h1" />
<a href="h2" />
<a href="h3" />
<b id="h1">E1</b>
<b id="h2">E1</b>
<b id="h3">E2</b>
<b id="h4">E3</b>
<b id="h5">E3</b>
<b id="h6">E4</b>
<b id="h7">E5</b>
有没有办法使用XSLT2 / Xpath2来获取h1和h3引用不同的值E1和E2并忽略h2,因为它引用相同的值E1?
感谢。
答案 0 :(得分:1)
使用,假设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
答案 1 :(得分:1)
你可以尝试这个XPath:
/*/b[@id = /*/a/@href and not(preceding::b = .)]
答案 2 :(得分:1)
我无法看到<a>
元素扮演什么角色 - 在我看来问题只涉及b
元素 - 我是否完全误解了它?
根据您的输入,将给定节点的父节点作为上下文项,
<xsl:for-each-group select="b" group-by=".">
<xsl:value-of select="current-group()[1]/@id"/>
</xsl:for-each-group>
将返回h1 h2