One can use the "maximum" template as provided by FXSL -- the Functional Programming Library for XSLT. FXSL is written entirely in XSLT itself.
Here is an example of using the "maximum" template:
When this transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:maximum-own-compare="maximum-own-compare"
xmlns:Mycompare="Mycompare"
exclude-result-prefixes="xsl f Mycompare"
>
<xsl:import href="maximum.xsl"/>
<xsl:output method="text"/>
<!-- This transformation must be applied to:
numList.xml
-->
<Mycompare:Mycompare/>
<xsl:template match="/">
<xsl:variable name="vCMPFun"
select="document('')/*/Mycompare:*[1]"/>
<xsl:call-template name="maximum">
<xsl:with-param name="pList" select="/*/*"/>
<xsl:with-param name="pCMPFun" select="$vCMPFun"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="MyIsGreater" mode="f:FXSL"
match="Mycompare:*">
<xsl:param name="arg1"/>
<xsl:param name="arg2"/>
<xsl:choose>
<xsl:when test="$arg1 > $arg2">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
is applied on this XML document:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
the wanted result is obtained.
10
Note, that I can pass any needed "compare" operation as parameter! For example, if my compare operation returns 1 whenever $arg1 < $arg2, then the above transformation will produce "01" -- the minimum of all values.
Now, I will show two solutions for the original problem.
Solution1 (using FXSL's "maximum" template):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:Mycompare="Mycompare"
exclude-result-prefixes="xsl f Mycompare"
>
<xsl:import href="maximum.xsl"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<Mycompare:Mycompare/>
<xsl:variable name="vCMPFun"
select="document('')/*/Mycompare:*[1]"/>
<xsl:template match="/">
<persons>
<xsl:apply-templates select="*/*"/>
</persons>
</xsl:template>
<xsl:template match="person">
<person>
<xsl:call-template name="maximum">
<xsl:with-param name="pList" select="*/*"/>
<xsl:with-param name="pCMPFun" select="$vCMPFun"/>
</xsl:call-template>
</person>
</xsl:template>
<xsl:template name="MyIsGreater" mode="f:FXSL"
match="Mycompare:*">
<xsl:param name="arg1"/>
<xsl:param name="arg2"/>
<xsl:choose>
<xsl:when test="$arg1 > $arg2">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>
<person>
<preferred-number>
<preferred-number>8</preferred-number>
<preferred-number>10</preferred-number>
<preferred-number>4</preferred-number>
<preferred-number>12</preferred-number></preferred-number>
</person>
<person>
<preferred-number>
<preferred-number>2</preferred-number>
<preferred-number>11</preferred-number>
<preferred-number>15</preferred-number>
<preferred-number>6</preferred-number></preferred-number>
</person>
<person>
<preferred-number>
<preferred-number>10</preferred-number>
<preferred-number>44</preferred-number>
<preferred-number>9</preferred-number></preferred-number>
</person>
</t>
the wanted result is produced:
<persons>
<person>
<preferred-number>12</preferred-number>
</person>
<person>
<preferred-number>15</preferred-number>
</person>
<person>
<preferred-number>44</preferred-number>
</person>
</persons>
Solution2 (using a template written by hand):
When this transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<persons>
<xsl:apply-templates select="*/*"/>
</persons>
</xsl:template>
<xsl:template match="person">
<person>
<xsl:call-template name="maximum">
<xsl:with-param name="pList" select="*/*"/>
</xsl:call-template>
</person>
</xsl:template>
<xsl:template name="maximum">
<xsl:param name="pList"/>
<xsl:choose>
<xsl:when test="not($pList)">
-99999999999999999999
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vLen" select="count($pList)"/>
<xsl:choose>
<xsl:when test="$vLen = 1">
<xsl:value-of select="$pList[1]"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vHalf"
select="floor($vLen div 2)"/>
<xsl:variable name="vMax1">
<xsl:call-template name="maximum">
<xsl:with-param name="pList"
select="$pList[not(position() > $vHalf)]"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vMax2">
<xsl:call-template name="maximum">
<xsl:with-param name="pList"
select="$pList[position() > $vHalf]"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of
select="$vMax1*($vMax1 > $vMax2)
+
$vMax2*($vMax2 >= $vMax1)
"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
is applied on the same XML document, again the correct result is produced:
<persons>
<person>12</person>
<person>15</person>
<person>44</person>
</persons>