This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: . in for
- From: Jeni Tennison <jeni at jenitennison dot com>
- To: www-xpath-comments at w3 dot org
- Cc: xsl-list at lists dot mulberrytech dot com
- Date: Fri, 4 Jan 2002 18:58:34 +0000
- Subject: [xsl] Re: . in for
- Organization: Jeni Tennison Consulting Ltd
- References: <200201041708.RAA22328@penguin.nag.co.uk>
- Reply-to: xsl-list at lists dot mulberrytech dot com
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