[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

XSLT/XPath Question (Grouping Authors by First Charact

Subject: XSLT/XPath Question (Grouping Authors by First Character of Last Name)
From: "Kevin Grover" <kevin@xxxxxxxxxxxxxxx>
Date: Sat, 3 Mar 2007 14:05:32 -0800
 XSLT/XPath Question (Grouping Authors by First Charact
I have an XSLT/XPath Question that I've been beating my head against
for a while.

I have a list of authors with a name element and a file-as attribute
(XPATH: /booklist/author/name/@file-as).  I currently build a Table of
Contents sorted by the author/name/@file-as attribute.  That works OK.
I want to add further markup (by putting authors in groups by the
first character of their last name).

I can get the first character of the last name, I've even created a
key that allows me to access the nodes of authors by the first
character in the last name (see the commented out section of the b.xsl
file included below).  However, I can not figure out how to get a list
of distinct characters (from the last names) so that I can iterate
over them and generate my list.

Here are stripped down example source files:

Exmaple author file: (file a.xml)

<?xml version="1.0" encoding="UTF-8"?>
<booklist>
  <author>
     <name file-as="Adams, Douglas">Douglas Adams</name>
  </author>
  <author>
     <name file-as="Anderson, Kevin J.">Kevin J. Anderson</name>
  </author>
  <author>
     <name file-as="Anthony, Piers">Piers Anthony</name>
  </author>
  <author>
     <name file-as="Archer, Jeffrey">Jeffrey Archer</name>
  </author>
  <author>
     <name file-as="Baldacci, David">David Baldacci</name>
  </author>
  <author>
     <name file-as="Ball, Margaret">Margaret Ball</name>
  </author>
  <author>
     <name file-as="Bradley, Marion Zimmer">Marion Zimmer Bradley</name>
  </author>
  <author>
     <name file-as="Carcaterra, Lorenzo">Lorenzo Carcaterra</name>
  </author>
  <author>
     <name file-as="Card, Orson Scott">Orson Scott Card</name>
  </author>
  <author>
     <name file-as="Chalker, Jack L.">Jack L. Chalker</name>
  </author>
  <author>
     <name file-as="Dahl, Roald">Roald Dahl</name>
  </author>
  <author>
     <name file-as="Daley, Brian">Brian Daley</name>
  </author>
  <author>
     <name file-as="Dann, Jack">Jack Dann</name>
  </author>
</booklist>


I can extract the authors and generate a table of contents with the following XSLT: (b.xsl)

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               >
   <xsl:output method="xml"/>
   <xsl:output indent="yes"/>
   <xsl:strip-space elements="*"/>

<xsl:key name="alet" match="//author" use="substring(name/@file-as,1,1)"/>

   <xsl:template match="/booklist">
       <xsl:call-template name="gen-toc"/>
   </xsl:template>

   <!-- Generate Table of Contents -->
   <xsl:template name="gen-toc">
     <div id="toc" class="toc">
<!--
     <h1>Test</h1>
     <ul>
     <xsl:for-each select="key('alet','A')">
       <li><xsl:value-of select="name/@file-as"/></li>
     </xsl:for-each>
     </ul>
-->
     <h1>Table of Contents (by Author)</h1>
     <ul>
     <xsl:for-each select="//author/name">
       <xsl:sort select="@file-as"/>
       <li><a href="#{generate-id(..)}"><xsl:value-of
select="@file-as"/></a></li>
     </xsl:for-each>
     </ul>
     </div>
   </xsl:template>

</xsl:stylesheet>


This works. It generates this: (out.xml)


<?xml version="1.0"?>
<div id="toc" class="toc">
 <h1>Table of Contents (by Author)</h1>
 <ul>
   <li>
     <a href="#id91524">Adams, Douglas</a>
   </li>
   <li>
     <a href="#id91570">Anderson, Kevin J.</a>
   </li>
   <li>
     <a href="#id91578">Anthony, Piers</a>
   </li>
   <li>
     <a href="#id91588">Archer, Jeffrey</a>
   </li>
   <li>
     <a href="#id91597">Baldacci, David</a>
   </li>
   <li>
     <a href="#id91607">Ball, Margaret</a>
   </li>
   <li>
     <a href="#id91617">Bradley, Marion Zimmer</a>
   </li>
   <li>
     <a href="#id91627">Carcaterra, Lorenzo</a>
   </li>
   <li>
     <a href="#id93622">Card, Orson Scott</a>
   </li>
   <li>
     <a href="#id93633">Chalker, Jack L.</a>
   </li>
   <li>
     <a href="#id93643">Dahl, Roald</a>
   </li>
   <li>
     <a href="#id93653">Daley, Brian</a>
   </li>
   <li>
     <a href="#id93663">Dann, Jack</a>
   </li>
 </ul>
</div>


I want to change that so that I have the authors in subsections, with the first letter of their last names as the the main entry, like so

       A
               //author/name/@file-as[.=='A']
       B
               //author/name/@file-as[.=='B']
       etc..

Like this output: (out-desired.xml)

[This was hand edited, I have not yet figured out how to automatically
generate it.]

<?xml version="1.0"?>
<div id="toc" class="toc">
 <h1>Table of Contents (by Author)</h1>
 <ul>
   <li>
     <a name="A">A</a>
     <ul>
       <li>
         <a href="#id91524">Adams, Douglas</a>
       </li>
       <li>
         <a href="#id91570">Anderson, Kevin J.</a>
       </li>
       <li>
         <a href="#id91578">Anthony, Piers</a>
       </li>
       <li>
         <a href="#id91588">Archer, Jeffrey</a>
       </li>
       <li>
         <a href="#id91597">Baldacci, David</a>
       </li>
     </ul>
   </li>
   <li>
     <a name="B">B</a>
     <ul>
       <li>
         <a href="#id91607">Ball, Margaret</a>
       </li>
       <li>
         <a href="#id91617">Bradley, Marion Zimmer</a>
       </li>
     </ul>
   </li>
   <li>
     <a name="C">C</a>
     <ul>
       <li>
         <a href="#id91627">Carcaterra, Lorenzo</a>
       </li>
       <li>
         <a href="#id93622">Card, Orson Scott</a>
       </li>
       <li>
         <a href="#id93633">Chalker, Jack L.</a>
       </li>
     </ul>
   </li>
   <li>
     <a name="D">D</a>
     <ul>
       <li>
         <a href="#id93643">Dahl, Roald</a>
       </li>
       <li>
         <a href="#id93653">Daley, Brian</a>
       </li>
       <li>
         <a href="#id93663">Dann, Jack</a>
       </li>
     </ul>
   </li>
 </ul>
</div>


I've tried some XPath 2 stuff and XQuery. I can get a list of first letters using XQuery (and thus XPath 2)

For example: (file fl.xq)

for $a in //author/name/substring(@file-as,1,1)
return
<c>{$a}</c>


Generates a list of the characters of the last name (although not unique).


I tried embedding something like the above "for $a in.." into an XSLT
2.0 stylesheet, and assign it to a variable, but I get an error from
saxon when I tried it.

Something like this is desired.... (with UNIQUE-SET-OF-FIRST-LETTERS)
replaced with something that works.  I set this to XSLT 2, and tried
"$letters//l" in place of that place-holder text
(UNIQUE-SET-OF-FIRST-LETTERS).  It generated the Letter items A B C
.., but all of the sub <ul>s where empty.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output method="xml"/>
 <xsl:output indent="yes"/>
 <xsl:strip-space elements="*"/>

<xsl:key name="alet" match="//author" use="substring(name/@file-as,1,1)"/>

<!--
 <xsl:variable name="letters">
   <l>A</l>
   <l>B</l>
   <l>C</l>
   <l>D</l>
   <l>E</l>
 </xsl:variable>
-->
 <xsl:template match="/booklist">
   <xsl:call-template name="gen-toc"/>
 </xsl:template>

 <!-- Generate Table of Contents -->
 <xsl:template name="gen-toc">
   <div id="toc" class="toc">
     <h1>Table of Contents (by Author)</h1>
     <ul>
       <xsl:for-each select="UNIQUE-SET-OF-FIRST-LETTERS">
         <xsl:variable name="lc" select="."/>
         <li>
           <a>
             <xsl:attribute name="name" select="$lc"/>
             <xsl:value-of select="$lc"/>
           </a>
           <ul>
             <xsl:for-each select="key('alet',$lc)">
               <xsl:sort select="name/@file-as"/>
               <li>
                 <a href="#{generate-id(.)}">
                   <xsl:value-of select="name/@file-as"/>
                 </a>
               </li>
             </xsl:for-each>
           </ul>
         </li>
       </xsl:for-each>
     </ul>
   </div>
 </xsl:template>
</xsl:stylesheet>

Hopefully, I didn't include too much detail.

Any help appreciated. Thanks.

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.