Re: [xsl] Muenchian method, and keys 'n stuff

Subject: Re: [xsl] Muenchian method, and keys 'n stuff
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Wed, 23 Jan 2002 09:14:53 +0000
Hi Dave,

>> The only reason I can see why the xsl:otherwise wouldn't be fired is
>> if the $auths variable always gets set to a node set that contains
>> some nodes. That would be true if within your document you have at
>> least one r element with a Ra/lett equal to each letter of the
>> alphabet. Which could be the case - it's impossible to tell without
>> seeing your document.
> Out of 2200 books, that's highly likely, though the scoping of
> 'within adventure' makes it not true for this scope.

Sure, but the code doesn't look just in the adventure, so it would
explain why you were never hitting the 'otherwise'.

To be more explicit about the solution I was suggesting for that -
make the key include the ID for the adventure as well as the Ra/lett:

<xsl:key name="auth" match="adventure/r"
         use="concat(generate-id(..), ' ', Ra/lett)" />

The key values here are combinations of the ID of the adventure and
the letter that the author's name starts with. I used a space between
them as a separator, but you could use anything that isn't allowed in
an ID.

You're passing through the ID of the adventure through the $section
parameter, so you can use this while creating the list of $auths:

  <xsl:variable name="auths"
    select="key('auth', concat($section, ' ', $letter))" />

That guarantees that the only r elements that you get hold of from the
key are those within the adventure whose ID you passed through from
the calling template. So now the $auths variable holds a node set of r
elements, within the adventure that you're looking at, whose Ra/lett
starts with the letter $letter.

Now, I'm not sure why you're trying to pick out only the first book
with a particular letter within that section. That would be something
that you'd need to do if you wanted to collect together the letters
that start the books in that section. But by the time you're within
the when, you *know* that the letter that you're currently on
($letter) is a letter that is present in one or more rs in this
adventure. I doubt that you explicitly need to get hold of the first
auth with that letter, but if you do, then you can just use:


I think that you probably want to have a heading saying what letter
you're on, followed by a list of the r elements that you've gathered
together from that adventure with that letter as their Ra/lett. So
within the xsl:when you want something like:

    The letter <xsl:value-of select="translate($letter, $l, $u)" />
  <xsl:for-each select="$auths">
    <h3><xsl:value-of select="Ra/auth" /></h3>

This is basically what you had in your original code (and is what I
suggested in the first solution that I sent).

> Strange, that keys have been given only the current document as
> scope, I can't use them across n documents, I can't use them in a
> section of a document... I'm sure there are other use cases for
> limited scope keys. Feature for consideration for 2.0?

It does seem to be a very popular use. I should think that most of the
utility comes when using the Muenchian grouping method. But the above
case (which doesn't really use Muenchian grouping, because you *know*
what groups you're after) illustrates that it's useful elsewhere.



Jeni Tennison

 XSL-List info and archive:

Current Thread