How to get maximum value under same node in xslt

30,990

Solution 1

Given XSLT 2.0 it should suffice to use

<xsl:variable name="max" select="max(/Report/Items/Item/*[starts-with(local-name(), 'Hour')]/xs:integer(.)"/>

(where the stylesheet would need to declare xmlns:xs="http://www.w3.org/2001/XMLSchema").

And with XSLT 1.0 I would simply sort and take the maximum value as in

<xsl:variable name="max">
  <xsl:for-each select="/Report/Items/Item/*[starts-with(local-name(), 'Hour')]">
    <xsl:sort select="." data-type="number" order="descending"/>
    <xsl:if test="position() = 1"><xsl:value-of select="."/></xsl:if>
  </xsl:for-each>
</xsl:variable>

Solution 2

In XSLT 2.0, with Item as the context node, use

max(*[starts-with(local-name(), 'Hour')])

Solution 3

This XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

    <!-- Putting the maximum hour from the list into a variable. -->
    <xsl:variable name="max-hour">
      <xsl:call-template name="find-max">
        <!-- Select the list of hour elements you want to look at. -->
        <xsl:with-param name="hours" select="//*[contains(local-name(), 'Hour')]"/>
      </xsl:call-template>
    </xsl:variable>

  <xsl:template match="*">   
    <!-- Displaying the result you are after. -->
    <result>
      <xsl:value-of select="$max-hour"/>
    </result>
  </xsl:template>

  <!-- This template works recursively on the list of hours. -->
  <xsl:template name="find-max">
    <xsl:param name="hours"/>

    <!-- The value of the first hour in this list. -->
    <xsl:variable name="this-hour">
      <xsl:value-of select="$hours[position() = 1]"/>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="$hours">
        <!-- The maximum value of the remaining hours in this list. -->
        <xsl:variable name="other-hours">
          <xsl:call-template name="find-max">
            <xsl:with-param name="hours" select="$hours[position() != 1]"/>
          </xsl:call-template>
        </xsl:variable>

        <!-- Return the maximum of this hour and the remaining hours. -->
        <xsl:choose>
          <xsl:when test="$other-hours &gt; $this-hour">
            <xsl:value-of select="$other-hours"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$this-hour"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>

      <!-- We've reached the last hour in the list. -->
      <xsl:otherwise/>
    </xsl:choose>

  </xsl:template>

</xsl:stylesheet>

gives you the following output:

<result>51</result>
Share:
30,990
CodeGuru
Author by

CodeGuru

Updated on July 09, 2022

Comments

  • CodeGuru
    CodeGuru almost 2 years

    I have a xml like below :

    <Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Name>HourlyReport</Name>
      <Id>8</Id>
      <TotalResults>1</TotalResults>
      <TotalPages>1</TotalPages>
      <Items>
        <Item>
          <Id>1</Id>
          <Hour0>23</Hour0>
          <Hour1>12</Hour1>
          <Hour2>7</Hour2>
          <Hour3>18</Hour3>
          <Hour4>32</Hour4>
          .
          .
          .
          <Hour20>28</Hour20>
          <Hour21>39</Hour21>
          <Hour22>51</Hour22>
          <Hour23>49</Hour23>
        </Item>
      </Items>
    </Report>
    

    i Need maximum value from above XML using xslt . In above case maximum value is 51. How i can get that? Also is it possible to get this maximum value in any xslt variable, so i can use it some where else. I am not getting any way. You can use any xslt version 1.0 or 2.0 .

  • dartonw
    dartonw about 10 years
    Good one. Templates, even recursive ones, are almost always faster than for-each or other loop constructs.
  • Alexander S.
    Alexander S. about 4 years
    Thank you! You made my day! It works nice for xslt 1.0 :)