Subject: Re: [xsl] XSLT/XPath Question (Grouping Authors by First Character of Last Name) From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx> Date: Sat, 3 Mar 2007 19:24:48 -0800 |
Perfect. Thanks. Just out of curiosity, is this possible (practical?) in XSLT 1.0?
Actually, this reminds me that six years ago I published a snippet in topxml.com solving exactly your problem in XSLT 1.0:
-- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence. --------------------------------------- To invent, you need a good imagination and a pile of junk ------------------------------------- You've achieved success in your field when you don't know whether what you're doing is work or play
Perfect. Thanks. Just out of curiosity, is this possible (practical?) in XSLT 1.0?
On 3/3/07, Dimitre Novatchev <dnovatchev@xxxxxxxxx> wrote: > You are not using XSLT 2.0 to its full potential. > > The solution is as easy as this: > > <xsl:stylesheet version="2.0" > xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > > > <xsl:output method="text"/> > > <xsl:template match="/"> > <xsl:for-each-group select="*/author" > group-by="substring(name/@file-as,1,1)" > > > <xsl:text>

</xsl:text> > <xsl:value-of select="current-grouping-key()"/> > <xsl:text>
</xsl:text> > > <xsl:for-each select="current-group()"> > <xsl:value-of select="name/@file-as"/> > <xsl:text>
</xsl:text> > </xsl:for-each> > </xsl:for-each-group> > </xsl:template> > </xsl:stylesheet> > > and when applied on the provided xml document it produces the wanted result: > > > > A > Adams, Douglas > Anderson, Kevin J. > Anthony, Piers > Archer, Jeffrey > > > B > Baldacci, David > Ball, Margaret > Bradley, Marion Zimmer > > > C > Carcaterra, Lorenzo > Card, Orson Scott > Chalker, Jack L. > > > D > Dahl, Roald > Daley, Brian > Dann, Jack > > > > -- > Cheers, > Dimitre Novatchev > --------------------------------------- > Truly great madness cannot be achieved without significant intelligence. > --------------------------------------- > To invent, you need a good imagination and a pile of junk > ------------------------------------- > You've achieved success in your field when you don't know whether what > you're doing is work or play > > > > > On 3/3/07, Kevin Grover <kevin@xxxxxxxxxxxxxxx> wrote: > > 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 |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSLT/XPath Question (Grou, Kevin Grover | Thread | Re: [xsl] XSLT/XPath Question (Grou, Kevin Grover |
Re: [xsl] XSLT/XPath Question (Grou, Kevin Grover | Date | Re: [xsl] XSLT/XPath Question (Grou, G. Ken Holman |
Month |