Можно использовать «максимальный» шаблон, как указано в FXSL - Библиотека функционального программирования для XSLT . FXSL полностью написан на самом XSLT.
Вот пример использования шаблона «максимум»:
При этом преобразование:
<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>
применяется к этому документу XML:
<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>
желаемый результат получен.
10
Обратите внимание, что я могу передать любую необходимую операцию "сравнения" в качестве параметра! Например, если моя операция сравнения возвращает 1 всякий раз, когда $ arg1 <$ arg2, то приведенное выше преобразование выдаст «01» - минимум всех значений. </p>
Теперь я покажу два решения исходной задачи.
Solution1 (используя «максимальный» шаблон FXSL):
<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>
Когда это преобразование применяется к следующему документу XML:
<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>
желаемый результат выдается:
<persons>
<person>
<preferred-number>12</preferred-number>
</person>
<person>
<preferred-number>15</preferred-number>
</person>
<person>
<preferred-number>44</preferred-number>
</person>
</persons>
Solution2 (используя шаблон, написанный от руки):
При этом преобразование:
<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>
применяется к тому же XML-документу, снова получается правильный результат:
<persons>
<person>12</person>
<person>15</person>
<person>44</person>
</persons>