Subject: [xsl] Functional programming in XSLT From: Alexey Gokhberg <alexei@xxxxxxxxxx> Date: Mon, 12 Mar 2001 10:07:49 +0100 |
XSLT is frequently called a functional programming language. However, few important constructions common for functional languages are missing in XSLT. At my opinion, adding the following features to XSLT could make it more suitable for the functional programming. 1. Lambda-elements ------------------ Defines anonymous functions, which may be passed to another functions as parameters. Syntax: <xsl:lambda> <xsl:param ...> <xsl:param ...> . . . <xsl:return> </xsl:lambda> (The prefix "xsl:" is used here for simplicity. Another prefix must be chosen when these features are implemented as extensions of XSLT 1.0). The xsl:lambda element contains zero or more xsl:param children and exactly one xsl:return child. The xsl:param children specify function parameters and have usual XSLT syntax and semantics. The xsl:return element specifies the function return value and may have one of two formats: <xsl:return select="expression"/> or <xsl:return> . . . <!-- Content: template --> . . . </xsl:return> When the first format is used, the result of evaluating "expression" is returned. When the second format is used, the result tree fragment obtained by instantiation of the element content is returned. (These rules are similar to those defined for xsl:variable in the standard XSLT). When the xsl:lambda element is instantiated, the xsl:lambda element node is simply copied, with all its children, to the result tree. Invocation of the lambda function is performed by the extension function "xsl:call". This function requires one or more arguments. The first argument must be a result tree fragment containing a single child node; this node must be the xsl:lambda element. Following arguments, if present, are interpreted as parameter values. The xsl:call function is evaluated as follows: a) the body of xsl:lambda element specified by the first argument is extracted b) values specified by the following arguments are assigned to parameters c) the xsl:return element is instantiated; the result of instantiation will be returned by xsl:call Arguments of xsl:call are mapped to parameters of xsl:lambda based on their position, therefore the order of xsl:param elements is significant. The following variables are visible inside the xsl:return element: - global variables and parameters - parameters declared by xsl:param siblings - variables defined locally inside this xsl:return 2. User-defined functions ------------------------- Syntax: <xsl:define name="qname"> <xsl:param ...> <xsl:param ...> . . . <xsl:return> </xsl:define> The xsl:define element defines the extension function with the name "qname". Extension functions can be defined at the top-level and within templates. The scope rules for extension function names are the same as for variable names defined with xsl:variable. The xsl:param and xsl:return children have the same syntax and similar semantics as described in case of xsl:lambda. 3. Examples ----------- A. Filtering elements in a node-set. This function accepts two arguments: a node-set and a unary lambda-function. It walks through the node-set, copying to the result tree the nodes, for which the lambda-function returns true. <xsl:define name="set:filter> <xsl:param name="set"/> <xsl:param name="lambda"/> <xsl:return> <xsl:for-each select="$set"> <xsl:if test="xsl:call($lambda, .)"> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> </xsl:return> </xsl:define> B. Mapping elements in a node-set This function accepts two arguments: a node-set and a unary lambda-function. It walks throug the node-set, applying the function to each node and copying the result to the result tree. <xsl:define name="set:map> <xsl:param name="set"/> <xsl:param name="lambda"/> <xsl:return> <xsl:for-each select="$set"> <xsl:copy-of select="xsl:call($lambda, .)"> </xsl:for-each> </xsl:return> </xsl:define> C. Reducing a node-set to a single value This function accepts three arguments: a node-set, a binary lambda-function, and an initial value. It first applies the function to the initial value and the first node in the list; then it applies the function to the result and the second node in the list, etc. <xsl:define name="set:reduce"> <xsl:param name="set"/> <xsl:param name="lambda"/> <xsl:param name="init"/> <xsl:return> <xsl:choose> <xsl:when test="count($set) = 0"> <xsl:value-of select="$init"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="set:reduce( $set[position() > 1], $lambda, xsl:call($lambda, $init, $set[1]))"/> </xsl:otherwise> </xsl:choose> </xsl:return> </xsl:define> Now, summation of values in a node-set can be defined as <xsl:define name=set:sum"> <xsl:param name="set"/> <xsl:param name="lambda"/> <xsl:return> <xsl:variable name="sum"> <xsl:lambda> <xsl:param name="x"/> <xsl:param name="y"/> <xsl:return select="$x + $y"/> </xsl:lambda> </xsl:variable> <xsl:value-of select="set:reduce($set, $sum, 0)"/> </xsl:return> </xsl:define> For the given node set "set", the sum of values for all "value" elements can now be obtained with: <xsl:variable name="value"> <xsl:lambda> <xsl:param name="node"> <xsl:return select="$node/@value"/> </xsl:lambda> </xsl:variable> <xsl:value-of select="set:sum($set, $value)"/> Due to its importance, "set:reduce" may be implemented as the built-in function. Alexey Gokhberg Unicorn Enterprises SA XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] How to disable escaping o, Peter Flynn | Thread | Re: [xsl] Functional programming in, David Rosenborg |
Re: [xsl] How to disable escaping o, Peter Flynn | Date | Re: [xsl] How to specify a path to , David Carlisle |
Month |