[xsl] Group by letter

Subject: [xsl] Group by letter
From: "Rick Quatro" <frameexpert@xxxxxxxxxxxx>
Date: Sun, 27 Jan 2008 16:58:47 -0500
Hello All,

Here is an example of my input:

<?xml version="1.0" encoding="utf-8"?>
<reference>
<refbody>
<section>
<title>Show Author ID</title>
<p id="Field_ShowAuthorID">Show Author ID</p>
<p id="Desc_ShowAuthorID">Setting that indicates if the ID...</p>
<p id="AppTo_ShowAuthorID">Review Definitions</p>
<p id="Hdr_ShowAuthorID">Author Settings</p>
</section>
<section>
<title>Author Job Title</title>
<p id="Field_ShowAuthorJobTitle">Author Job Title</p>
<p id="Desc_ShowAuthorJobTitle">Setting that indicates if the job title...</p>
<p id="AppTo_ShowAuthorJobTitle">Review Definitions, Section Item</p>
<p id="Hdr_ShowAuthorJobTitle">Author Settings</p>
</section>
<section>
<title>Author Description</title>
<p id="Field_AuthorDescription">Author Description</p>
<p id="Desc_AuthorDescription">Description of the performance review defined...</p>
<p id="AppTo_AuthorDescription">Review Definitions, Section Item</p>
<p id="Hdr_AuthorDescription">Author Settings</p>
</section>
</refbody>
</reference>


My stylesheet successfully sorts by <title> and outputs a simple glossary like this:

<?xml version="1.0" encoding="utf-16"?>
<definitions>
 <dlentry>
   <dt>Author Description</dt>
   <dd>Description of the performance review defined...</dd>
 </dlentry>
 <dlentry>
   <dt>Author Job Title</dt>
   <dd>Setting that indicates if the job title...</dd>
 </dlentry>
 <dlentry>
   <dt>Show Author ID</dt>
   <dd>Setting that indicates if the ID...</dd>
 </dlentry>
</definitions>

I need to go one step further and group the <dlentry> elements by the first character (case-insensitive) of the <dt> element, which is originally the first <p> element in the source document. So, the desired output would be:

<?xml version="1.0" encoding="utf-16"?>
<definitions>
 <dl title="A">
   <dlentry>
     <dt>Author Description</dt>
     <dd>Description of the performance review defined...</dd>
   </dlentry>
   <dlentry>
     <dt>Author Job Title</dt>
     <dd>Setting that indicates if the job title...</dd>
   </dlentry>
 </dl>
 <dl title="S">
   <dlentry>
     <dt>Show Author ID</dt>
     <dd>Setting that indicates if the ID...</dd>
   </dlentry>
 </dl>
</definitions>

Here is my working stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="xml" />


<xsl:template match="reference">
 <definitions>
   <xsl:apply-templates select="refbody" />
 </definitions>
</xsl:template>

<xsl:template match="refbody">
 <xsl:apply-templates select="section">
   <xsl:sort select="title" />
 </xsl:apply-templates>
</xsl:template>

<xsl:template match="section">
 <dlentry>
   <xsl:apply-templates select="p" />
 </dlentry>
</xsl:template>

<xsl:template match="p[position()=1]">
 <dt>
   <xsl:copy-of select="text()|*" />
 </dt>
</xsl:template>

<xsl:template match="p[position()=2]">
 <dd>
   <xsl:copy-of select="text()|*" />
 </dd>
</xsl:template>

<xsl:template match="p"/>

</xsl:stylesheet>

I think I have to add a predicate to this line to find out when a <p> has a different first character than the previous one did:

<xsl:template match="p[position()=1]">

but I am having trouble figuring out what I need. Any help or pointers would be appreciated. Thank you very much.

Rick Quatro
Carmen Publishing
585-659-8267
www.frameexpert.com

Current Thread