Вот существенно более читаемый вариант решения @ Lachlan-Roche :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kRowByDate" match="row"
use="concat(column[name='Year']/value,
'+',
column[name='Month']/value)"/>
<xsl:template match="/*">
<Response>
<xsl:apply-templates/>
</Response>
</xsl:template>
<xsl:template match=
"row[generate-id()
=
generate-id(key('kRowByDate',
concat(column[name='Year']/value,
'+',
column[name='Month']/value)
)[1]
)
]
">
<xsl:variable name="vMonth" select="column[name='Month']/value"/>
<xsl:variable name="vYear" select="column[name='Year']/value"/>
<PeriodInfo>
<Month><xsl:value-of select="$vMonth"/></Month>
<Year><xsl:value-of select="$vYear"/></Year>
<xsl:apply-templates mode="data"
select="key('kRowByDate', concat($vYear,'+',$vMonth))"/>
</PeriodInfo>
</xsl:template>
<xsl:template match="row"/>
<xsl:template match="row" mode="data">
<EmployeeDetails>
<Name><xsl:value-of select="column[name='EmpName']/value"/></Name>
<Age><xsl:value-of select="column[name='Age']/value"/></Age>
</EmployeeDetails>
</xsl:template>
</xsl:stylesheet>
когда это преобразование применяется к предоставленному документу XML :
<resultset>
<row>
<column>
<name>Month</name>
<value>2</value>
</column>
<column>
<name>Year</name>
<value>2010</value>
</column>
<column>
<name>EmpName</name>
<value>Anu</value>
</column>
<column>
<name>Age</name>
<value>24</value>
</column>
</row>
<row>
<column>
<name>Month</name>
<value>2</value>
</column>
<column>
<name>Year</name>
<value>2010</value>
</column>
<column>
<name>EmpName</name>
<value>Nancy</value>
</column>
<column>
<name>Age</name>
<value>26</value>
</column>
</row>
<row>
<column>
<name>Month</name>
<value>3</value>
</column>
<column>
<name>Year</name>
<value>2010</value>
</column>
<column>
<name>EmpName</name>
<value>Ned</value>
</column>
<column>
<name>Age</name>
<value>25</value>
</column>
</row>
</resultset>
желаемый, правильный результат получается :
<Response>
<PeriodInfo>
<Month>2</Month>
<Year>2010</Year>
<EmployeeDetails>
<Name>Anu</Name>
<Age>24</Age>
</EmployeeDetails>
<EmployeeDetails>
<Name>Nancy</Name>
<Age>26</Age>
</EmployeeDetails>
</PeriodInfo>
<PeriodInfo>
<Month>3</Month>
<Year>2010</Year>
<EmployeeDetails>
<Name>Ned</Name>
<Age>25</Age>
</EmployeeDetails>
</PeriodInfo>
</Response>