Subject: Re: [xsl] Converting a Table of Contents to an index From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Thu, 11 Apr 2002 09:51:22 +0100 |
Hi Jim, > I am trying to invert a tree - specifically to create an index for a > document by pulling the leaves to the top and grouping them. A > classic problem that I am just having a mental block on . . . > ARGHHHH!!! Classic indeed :) This is a grouping problem, where you want to group the para elements throughout your document, first by their index and second by their chapter. There are two things twists on normal grouping that might be tripping you up here -- the fact that the para elements each belong to more than one group, and the fact that there are two levels of grouping. The first level key has to group the para elements by their index. However, each para element has more than one index. In the Muenchian approach, you have to have a one-to-one mapping between the things you group and the values you group them by. So in this situation, you actually have to index the *index* elements by their value: <xsl:key name="entries" match="para/index" use="." /> This enables you to get the first level of the grouping using the normal method (see http://www.jenitennison.com/xslt/grouping): <xsl:template match="book"> <index> <xsl:for-each select="chapter/para/index [count(.|key('entries', .)[1])) = 1]"> <xsl:sort select="." /> <entry> <text><xsl:value-of select="." /></text> ... </entry> </xsl:for-each> </index> </xsl:template> For the second level of the grouping, you need a key that groups together the para elements by both their index entry and their chapter. Again, it needs to be a one-to-one mapping so you actually need to match the *index* elements. From the looks of it, you can use the title of the chapter as an identifier for each chapter (otherwise generate an id using generate-id()): <xsl:key name="entries-by-chapter" match="para/index" use="concat(., '+', ancestor::chapter/@title)" /> You don't need to use this key to find the chapters for each index -- you can do that with a simple path up the ancestor axis: <xsl:template match="book"> <index> <xsl:for-each select="chapter/para/index [count(.|key('entries', .)[1])) = 1]"> <xsl:sort select="." /> <entry> <text><xsl:value-of select="." /></text> <xsl:for-each select="key('entries', .)/ancestor::chapter"> <referenceChapter name="{@title}"> ... </referenceChapter> </xsl:for-each> </entry> </xsl:for-each> </index> </xsl:template> However, you can use this key to locate the index elements within the chapter that have the entry that you're interested in, so that you can create the referencePara elements: <xsl:template match="book"> <index> <xsl:for-each select="chapter/para/index [count(.|key('entries', .)[1])) = 1]"> <xsl:sort select="." /> <xsl:variable name="entry" select="." /> <entry> <text><xsl:value-of select="$entry" /></text> <xsl:for-each select="key('entries', $entry)/ancestor::chapter"> <referenceChapter name="{@title}"> <xsl:for-each select="key('entries-by-chapter', concat($entry, '+', @title)"> <referencePara> <xsl:number count="para" /> </referencePara> </xsl:for-each> </referenceChapter> </xsl:for-each> </entry> </xsl:for-each> </index> </xsl:template> --- In XSLT 2.0, you could do this grouping with: <xsl:template match="book"> <index> <xsl:for-each-group select="chapter/para/index" group-by="."> <xsl:sort select="." /> <entry> <text><xsl:value-of select="." /></text> <xsl:for-each-group select="current-group()" group-by="ancestor::chapter/@title"> <referenceChapter name="{ancestor::chapter/@title}"> <xsl:for-each select="current-group()"> <referencePara> <xsl:number count="para" /> </referencePara> </xsl:for-each> </referenceChapter> </xsl:for-each-group> </entry> </xsl:for-each-group> </index> </xsl:template> Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Converting a Table of Content, Jim Freeman | Thread | RE: [xsl] SVG Manipulation Problems, DPawson |
RE: [xsl] date, Michael Kay | Date | Re: [xsl] Netscape XSLT ?, David Carlisle |
Month |