[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] Here's how to create a function that has context, without passing it context


Subject: [xsl] Here's how to create a function that has context, without passing it context
From: "Costello, Roger L." <costello@xxxxxxxxx>
Date: Fri, 16 Nov 2012 23:28:03 +0000

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
Keywords