[xsl] Re: . in for

Subject: [xsl] Re: . in for
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Fri, 4 Jan 2002 18:58:34 +0000
David Carlisle wrote:
> The expression in the return clause of a for expression is evaluated
> with the focus being the same as the focus at the start of the for
> expression.
>
> In particular this means that . (and relative path expressions) work
> in a rather unexpected way.

I agree wholeheartedly with this observation, but would like to go
further in suggesting something that could be done about it.

It seems that the main purpose of the for expression in XPath is to
provide a substitute for the / operator for dealing with sequences
containing simple typed values (which should not have duplicates
eliminated or be re-sorted into document order). I think that this
requirement would be better satisfied with a simple mapping operator
than a for expression.

I can see that in XQuery something more is needed - full FLWR
expressions. What I say here doesn't remove the necessity of FLWR
expressions in XQuery.

But:

 - I think that having cut-down FLWR expressions in XPath
   complicates XPath unnecessarily, when a simple mapping operator
   would fulfil the common requirements, and xsl:for-each or recursive
   user-defined functions or templates can handle the rest.

 - I think XQuery would benefit from a simple mapping operator as
   well as the more sophisticated FLWR expressions, just as it's
   proved handy in many languages to have both a basic conditional
   operator and a more sophisticated if statement.

 - I think that a mapping operator would make some operations much
   easier to manage than a for expression because it could be used to
   create 'pipes' of simple operations on the items in a sequence, in
   a similar way to the manner in which the / operator allows you
   create paths of simple steps to move around a node tree.

 - I think that users will find it easier to understand a mapping
   operator, because of its similarity in behaviour to both the /
   operator and xsl:for-each, than they would a for expression that
   behaves in a very different way from either / or xsl:for-each. (The
   erroneous use of . in the return expression is an example of this
   problem.)

 - I think that users of XSLT will find it confusing that they have
   two choices for iterating over a sequence - a for expression or an
   xsl:for-each instruction - and will unadvisedly choose to use a for
   expression, which is not as extensible as xsl:for-each (you can't
   add sorting, can't assign variables, can't change to applying
   templates rather than iterating if you start with a for
   expression).

   [BTW, even if you don't agree with the suggestion for a mapping
   operator, I'd suggest that the example involving using the for
   expression on the bibliography is removed from the XPath WD for the
   above reason; of course it is entirely appropriate that it remains
   in the XQuery WD.]


I have no strong feelings about the syntax of the mapping operator,
but for the sake of some examples I'll use "->" (of course this
wouldn't be a good choice if "=>" is retained for dereferences). The
syntax could be:

  Expr "->" Expr

with the result being a sequence of items comprised of the results of
applying the expression given as the right operand on each of the
items in the sequence generated by evaluating the left operand.

To produce a sequence containing the names of the ancestor elements of
the current node:

  ancestor::* -> name()

To take a sequence of (pairs of) coordinates and first scale (through
multiplication by 2) and then move (through addition of 50 to the odd
coordinates):

  $coordinates -> (. * 2)
               -> if (position() mod 2) then . + 50 else .

This compares favourably (in my opinion, for XPath) with:

  for $a in (for $b in $coordinates return (. * 2))
      return if (position() mod 2)
             then . + 50
             else .

or:

  for $a in $coordinates
      return if (position() mod 2)
             then (. * 2) + 50
             else (. * 2)


I can see two drawbacks to using a simple mapping operator rather than
a for expression, because the context item is used rather than there
being explicit variable bindings for range variables:

 - you cannot iterate over several sequences at the same time
 - you cannot have right operands that use the value of the item from
   the left operand within a predicate

However, I believe that the proportion of cases where either of these
are necessary is small, and that the majority of those would be better
handled with the more powerful xsl:for-each (or full FLWR expressions
in XQuery) in any case.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread