Основная проблема заключается в том, что вам необходимо учитывать NUMBER
в вашем ключе, в противном случае вы сгруппируете все совпадающие годы по всему документу
<xsl:key name="years" match="Period" use="concat(../../NUMBER, '|', @Year)"/>
Кроме того, для ваших первых xsl:for-each
Вы начинаете выражение выбора с /TEST/RESPONSE/HISTORY/Period
, что также проверит все периоды в документе, когда вам действительно нужно, чтобы оно было относительно текущего HISTORY
, например, так:
<xsl:for-each select="Period[generate-id(.) = generate-id(key('years', concat(../../NUMBER, '|', @Year))[1])]">
Попробуйтеthis XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="years" match="Period" use="concat(../../NUMBER, '|', @Year)"/>
<xsl:template match="node() | @*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="HISTORY">
<xsl:call-template name="identity" />
<GROUP-HISTORY>
<xsl:for-each select="Period[generate-id(.) = generate-id(key('years', concat(../../NUMBER, '|', @Year))[1])]">
<xsl:sort select="@Year" order="descending"/>
<xsl:variable name="currY" select="@Year"/>
<Year Value="{$currY}">
<xsl:for-each select="key('years', concat(../../NUMBER, '|', $currY))">
<Months Month="{@Month}" Value="{@Value}" />
</xsl:for-each>
</Year>
</xsl:for-each>
</GROUP-HISTORY>
</xsl:template>
</xsl:stylesheet>
Примечание:
- Вам не нужно указывать полный путь к соответствующему элементу в
xsl:key
(нет, если у вас нет других элементов сто же имя, но разные пути, которые вы не хотите сопоставлять). - Ваш шаблон, соответствующий
TEST
, не был необходим, так как шаблон удостоверения сделал бы то же самое. - Вы не делаетеНеобходимо использовать
xsl:element
, где имя элемента является статическим.Просто запишите тег элемента напрямую. - Вы можете использовать Шаблоны значений атрибутов , чтобы упростить создание атрибутов.