我有一个看起来像这样的文件:
<template>
<otherstuff>
<group name="foo">
...stuff...
</group>
</template>
<template>
<otherstuff>
<group name="bar">
...different stuff...
</group>
</template>
<template>
<otherstuff>
<group name="foo">
...same stuff as first foo group...
</group>
</template>
我想要做的是为给定组名的每个实例调用一个特定的模板 - 所以一次用于“foo”,一次用于“bar”。由于它们是相同的,我不关心它们中的哪一个用于调用此模板。
根据Select unique nodes based on a combination of two attribute values的答案,我制作了以下代码:
<xsl:key name="groupsByName" match="//group" use="@name"/>
<xsl:template match="/">
<xsl:for-each select="//group[count(.|key('groupsByName',@name)[1])!=1]">
<xsl:call-template name="template-or-group"/>
</xsl:for-each>
</xsl:template>
然而,结果是不调用模板。我也怀疑,因为我的案例比我的代码基于的问题更简单,所以可能有一种更简单的方法。但是,我的XSLT不够强大,无法确定它可能是什么。
答案 0 :(得分:1)
我建议用以下代码替换你的模板:
<xsl:template match="group[generate-id(.) = generate-id(key('groupsByName',@name)[1])]">
....
</xsl:template>
或者只是将xpath表达式更改为//group[generate-id(.) = generate-id(key('groupsByName',@name)[1])]
。
count(.|some-node-set)
通常用于检查某个节点是否属于该集合。在这里,您需要将当前节点与每个组的第一个唯一节点进行比较。此外,改进Xpath表达式并仅匹配具有@name
属性的组元素可能也很有用。说完所有这些后,我们得到://group[@name][generate-id(.) = generate-id(key('groupsByName', @name)[1])]
。
答案 1 :(得分:1)
只需替换:
//group[count(.|key('groupsByName',@name)[1])!=1]
<强>与强>:
//group[count(.|key('groupsByName',@name)[1])=1]
这是一个完整的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="groupsByName" match="//group"
use="@name"/>
<xsl:template match="/">
<xsl:for-each select=
"//group[count(.|key('groupsByName',@name)[1])=1]">
<xsl:call-template name="template-or-group"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="template-or-group">
<xsl:value-of select="@name"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
将此转换应用于提供的XML文档(已修复为格式良好):
<t>
<template>
<otherstuff/>
<group name="foo"> ...stuff... </group>
</template>
<template>
<otherstuff/>
<group name="bar"> ...different stuff... </group>
</template>
<template>
<otherstuff/>
<group name="foo"> ...same stuff as first foo group... </group>
</template>
</t>
产生了想要的正确结果:
foo
bar