RE: XSLT2.0 feedback

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