Thanks for that review, Gerrit.
> I've seen situations where XSLT developers didn't seem to know how
> to select every p from each of the two variable flavors.
I'm one of those who don't really know, but at least I know that I
don't know. First thing I do almost every time I've created a $var1
is test whether I want $var1/*/p or $var1/p. :-)
(Although these days I'm much more likely to create a $var2 by being
explicit with @as, of which I'm becoming a bit of a fan.)
> While it has been mentioned that it is generally advisable to add an as
> attribute to variable and parameter declarations, it might be useful to
> make novices aware of the fact that adding or omitting type information
> can change the nature of the beast that they are declaring.
> Example:
> <xsl:variable name="var1">
> <doc>
> <p/>
> </doc>
> </xsl:variable>
> $var1/*/name() gives 'doc'
> <xsl:variable name="var2" as="element(*)">
> <doc>
> <p/>
> </doc>
> </xsl:variable>
> $var2/*/name() gives 'p'
> This is because of implicit document node creation [1].
> I've seen situations where XSLT developers didn't seem to know how to
> select every p from each of the two variable flavors. That's why they
> tend to write $var1//p and $var2//p indiscriminately, instead of
> $var1/doc/p and $var2/p. Not only are the latter expressions more
> efficient, but they also help avoid selecting nested p elements in this
> scenario:
> <xsl:variable name="var">
> <doc>
> <p>text<fn>
> <p>footnote</p>
> </fn></p>
> </doc>
> </xsl:variable>
> Because of an uncertainty about what to expect when they select a child
> element of this variable, these people tend to write something like
> $var//p[not(ancestor::p)]
> in order to get only the outermost p elements, which is even more
> inefficient.
> I must admit that if I really want to have a document node around the
> element, for example because I want to use fn:key() on the variable
> content in XSLT 2.0, I sometimes omit the as attribute deliberately. On
> other occasions, I would write
> <xsl:variable name="var1" as="document-node(element(*))">
> <xsl:document>
> <doc>
> <p/>
> </doc>
> </xsl:document>
> </xsl:variable>
> instead of the $var1 declaration as seen above, just to make clear that
> I deliberately wanted the variable to hold a document.
> Other people disagree [2], but I always try to teach the importance of
> the as attribute in the first lessons, and I keep telling novices that
> they should use xsl:sequence instead of xsl:value-of, unless they want
> to create a text node.
> People with an XSLT1 upbringing frequently use xsl:value-of, and they
> spread this bad habit when they teach, alas.
> Remember, the XDM sequence type system is your friend [3].
> [1] https://www.w3.org/TR/xslt-30/#temporary-trees
> [2] https://twitter.com/gimsieke/status/756810053613678592
> [3] https://twitter.com/gimsieke/status/233936479917846528
|