xsl-list
[Top] [All Lists]

Re: [xsl] Matching on keys

2017-01-06 12:37:15
This comes up a lot in the DITA stylesheets. John Lumley did a fair bit of work 
on optimizing such patterns, and the basic technology is there in current Saxon 
releases, but not well productized, so you have to configure it using some 
pretty complex configuration files. As it happens I've just been studying the 
code to see what part of it could be packaged in a more usable way for Saxon 
9.8. But in the absence of that...

From the performance perspective you really want to only tokenize the class 
attribute of each element once, rather than doing it each time an attempt is 
made to match the element against a template rule. Not only that, but you want 
to index the elements against all the classes they belong to, and the only way 
to do that is with keys (or with maps perhaps). So I don't think your code can 
be bettered from a performance perspective.

There are cases where using functions - especially memo functions - in match 
patterns can be useful, but I don't think that's particularly the case here. 
There are also cases where using global variables is effective, e.g if you want 
to treat the first X sibling after a Y specially, the most effective way might 
be

<xsl:variable name="special-Xs" select="//Y/following-sibling::X[1]"/>

<xsl:template match="$special-Xs">  (XSLT 3.0)

or

<xsl:template match="*[. intersect $special-Xs]">  (XSLT 2.0)

Michael Kay
Saxonica




On 6 Jan 2017, at 17:56, Wendell Piez wapiez(_at_)wendellpiez(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Hello XSL-List,

I am having more and more occasions these days to handle HTML @class
semantics, which as you probably know can be 'overloaded' in the sense
that multiple values (NMTOKEN) of 'class' may have to be distinguished
and handled separately.

An idiom for matching any element .foo (CSS selector) could be

<xsl:template match="*[tokenize(@class,'\s+')='foo')]">
  ...
</xsl:template>

This will match the element by virtue of the value being present on
the @class, split apart at white space and compared (many-to-one) with
=

(That logic can of course be relegated to a stylesheet function call
for neatness. It's true you can get an element matching more than one
template this way: that's the idea.)

Question: I can define a key, as in

<xsl:key name="elements-by-class" match="*[matches(@class,'\S')]"
use="tokenize(@class,'\s+')"/>

then

<xsl:template match="key('elements-by-class','foo')">
...
</xsl:template>

I regard this as a neat trick, and think it might be an "improvement"
:-) but I suppose from one point of view at least, that may be
arguable.

What do readers think? Should I prefer a stylesheet function instead?
(John Lumley what do you think?)

Regards,
Wendell

-- 
Wendell Piez | http://www.wendellpiez.com
XML | XSLT | electronic publishing
Eat Your Vegetables
_____oo_________o_o___ooooo____ooooooo_^

--~----------------------------------------------------------------
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>