xsltxslt-1.0xslt-grouping

Compare element values in a array and fetch the biggest value elements inside the Parent element


I am trying to create a XSLT in 1.0.PLease find below a sample xml. The requirement is to get the biggest value1 field from all 3 and display the tags inside them.

Request XML:

<?xml version="1.0" encoding="UTF-8"?>
<GetTestValues xmlns="http://www.test.com/GetTestValues">
  <TestSample>
    <Test>
      <value1>10000</value1>
      <value2>2016-01-28</value2>
      <value3>2017-12-10T01:36:12.403+00:00</value3>
      <value4>US</value4>
      <value5>true</value5>
    </Test>
    <Test>
      <value1>30000</value1>
      <value2>2019-01-28</value2>
      <value3>2019-01-28T18:04:13.763+00:00</value3>
      <value4>Canada</value4>
      <value5>false</value5>
    </Test>
    <Test>
      <value1>50000</value1>
      <value2>2019-01-28</value2>
      <value3>2019-01-28T18:04:13.763+00:00</value3>
      <value4>Canada</value4>
      <value5>false</value5>
    </Test>
  </TestSample>
</GetTestValues>

Expected Response after transformation:

Request XML:

<?xml version="1.0" encoding="UTF-8"?>
<GetTestValues xmlns="http://www.test.com/GetTestValues">
  <TestSample>
    <Test>
      <value1>50000</value1>
      <value2>2019-01-28</value2>
      <value3>2019-01-28T18:04:13.763+00:00</value3>
      <value4>Canada</value4>
      <value5>false</value5>
    </Test>
  </TestSample>
</GetTestValues>

I tried to put foreach and it is displaying everything. Not sure how to compare the get the great value.

<xsl:for-each select="/ns0:GetTestValues/ns0:TestSample/ns0:Test">
  <ns0:value1>
    <xsl:value-of select="ns0:value1"/>
  </ns0:value1>
  <ns0:value2>
    <xsl:value-of select="ns0:value2"/>
  </ns0:value2>
  <ns0:value3>
    <xsl:value-of select="ns0:value3"/>
  </ns0:value3>
  <ns0:value4>
    <xsl:value-of select="ns0:value4"/>
  </ns0:value4>
  <ns0:value5>
    <xsl:value-of select="ns0:value5"/>
  </ns0:value5>
</xsl:for-each>

Solution

  • In this stylesheet, I iterate over the set of Test elements, in descending order of their value1 child elements (so that the first Test element has the highest value1). Inside the for-each I check the current position of the iteration, and if it's 1 then I copy the current Test element; the other Test elements are simply ignored.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
        xmlns:test="http://www.test.com/GetTestValues">
    
        <xsl:output method="xml" indent="yes" />
    
        <!-- identity template -->
        <xsl:template match="@*|node()" name="identity">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>
    
        <!-- Select only the Test child whose value1 is greatest -->
        <xsl:template match="test:TestSample">
            <xsl:copy>
                <!-- iterate over the test child elements, in descending order of value1 -->
                <xsl:for-each select="test:Test">
                    <xsl:sort select="test:value1" order="descending"/>
                    <!-- copy the test element if it's the first (has the highest value1) -->
                    <xsl:if test="position()=1">
                        <xsl:copy-of select="."/>
                    </xsl:if>
                </xsl:for-each>
            </xsl:copy>
        </xsl:template>
    
    </xsl:stylesheet>