Как использовать XSL, чтобы получить первого ребенка после сортировки - PullRequest
0 голосов
/ 02 мая 2018

У меня есть XML с этим estruture:

<?xml version="1.0" encoding="utf-8" ?>
    <products>
      <product>
        <code>XXX</code>
        <name>XXXXXX</name>
        <variants>
          <variant>
            <code>XXXY</code>
            <stock>5</stock>
          </variant>
          <variant>
            <code>XXXZ</code>
            <stock>8</stock>
          </variant>
          <variant>
            <code>XXXW</code>
            <stock>7</stock>
          </variant>
        </variants>
      </product>
      <product>
        <code>ZZZ</code>
        <name>ZZZZZZ</name>
        <variants>
          <variant>
            <code>ZZZY</code>
            <stock>5</stock>
          </variant>
          <variant>
            <code>ZZZX</code>
            <stock>8</stock>
          </variant>
          <variant>
            <code>ZZZW</code>
            <stock>7</stock>
          </variant>
        </variants>
      </product>
    </products>

Мне нужно отсортировать по складу и получить первый «вариант». Вывод примерно такой:

<variant>
  <code>XXXZ</code>
  <stock>8</stock>
</variant>

<variant>
  <code>ZZZX</code>
  <stock>8</stock>
</variant>

Возможно ли это? Как я могу решить это?

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Код ниже должен сделать трюк:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <xsl:for-each select="products/product">   
    <xsl:for-each select="variants/variant">
      <xsl:sort order="descending" select="stock" data-type="number"/>
      <xsl:if test="position() = 1">
              <xsl:apply-templates select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>

<xsl:template match="variant">
    <xsl:apply-templates select="code"/>  
    <xsl:apply-templates select="stock"/>
</xsl:template>

</xsl:stylesheet>

Что мы здесь делаем:

  • Получение товара из списка товаров;
  • Для этого товара мы получаем и сортируем список вариантов;
  • В этом списке вариантов мы получаем первый элемент;
  • мы передаем этот первый вариант (select = ".") Вашему внешнему шаблону;
  • тогда вы можете использовать свой вариант в своем шаблоне по своему желанию;
0 голосов
/ 02 мая 2018

Вы можете использовать xsl:perform-sort для сортировки variant элементов, а затем вывести или выбрать первый в порядке убывания:

  <xsl:template match="variants">
      <xsl:variable name="sorted-variants" as="element(variant)*">
          <xsl:perform-sort select="variant">
              <xsl:sort select="xs:integer(stock)" order="descending"/>
          </xsl:perform-sort>
      </xsl:variable>
      <xsl:copy-of select="$sorted-variants[1]"/>
  </xsl:template>

https://xsltfiddle.liberty -development.net / 3NzcBsU

То же самое возможно при использовании apply-templates, если другие шаблоны (например, преобразование идентичности) копируют обработанные variant s:

  <xsl:template match="variants">
      <xsl:variable name="sorted-variants" as="element(variant)*">
          <xsl:apply-templates select="variant">
              <xsl:sort select="xs:integer(stock)" order="descending"/>
          </xsl:apply-templates>
      </xsl:variable>
      <xsl:copy-of select="$sorted-variants[1]"/>
  </xsl:template>

https://xsltfiddle.liberty -development.net / 3NzcBsU / 1

С помощью for-each вы можете напрямую вкладывать if test="position() = 1":

  <xsl:template match="variants">
      <xsl:for-each select="variant">
          <xsl:sort select="xs:integer(stock)" order="descending"/>
          <xsl:if test="position() = 1">
              <xsl:copy-of select="."/>
          </xsl:if>
      </xsl:for-each>
  </xsl:template>

https://xsltfiddle.liberty -development.net / 3NzcBsU / 2

...