XSLT max каждой группы - PullRequest
       2

XSLT max каждой группы

0 голосов
/ 06 марта 2019

У меня есть данные в формате XML, в котором приводится список продуктов и их цены.Ищите XSLT, который поможет мне получить максимальную цену для каждого продукта.Пробовал, может, пока что не повезло.Пожалуйста, помогите.

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <Product>
    <name>P1</name>
    <price>10</price>
  </Product>
  <Product>
    <name>P1</name>
    <price>20</price>
  </Product>
  <Product>
    <name>P2</name>
    <price>5</price>
  </Product>
  <Product>
    <name>P3</name>
    <price>8</price>
  </Product>
  <Product>
    <name>P1</name>
    <price>30</price>
  </Product>
</root>

Ожидаемый результат

Product	Price
P1	30
P2	5
P3	8

1 Ответ

0 голосов
/ 06 марта 2019

Используя 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&#x0A;</xsl:text>
    <xsl:for-each-group select="Product" group-by="name">
      <xsl:value-of select="concat(current-grouping-key(),
        '      ', max(current-group()/price), '&#x0A;')"/>
    </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&#x0A;</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="'&#x0A;'"/>
    </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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...