Используя XSLT 2.0 , это довольно просто:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:text>Product Price
</xsl:text>
<xsl:for-each-group select="Product" group-by="name">
<xsl:value-of select="concat(current-grouping-key(),
' ', max(current-group()/price), '
')"/>
</xsl:for-each-group>
</xsl:template>
</xsl:transform>
Как видите, необходим цикл for-each-group
,
выбрав Product
элементов и сгруппировав их по значению
ребенка name
элемент.
Внутри цикла, функция current-grouping-key()
предоставляет ключ текущей группы
(значение элемента name
) и max(current-group()/price)
вычисляет
максимальная цена.
Рабочий пример см. http://xsltransform.net/pNEhB3c
Редактировать после вашего комментария относительно версии XSLT
Ваша задача может быть выполнена также в XSLT 1.0 , используя так называемые
Muenchian Grouping (для более подробного описания ищите в сети).
Первое, что нужно сделать, это создать ключ , группирующий элементы
группироваться ( Product ) по некоторому ключу группировки (в нашем случае
имя ):
<xsl:key name="prods" match="Product" use="name"/>
Тогда фактическая группировка может быть выполнена в цикле for-each
,
используя предикат с идиомой мюнхенской группировки внутри:
[generate-id()=generate-id(key('prods', name)[1])]
Дополнительной трудностью является то, что XSLT 1.0 имеет так много
ограниченные возможности, что он даже не имеет функции max
.
Чтобы обойти это ограничение, мы должны написать шаблон
(Я назвал это максимум ), который принимает последовательность элементов,
сортирует их (по убыванию) и выводит первое (максимальное) значение.
Этот шаблон предназначен для price
дочерних элементов всех
Product
элементов из текущей группы.
Таким образом, весь скрипт может выглядеть следующим образом:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:key name="prods" match="Product" use="name"/>
<xsl:template match="root">
<xsl:text>Product Price
</xsl:text>
<xsl:for-each select="Product[generate-id()=
generate-id(key('prods', name)[1])]">
<xsl:value-of select="concat(name, ' ')"/>
<xsl:call-template name="maximum">
<xsl:with-param name="src" select="key('prods', name)/price"/>
</xsl:call-template>
<xsl:value-of select="'
'"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="maximum">
<xsl:param name="src"/>
<xsl:for-each select="$src">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
Рабочий пример см. http://xsltransform.net/pNEhB3c/1