RE: breaking sorted material into subsections

Subject: RE: breaking sorted material into subsections
From: Don Bruey <dbruey@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 18 Sep 2000 13:06:23 -0400
Oliver, 

Thanks for reading carefully - I cut and pasted from the wrong XML file.  I
have been using this list to find examples of problems to solve and trying
to solve them to teach myself XSL, I goofed on this one.  My test input was
sorted in document order and I changed it before I pasted into my reply.  

Don

DaveP:  better take the "bad" XSL out of the FAQ

> -----Original Message-----
> From: Oliver Becker [mailto:obecker@xxxxxxxxxxxxxxxxxxxxxxx]
> Sent: Monday, September 18, 2000 11:02 AM
> To: xsl-list@xxxxxxxxxxxxxxxx
> Subject: RE: breaking sorted material into subsections
> 
> 
> Hi Don,
> 
> > Assuming XML looks something like this (@location left out 
> because question
> > didn't pertain to parent's @location href):
> > 
> > 
> > <IndexEntryData>
> >   <index entry = "Ca">Index1</index>
> >   <index entry = "Aaaa">Index1</index>
> >   <index entry = "Az">Index1</index>
> >   <index entry = "Bz">Index1</index>
> >   <index entry = "Abb">Index1</index>
> >   <index entry = "Ba">Index1</index>
> > </IndexEntryData>
> > 
> > This works in MSXML3 and SAXON
> 
> Do you have a different version of Saxon from mine (which is 
> Saxon 5.4.1)?
> 
> > <xsl:template match="/">                                
> >   <xsl:for-each select="//index">
> >     <xsl:sort select="@entry"/>
> > 
> > 	<!-- if first character of @entry attrib of first preceding -->
> > 	<!-- node is not equal to the context's @entry attrib -->
> > 	<!-- it's a "break" on first character of @entry -->
> > 	<!-- this works because we're already sorted by @entry -->
> > 
> >       <xsl:if test ="substring(preceding::*[1]/@entry, 1, 1) !=
> > substring(@entry, 1, 1)"> 
> 
> All axes apply to the nodes in the document, not to a 
> selected node-set.
> That means, your test checks if the entry attribute of the preceding 
> element in the *document* starts with a different letter.
> 
> >         <H2><xsl:value-of select="substring(@entry, 1, 1)" /></H2>
> >       </xsl:if>  
> > 
> >       <p>
> >         <a href="{../@location}">
> >           <xsl:value-of select="@entry"/>
> >         </a>
> >       </p>
> >   </xsl:for-each>
> > </xsl:template>
> 
> As a result Saxon outputs (newlines added)
> <H2>A</H2>
> <p><a href="">Aaaa</a></p>
> <H2>A</H2>
> <p><a href="">Abb</a></p>
> <p><a href="">Az</a></p>
> <H2>B</H2>
> <p><a href="">Ba</a></p>
> <H2>B</H2>
> <p><a href="">Bz</a></p>
> <H2>C</H2>
> <p><a href="">Ca</a></p>
> 
> i.e. two A headers and two B headers.
> 
> In fact it's a grouping problem: gather all indizes starting with the
> same letter.
> Always a good reading for this kind of problems is
> http://www.jenitennison.com/xslt/grouping/muenchian.html
> 
> Adapted to Eric's problem I get
> 
> <xsl:key name="letters" match="index" use="substring(@entry,1,1)" />
> <xsl:template match="IndexEntryData">
>    <xsl:for-each 
>         select="index[count(. | key('letters', 
>                                     substring(@entry,1,1))[1]) = 1]">
>       <xsl:sort select="@entry" />
>       <xsl:variable name="initial" select="substring(@entry,1,1)" />
>       <h2> <xsl:value-of select="$initial" /> </h2>
>       <xsl:for-each select="key('letters', $initial)">
>          <xsl:sort select="@entry" />
>          <p> <xsl:value-of select="@entry" /> </p>
>       </xsl:for-each>
>    </xsl:for-each>
> </xsl:template> 
> 
> Cheers,
> Oliver
> 
> 
> /-------------------------------------------------------------------\
> |  ob|do        Dipl.Inf. Oliver Becker                             |
> |  --+--        E-Mail: obecker@xxxxxxxxxxxxxxxxxxxxxxx             |
> |  op|qo        WWW:    http://www.informatik.hu-berlin.de/~obecker |
> \-------------------------------------------------------------------/
> 
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 


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


Current Thread