Here is a much simpler solution (completely "push style", no <xsl:for-each>
, no nesting, no <xsl:variable>
, no current()
, , no //
, no axes):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kGoodsByType" match="/*/*" use="a"/>
<xsl:template match=
"/*/*[generate-id()
=
generate-id(key('kGoodsByType', a)[1])
]
">
<group type="{a}">
<xsl:apply-templates select="key('kGoodsByType', a)/b"/>
</group>
</xsl:template>
<xsl:template match="b">
<value v="{.}"/>
</xsl:template>
<xsl:template match="*/* | text()" priority="-1"/>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<Test>
<grapes>
<a>TypeA</a>
<b>value1</b>
</grapes>
<oranges>
<a>TypeB</a>
<b>value2</b>
</oranges>
<apples>
<a>TypeA</a>
<b>value3</b>
</apples>
</Test>
the wanted, correct result is produced:
<group type="TypeA">
<value v="value1"/>
<value v="value3"/>
</group>
<group type="TypeB">
<value v="value2"/>
</group>
Explanation: Muenchian grouping of /*/*
using as key the string values of their a
children.
II. XSLT 2.0 solution:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:for-each-group select="*/a" group-by=".">
<group type="{current-grouping-key()}">
<xsl:sequence select="current-group()/../b"/>
</group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
When this transformation is performed on the same XML document (above), the same correct result is produced:
<group type="TypeA">
<b>value1</b>
<b>value3</b>
</group>
<group type="TypeB">
<b>value2</b>
</group>
Explanation:
<xsl:for-each-group>
current-group()
current-grouping-key()