Re: [xsl] XSL QUERY

Subject: Re: [xsl] XSL QUERY
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Fri, 7 Dec 2001 16:25:35 +0000
Hi Tarun,

> Now if I have to display the XSL by categorizing from the 'Type'
> attribute of <BookName>, for example I want to display all the books
> that belong to the 'Fiction' Category of Author1, inspite of Author1
> having other types of books, then how will I achieve it?

The best way to get hold of all the nodes in a document that have some
specific value for a property is to set up a key that indexes the
nodes according to that property.

In your case, you want to get hold of all the BookName elements whose
Type attribute has the value 'Fiction', so you need to index all the
BookName elements by their Type attribute. The key needs to *match*
the BookName elements and *use* their Type attributes, as follows:

<xsl:key name="books" match="BookName" use="@Type" />

You can access all the nodes that have that particular value using the
key() function. The first argument is the name of the key (from the
name attribute of xsl:key), and the second argument is the value that
you want to search for.

In your case, the call to the key function has a first argument of
'books' and a second argument of 'Fiction'. So to apply templates to
all the BookName elements whose Type attribute has the value of
'Fiction' then you should use:

  <xsl:apply-templates select="key('books', 'Fiction')" />

But that isn't precisely what you want, since you are also concerned
about the author of those books. In fact, you want to index the
BookName elements by their Type and by their author. The author of a
particular BookName is only accessible, as far as I can tell, from the
closest preceding sibling Author element to the BookName. So given a
BookName, you could get to the name of the Author using:

  preceding-sibling::Author[1]/@name

To additionally index the BookName elements by the Author, you should
use the concat() function to concatenate the Type and the Author name
together:

<xsl:key name="books" match="BookName"
         use="concat(@Type, '::',
                     preceding-sibling::Author[1]/@name)" />

You can then find all the Fiction written by Author1 with:

  key('books', 'Fiction::Author1')

If any single run of the stylesheet is only going to be accessing
BookName elements in this way once or twice, you may find it slightly
more efficient to use a direct XPath instead, as follows:

  /Books/BookName[@Type = 'Fiction' and
                  preceding-sibling::Author[1]/@name = 'Author1']

But in the majority of cases, a key will be more efficient, especially
if you have large documents or are performing the same search multiple
times.

If your next question is what to do when you don't know the names of
the authors or the types of the books in advance, then have a look at
http://www.jenitennison.com/xslt/grouping/muenchian.html, which
describes how to use the Muenchian method, which uses keys like the
above, to do grouping when you don't know the groups that you want in
advance.

I hope that helps,

Jeni

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


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


Current Thread