Re: Designs for XSLT functions (Was: Re: [xsl] RE: syntax sugar for call-template)

Subject: Re: Designs for XSLT functions (Was: Re: [xsl] RE: syntax sugar for call-template)
From: Uche Ogbuji <uche.ogbuji@xxxxxxxxxxxxxxx>
Date: Sun, 18 Feb 2001 22:10:44 -0700
> There seems to be a reasonable amount of support for user-defined
> functions written in XSLT, whether to sweeten the syntax of
> xsl:call-template or to allow XPaths previously only dreamed about.
> If we're going to move ahead with this, we need to agree on a syntax
> for (1) declaring the functions and (2) calling the functions.  In
> this email, I'm going to lay out the major designs that have been
> suggested so far so that we can discuss them and hopefully come up
> with some kind of resolution that's acceptable to everyone.
> If I leave out an argument or you have a strong feeling in support or
> contradiction of one, please comment on it. After we've discussed the
> different options for a bit, I'll organise a vote and then put
> together a proposal based on that. So long as no one objects to me
> doing so?
> Of course, we can discuss this as much as we want - if we don't get
> implementation support then it's pointless. But I have faith that if
> we come up with a well-thought-out proposal then at least some
> implementers will come on board.

I've enjoyed the discussion quite a bit, and if I wan't using up all my ticks 
fighting xsl:script, I'd have participated more.

As it is, I am very interested in experimental implementation of these ideas 
in 4XSLT.

I hope that I and my fellow implementors who are interested in these ideas can 
all agree on a single NSRef for this set of extensions.  I have the domain available.  If this is amenable,  how about

> [Within this email, I'm using 'exsl' as a namespace prefix for a set
> of common extensions, to highlight that new elements will have to be
> defined somewhere and that they very likely won't make it into XSLT
> 1.1.]
> 1. Declaring Functions
> ----------------------
> 1.a. Using xsl:template vs. using exsl:function
> Using xsl:template:
> <xsl:template name="my:func">
>   ...
> </xsl:template>
> Using exsl:function:
> <exsl:function name="my:func">
>   ...
> </exsl:function>
> Arguments for xsl:template include:
> i.  it already exists
> ii. it might then be possible to have a template that was used both
>     with normal xsl:call-template syntax and as a function (though
>     it's arguable whether this is desirable).

Well, the nice thing about this is that it would be easy to call existing 
named templates with the new syntax.  Also, one could set up a single template 
for import into both regular transforms and ones that use exsl:function.

> Arguments for exsl:function include:
> i.  the ability to constrain its content in ways that are necessary for
>     extension functions
> ii. it highlights the distinction between templates and functions.

These are also powerful arguments.  I would tend to lean towards 
exsl:function, since it's probably easier to extend the system to accommodate 
reguler templates after it has been exercised a bit.

> 1.b. Top-level declaration vs. declaration within xsl:script

As they say in teen movies: "don't even go there".

To be more precise, I vote firmly for top-level.  Surprise surprise.  
Perfectly legal under XSLT 1.0, so why not?

> 1.c. exsl:return and/or result tree fragments
> exsl:return:
> <exsl:function name="my:func">
>    <exsl:return select="'foo'" />
> </exsl:function>
> [Note - similar syntax for exsl:return as xsl:variable etc. - set
> through select attribute or content.]
> result tree fragments:
> <exsl:function name="my:func">
>    <xsl:text>foo</xsl:text>
> </exsl:function>
> both:
> <exsl:function name="my:func">
>    <xsl:choose>
>       <xsl:when test="$mytest">foo</xsl:when>
>       <xsl:otherwise>
>          <exsl:return select="'foo'" />
>       </xsl:otherwise>
>    </xsl:choose>
> </exsl:function>
> Arguments for exsl:return include:
> i. allows return of value types other than RTFs
> Arguments for returning result tree fragments include:
> i. gives easy shorthand for returning values other than node sets
> Arguments for *only* exsl:return include:
> i.  prevents result elements from 'disappearing' or being written to
>     the result tree

I vote firmly for *only* exsl:return.  I agree with Mike Kay, and I'll add the 
general non-determinism that is thrown into the mix by such a broad 
side-effect as copying to the result tree.  And I can't see the point if the 
contents would just disappear.

But I do think we should allow RTFs as follows:

<exsl:function name="my:func">
   <xsl:when test="$i-want-my-rtf">
    <exsl:return select="'foo'" />

> 2. Calling Functions
> --------------------
> 2.a. exsl:function() vs. my:func()
> exsl:function():
>    foo[exsl:function('my:func')]
> my:func():
>    foo[my:func()]
> Arguments for exsl:function() [or similar] include:
> i. allows function names to be decided dynamically
> Arguments for my:func() include:
> i. follows syntax for other extension functions

I think we can have both, but I'd rename exsl:function to exsl:call.  Then both




would be legal.  This is a common approach in languages that allow dynamic 
programming (for instance, in Python exsl:call() is similar to apply()).

> 2.b. Passing parameters by position vs. name
> Passing parameters by position:
>    my:func(foo, 'bar', 1)
> Passing parameters by name:
>    my:func('one', foo,
>            'two', 'bar',
>            'three', 1)
> Arguments for passing parameters by position include:
> i. follows syntax for other extension functions
> Arguments for passing parameters by name include:
> i.  follows syntax for xsl:call-template
> ii. more easily allows multiple optional parameters

OK, here's an extravagant idea.

Again allow both, but this time by allowing tricks with exsl:call.

The first exsl:call parameter is the function qname.  An even number of 
further parameters is permitted, and if so, these are the named parameters.  
So given

<exsl:function name="my:ternary">
  <xsl:param name='a'/>
  <xsl:param name='b'/>
  <xsl:param name='c'/>
  <xsl:when test="$a">
    <exsl:return select="$b">
    <exsl:return select="$c" />

I could call this either as

my:ternary($bool, 'true', 'false')

or as

exsl:call('my:ternary', 'a', $bool', 'b', 'true', 'c', 'false')

Uche Ogbuji                               Principal Consultant
uche.ogbuji@xxxxxxxxxxxxxxx               +1 303 583 9900 x 101
Fourthought, Inc.                
4735 East Walnut St, Ste. C, Boulder, CO 80301-2537, USA
Software-engineering, knowledge-management, XML, CORBA, Linux, Python

 XSL-List info and archive:

Current Thread