一种方法是通过不同的模板推送项目,在这些模板中使用键来标识组和组的条件,然后为每个组中的第一个项目组成组,并为每个组中的其他项目使用空模板;请注意,下面的方法利用了order强加的优先级
https://www.w3.org/TR/xslt-30/#conflict
因此,下面使用的模板顺序很重要,尽管您也可以使用
priority
把你的规则强加于
@id
基于分组,然后
@name
基于分组,然后对任何项目进行分组(即。
match="item"
)其他分组条件不包括:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="id" match="item[normalize-space(@id)]" use="@id"/>
<xsl:key name="name" match="item" use="@name"/>
<xsl:template match="item">
<group>
<xsl:copy-of select="."/>
</group>
</xsl:template>
<xsl:template match="item[key('name', @name)[2] and . is key('name', @name)[1]]">
<group>
<xsl:copy-of select="key('name', @name)"/>
</group>
</xsl:template>
<xsl:template match="item[key('name', @name)[2] and not(. is key('name', @name)[1])]"/>
<xsl:template match="item[key('id', @id)[2] and . is key('id', @id)[1]]">
<group>
<xsl:copy-of select="key('id', @id)"/>
</group>
</xsl:template>
<xsl:template match="item[key('id', @id)[2] and not(. is key('id', @id)[1])]"/>
</xsl:stylesheet>
在线
https://xsltfiddle.liberty-development.net/bdxtqt
xsl:mode
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
让它与XSLT2处理器一起工作。唯一要注意的是,如果存在多个匹配项,XSLT 2处理器可能会报告错误,而不是使用最后一个匹配模板,我不记得哪个XSLT 2处理器会这样做,但正如前面所说,显式使用优先级可以解决这个问题。
你发布的方法也应该有效:
<xsl:template match="items">
<xsl:copy>
<xsl:variable name="nonMatched" as="element()*">
<xsl:for-each-group select="item" group-by="@id">
<xsl:sequence
select="if (not(current-group()[2]))
then .
else ()"/>
</xsl:for-each-group>
</xsl:variable>
<xsl:for-each-group select="item except $nonMatched" group-by="@id">
<group>
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:for-each-group>
<xsl:for-each-group select="$nonMatched" group-by="@name">
<group>
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
https://xsltfiddle.liberty-development.net/3NzcBtv