[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: XPath's role (Was: Re: Re: . in for)

Subject: Re: XPath's role (Was: Re: Re: . in for)
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 7 Jan 2002 18:27:26 +0000
xpath select item from sequence
Hi Mike,

> If it can be shown that user-defined functions can handle all cases
> that would otherwise need range variables, that would certainly be
> an interesting argument to use.

I'm not sure I can *prove* anything (left my mathematical years behind
a while ago), so this is probably something for David or Dimitre. But
isn't it provable from the fact that any iteration over a sequence can
be performed by recursing over the sequence?

Taking the basic example:

  for $item in $sequence return some:function($item)

is equivalent to:

<xsl:function name="my:for">
  <xsl:param name="sequence" type="item*" />
  <xsl:result select="if (empty($sequence))
                      then ()
                      else (my:function($sequence[1]),
                            my:for($sequence[position() > 1]))" />

with the call:


Introducing a second range variable:

  for $item1 in $sequence1,
      $item2 in $sequence2
  return some:function($item1, $item2)

is equivalent to:

<xsl:function name="my:for1">
  <xsl:param name="sequence1" type="item*" />
  <xsl:param name="sequence2" type="item*" />
  <xsl:variable name="item1" select="$sequence1[1]" />
  <xsl:result select="if (empty($sequence1))
                      then ()
                      else (my:for2($item1, $sequence2),
                            my:for1($sequence1[position() > 1],
                                    $sequence2))" />

<xsl:function name="my:for2">
  <xsl:param name="item1" type="item" />
  <xsl:param name="sequence2" type="item*" />
  <xsl:variable name="item2" select="$sequence2[1]" />
  <xsl:result select="if (empty($sequence2))
                      then ()
                      else (some:function($item1, $item2),
                                    $sequence2[position() > 1]))" />

which you would call with:

  my:for1($sequence1, $sequence2)

[Note that any filtering of $sequence2 based on the items in
$sequence1 can be handled in some:function() in the general case.]

You can continue doing this ad infinitum, I believe, each time adding
another my:for() function to handle the additional range variable.

Of course there's a difference between proving that you *can* do all
for expressions with user-defined functions and stating that you'd
*want* to do all for expressions with user-defined functions. And I
can quite understand people looking at the above and going 'I'd rather
write a for expression than all of that!'

But in real life, I think the vast majority of the use cases for the
for expression (in XSLT) can be handled with a simple mapping
operator. And hardly any need more than a single function (plus a
simple mapping operator). The existential semantics of the various
comparison operators help enormously, of course. Plus, the only reason
you need to use a function rather than a xsl:for-each (or equivalent)
is if (a) some:function() returns nodes and (b) you don't want to lose
the identity of those nodes.



Jeni Tennison

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Current Thread


Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
First Name
Last Name
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.