Вот гораздо более простое решение (полностью "стиль нажатия", нет <xsl:for-each>
, нет вложенности, нет <xsl:variable>
, нет current()
, нет //
, нет осей):
<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>
когда это преобразование применяется к предоставленному XML-документу :
<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>
желаемый, правильный результат получается :
<group type="TypeA">
<value v="value1"/>
<value v="value3"/>
</group>
<group type="TypeB">
<value v="value2"/>
</group>
Объяснение : мюнхенская группировка из /*/*
с использованием в качестве ключа строковых значений их a
потомков.
II.Решение XSLT 2.0 :
<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>
Когда это преобразование выполняется для того же XML-документа (см. Выше), получается тот же правильный результат :
<group type="TypeA">
<b>value1</b>
<b>value3</b>
</group>
<group type="TypeB">
<b>value2</b>
</group>
Пояснение :
<xsl:for-each-group>
current-group()
current-grouping-key()