Subject: Re: [xsl] Here's how to create a function that has context, without passing it context From: Michael Kay <mike@xxxxxxxxxxxx> Date: Sat, 17 Nov 2012 00:07:33 +0000 |
<xsl:function name="f:author"> <xsl:param name="arg" as="xs:string"/> <xsl:sequence select="$root//author[name=$arg]"/> </xsl:function>
Michael Kay Saxonica
Hi Folks,
Suppose that you would like to create a function that, given the title of a book, it returns the author.
For example, this function call:
author('The Society of Mind')
returns this author:
Marvin Minsky
Notice that the function, author(), was just provided a string and no context.
How can the function obtain the author without being given any context? Recall that functions supposedly have no context and you must give it (through parameters) all the context it needs.
In this message I show how to create functions that have context, but you don't have to give it the context.
This technique is so cool.
Here is the XML document that the function will operate on:
<Books> <Book> <Title>Six Great Ideas</Title> <Author>Mortimer J. Adler</Author> </Book> <Book> <Title>The Society of Mind</Title> <Author>Marvin Minsky</Author> </Book> </Books>
I create a variable, author, that is defined to be an XPath 3.0 anonymous function:
<xsl:variable name="author" select="... define author as an anonymous function ... " />
Then I invoke the "author function" with a string representing the title of a book:
<xsl:value-of select="$author('The Society of Mind')" />
Here is the output:
Marvin Minsky
This is the key to the technique:
Create a variable that is defined to be a function that returns a function.
Wow!
We need to step through this very carefully.
I create a variable, root, to which I pass the root element of the XML document (Books):
<xsl:variable name="root" select="function( $root_ as element(Books) )
The function returns a function:
<xsl:variable name="root" select="function( $root_ as element(Books) ) as function(xs:string) as item()
The function that is returned takes an argument that is a string representing the title of a book and it returns the author of the book:
<xsl:variable name="root" select="function( $root_ as element(Books) ) as function(xs:string) as item() {function($title as xs:string) as item() {$root_/Book[Title eq $title]/Author}}" />
Remember the author variable? It gets the returned function:
<xsl:variable name="author" select="$root(/Books)" />
Okay, let's put it all together:
--------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:output method="text"/>
<xsl:variable name="root" select="function(
$root_ as element(Books)
)
as function(xs:string) as item()
{function($title as xs:string) as item() {$root_/Book[Title eq $title]/Author}}" />
<xsl:variable name="author" select="$root(/Books)" />
<xsl:template match="Books">
<xsl:value-of select="$author('The Society of Mind')" />
</xsl:template>
</xsl:stylesheet>
--------------------------------------------------------
Pretty cool, aye?
/Roger
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Here's how to create a functi, Costello, Roger L. | Thread | Re: [xsl] Here's how to create a fu, Dimitre Novatchev |
[xsl] Here's how to create a functi, Costello, Roger L. | Date | Re: [xsl] Here's how to create a fu, Dimitre Novatchev |
Month |