xsl-list
[Top] [All Lists]

Re: [xsl] Best practice for typing?

2019-11-24 13:05:47
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
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>