RE: XSLT 2.0 Idea: third argument for key()

Subject: RE: XSLT 2.0 Idea: third argument for key()
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Mon, 11 Sep 2000 19:38:43 +0100
Mike Kay wrote:
>> In brief: I'd like to suggest having a third argument for 
>> key(), a node set, such that the key only retrieves nodes with the
>relevant 
>> key value that are within this node set.
>>
>I'm personally more inclined to the view that the key() function should be
>deprecated, and <xsl:key> should become like "create index" in SQL: an
>optimization hint for the processor. Your XPath expression should then
>specify the nodes it wants explicitly using predicates, and the processor
>should detect automatically that there's an index it can use.

I think that this would be really useful, especially in cases where the
expression used to retrieve a particular node is fairly simple, like:

  $elements[@id = $id]

[Presumably id() should be deprecated as well?]

I think it's worth bearing in mind, though, that key() is a shortcut for
the stylesheet author as well as an optimisation for the processor.  For
example, with a structure of the form:

  <km:concept id="cat">
    ...
    <km:supertype>
      <km:concept-ref ref="mammal" />
    </km:supertype>
    ...
  </km:concept>

It's handy to define a key to retrieve all the subtypes of a concept based
on their definition of their supertype(s):

<xsl:key name="subtypes"
         match="km:concept" 
         use="km:supertype/km:concept-ref/@ref" />

In this case, the 'use' expression is fairly long and fairly complex.
[This is also the case with keys with values constructed through
concatenation, but those aren't an issue as they would generally be much
better represented through XPaths given the automatic optimisation Mike
suggests.]

Using the key() function, getting the suptype involves:

  key('subtypes', @id)

Using a full XPath, it would be:

  //km:concept[km:supertype/km:concept-ref/@ref = current()/@id]

This isn't a problem per se, but it is a little annoying when you want to
retrieve nodes in the same way in multiple places within your stylesheet,
both in terms of the length and complexity of the expression, and in terms
of ease of maintenance: one good thing about key() is that it centralises
the location of the definition of the way in which you want to retrieve
certain node sets.  The only way that I can see to give a similar
centralised definition of the equivalent of the 'use' attribute of a key is
to use entities.

Basically I'm arguing that, even leaving aside optimisation issues, the
key() function is still useful for stylesheet authors as it can be simpler,
shorter and easier to maintain than writing an XPath to do the equivalent
retrieval.

Another, perhaps more convincing, argument that springs to mind is the fact
that the key value within the key() function is relative to the context
node, whereas within an XPath expression the context node changes by the
time you get to saying what 'key value' you want.  I don't think it would
be possible to generate the equivalent of:

  km:concept[key('subtypes', @id)]

(selecting only those concepts that have a subtype) in a single XPath
expression, although I'd be happy to be proved wrong.  Naturally, there are
ways round this kind of thing (e.g. using an xsl:if nested inside an
xsl:for-each), but not within a xsl:sort select expression, for example.

Personally, I find key() very useful, not just because it gives an
optimised alternative to XPaths, but in its own right.

Cheers,

Jeni

Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread