- From: Kay, Michael <Michael.Kay@softwareag.com>
- Date: Thu, 8 Jan 2004 19:52:24 +0100
- To: "Roorda, Dirk" <DRoorda@kluwer.nl>, <public-qt-comments@w3.org>
Many thanks for the feedback, and the kind words about Saxon. The
working groups will respond in detail, I'll try here to give a
provisional response, and also to distill the comments that we need to
discuss, some of which belong in different subgroups. I've flagged three
points below:
A - joint (XPath)
B - XSLT
C - joint (XPath)
>
> Performance improvement!
> ------------------------
> In XSLT1.0 the code was 160 kB, and on a book of 250 kB it
> ran 40 seconds (500MHz). This includes the generations of a
> table of contents and several registers. I have completely
> rewritten de code in order to exploit the benefits of
> XSLT2.0. Now the code is only 100 kB and the execution time
> is 20 seconds with identical output.
This is excellent news. In general Saxon 7.8 is about 25% faster than
6.5, so the rest of the improvement must be due to new language
features.
>
> Less extensions needed
> ----------------------
> I generally enjoyed the improvements of 2.0 over 1.0 very
> much. A lot of code I have moved into XPATH2.0 expressions. I
> got rid of the use of all extensions, except saxon:evaluate.
Also good news. Unless you suggest otherwise, I won't interpret this as
a formal comment asking for dynamic XPath evaluation - a feature which
the working group has previously decided not to include in the spec this
time around.
>
> Using XSLT2.0 and XPATH2.0
> --------------------------
> 1. No variable declaration in XPATH
> While moving code from XSLT to XPATH I encountered one
> particular stumbling block: in XPATH you cannot declare
> variables in full generality. As you say in your saxon
> documentation, XPATH now has variable binding constructs as
> for, some and every, but that does not help enough. For
> example, if I want to recode something like <xsl:for-each
> select="tokenize('1 2 3 4 5')">
> <xsl:variable name="a" as="xs:string" select="my:func1(.)"/>
> <xsl:variable name="b" as="xs:integer" select="my:func2(a)"/>
> <xsl:variable name="c" as="xs:string *" select="my:func3(a)"/>
> <!-- do something useful with $a and $b and $c -->
> </xsl:for-each> In XPATH2.0 I am tempted to do something like
> this: <xsl:sequence select="
> for $i in tokenize('1 2 3 4 5') return
> for $a in my:func1($i) return
> for $b in my:func2($a) return
> for $c in (my:func3($b)) return
> ...
> "/>
> But the problem here is that $c is sequence valued, and
> because sequences cannot be nested, I see no way to bind the
> $c of the third for loop to a sequence of strings. That's why
> I think XPATH would profit by a define or let construct, like
> functional programming languages have, something like define
> $x value ( expr ) in expr or more general define $x1 value (
> expr ) $x2 value ( expr ) ... $xn value ( expr ) in expr
[Comment A]
What you are asking for here is for the XPath "for" expression to be
extended to include a larger subset of XQuery's FLWOR expressions, which
include a "let" clause that has the functionality you are looking for.
The syntax is "let $x := value return expr". This is something that we
should consider in the XPath sub-group.
>
> 2. Text nodes
> -------------
> It was not obvious to me how to generate text-nodes. Of the
> text comes from a parameter, <xsl:text> does not do it.
> Thanks to Michael Kay I know now how to do it: <xsl:function
> name="my:text" as="node()?">
> <xsl:param name="text" as="xs:string"/>
> <xsl:sequence>
> <xsl:value-of select="$text"/>
> </xsl:sequence>
> </xsl:function>
> Note that if $text is empty, no node will be returned!
> But I wonder why it is not possible to create text nodes with
> <xsl:text> as freely as you create attribute nodes with
> <xsl:attribute> and element nodes with <xsl:element> and
> namespace nodes with <xsl:namespace>.
[Comment B]
I think the XSL WG should look again at whether we can make <xsl:text>
and <xsl:value-of> synonymous. The current nomenclature will, as you
point out, cause people to expect that the instruction for creating text
nodes is <xsl:text> rather than <xsl:value-of>, and we should see if we
can meet that expectation while retaining backwards compatibility.
>
> 3. Manipulating the context
> ---------------------------
> Often I find myself in a situation that I want to repeat a
> piece of working code, so I wrap it in a for loop. There are
> two options: an XSLT for-each or an XPATH for. When I have
> the choice, I take the XPATH version, which has the advantage
> that the context node does not change. But when I need to do
> things inside the body of the loop that cannot (yet) be done
> in XPATH, I am forced to use the XSLT for-each. But then the
> context node changes, and this may cause nasty problems. For
> example, if I use the function key in the body, it does not
> work if the sequence that I selected in the xsl:for-each does
> not consist of nodes in the current document. Again, Michael
> Kay pointed out that one can say $n/key($key,$value) for a
> suitable node $n. This may lead to a more general concept:
> allow more access to the stack of contexts that must be
> maintained somewhere. It would be nice to be able to specify
> in what context an XPATH expression should be evaluated.
> Especially in for-each loops, what you really want is to
> evaluate XPATH expressions in the parent context, i.e. the
> context that was in force just before entering the for-each
> loop. For example: current() is the current context node,
> current(1) the node that is current in the parent context,
> current(2) the node that is current in the grandparent
> context. Likewise position(1), position(2) and last(1) and
> last(2), etc. Or things like <xsl:value-of select="." context="2"/>.
[Comment C]
It seems that for complex programming tasks, range variables are needed,
while for simple programming tasks, a "context" concept is useful. This
means we currently have an awkward mixture of the two. I'm not
comfortable with this situation, but I can't see easily how to resolve
it. I think a stack of contexts would be quite difficult for some users
to cope with: it was offered by Microsoft's WD-xsl dialect and I don't
think it was greatly successful. There is a long-standing proposal on
the table that a version of the "for" expression (a "simple mapping
operator") is needed that binds a context item rather than a range
variable; I have also proposed in the past a mechanism that allows a
variable to be bound to the context node so that arbitrary joins can be
done in a path expression. Adding "let" to XPath, as suggested above,
would enable this, though the syntax is not elegant: you would be able
to write:
//customer[let $c := . return //product[.//customer = $c]]
A syntax that looks better in the middle of a path expression might be
//customer[$c$ //product[.//customer = $c]]
>
> 4. Overall impression
> ---------------------
> I have the feeling that XSLT2.0 is much more of a programming
> language than XSLT1.0 was. I am pleased with the more general
> datastructures of sequences and with more capabilities of
> manipulating nodes, so that you can use node sequences for
> general data manipulation.
>
It's really good to have positive feedback. Thanks!
Michael Kay
Received on Thursday, 8 January 2004 13:56:33 UTC