Is it possible to call function indirectly in xslt 2.0?
The answer is yes, however implementation uses dull trick of template matching to select a function handler. Template matching is a beautiful thing. Definitely it was not devised to make this trick possible.
The following example defines two functions t:sum, and t:count to call indirectly by t:test.Function id (a.k.a. function pointer) is defined by t:sum, and t:count variables.
<?xml version="1.0" encoding="utf-8"?><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="http://www.nesterovsky-bros.com" exclude-result-prefixes="xs t"><xsl:output method="xml" indent="yes"/><xsl:template match="/"> <xsl:variable name="items" as="element()*"> <value>1</value> <value>2</value> <value>3</value> <value>4</value> <value>5</value> </xsl:variable> <root> <sum> <xsl:sequence select="t:test($items, $t:sum)"/> </sum> <count> <xsl:sequence select="t:test($items, $t:count)"/> </count> </root></xsl:template><!-- Mode "t:function-call". Default match. --><xsl:template mode="t:function-call" match="@* | node()"> <xsl:sequence select=" error ( xs:QName('invalid-call'), concat('Unbound function call. Id: ', name()) )"/> </xsl:template><!-- Id of the function t:sum. --><xsl:variable name="t:sum" as="item()"> <t:sum/> </xsl:variable><!-- Mode "t:function-call". t:sum handler. --><xsl:template mode="t:function-call" match="t:sum"> <xsl:param name="items" as="element()*"/> <xsl:sequence select="t:sum($items)"/></xsl:template><!-- Calculates a sum of elements. $param - items to sum. Returns sum of element values.--><xsl:function name="t:sum" as="xs:integer"> <xsl:param name="items" as="element()*"/> <xsl:sequence select="sum($items/xs:integer(.))"/></xsl:function><!-- Id of the function t:count. --><xsl:variable name="t:count" as="item()"> <t:count/></xsl:variable><!-- Mode "t:function-call". t:count handler. --><xsl:template mode="t:function-call" match="t:count"> <xsl:param name="items" as="element()*"/> <xsl:sequence select="t:count($items)"/></xsl:template><!-- Calculates the number of elements in a sequence. $param - items to count. Returns count of element values.--><xsl:function name="t:count" as="xs:integer"> <xsl:param name="items" as="element()*"/> <xsl:sequence select="count($items)"/></xsl:function><!-- A function that performs indirect call. $param - items to pass to an indirect call. $function-id - a function id. Returns a value calculated in the indirect function.--><xsl:function name="t:test" as="xs:integer"> <xsl:param name="items" as="element()*"/> <xsl:param name="function-id" as="item()"/> <xsl:variable name="result" as="xs:integer"> <xsl:apply-templates mode="t:function-call" select="$function-id"> <xsl:with-param name="items" select="$items"/> </xsl:apply-templates> </xsl:variable> <xsl:sequence select="$result"/></xsl:function></xsl:stylesheet>
Remember Me
a@href@title, b, blockquote@cite, em, i, strike, strong, sub, super, u