Search code examples
xsltxslt-2.0

How to use XSL to get first child after sort


I have an XML with that 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>

I need to sort by stock and get the first "variant". The output is something like that:

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

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

Is it possible? How can I solve this?


Solution

  • The code bellow should do the trick:

    <?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>
    

    What we're doing here:

    • Getting a product from your list of products;
    • For this product, we get and sort the list of variants;
    • In this list of variants, we get the first element;
    • we pass this first variant (select=".") to your external template;
    • then, you can use your variant in your template as you wish;