[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] glossary sorting/indexing question


Subject: [xsl] glossary sorting/indexing question
From: "Trevor Nicholls" <trevor@xxxxxxxxxxxxxxxxxx>
Date: Tue, 20 May 2008 23:35:06 +1200

Hello

I am putting together some xsl tools to produce and maintain a glossary, and
although I have an initial working solution I don't believe it is written
very efficiently. I would like to identify issues in the way I am tackling
it before I add more complexity.

In the following simplified example the source document has sections which
are to be ordered by title (case insensitive), and grouped by the initial
letter of that title. Each initial "generates" a heading which is followed
by a subheading which shows the range of entries for that initial, followed
by the title of each entry in a separate paragraph. Of course in the real
application the output is put together a bit differently but this stylesheet
illustrates how I am determining the glossary structure.

It seems to me that there are far too many <for-each/sort> constructs in
this solution, for one thing. Are there feasible improvements I should make?

The xsl file says version 2.0. I believe it is only using 1.0 features, and
it runs in Saxon if I declare it as version 1.0, but it only runs in XMLSpy
if it is given version 2.0. XMLSpy complains about the key definition, but
that's not a big concern.

I'm not that au fait with XSL version 2.0 but I suspect that it is probably
a lot neater for this kind of job. Even in 1.0 I'm sure there is a better
way of coding the stylesheet which follows.

XML document (shortgloss.xml):
------
<?xml version="1.0" encoding="UTF-8"?>
<document>
 <title>Glossary</title>
 <section>
  <title>Benefit</title>
  <para>blah blah.</para>
 </section>
 <section>
  <title>Access mode</title>
  <para>blah blah.</para>
 </section>
 <section>
  <title>ACRONYM</title>
  <para>blah blah.</para>
 </section>
 <section>
  <title>Alice</title>
  <para>blah blah.</para>
 </section>
 <section>
  <title>bridging</title>
  <para>blah blah.</para>
 </section>
 <section>
  <title>Access</title>
  <para>blah blah.</para>
 </section>
</document>

Stylesheet (shortgloss.xsl):
------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp "&#160;">]>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="html" encoding="us-ascii" indent="no"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
doctype-system="http://www.w3.org/TR/html4/loose.dtd" />

<!-- constants -->
<xsl:variable name="upchars" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:variable name="lochars" select="'abcdefghijklmnopqrstuvwxyz'" />

<!-- subhead key -->
<xsl:key name="subhead" match="/document/section"
use="translate(substring(./title,1,1),$lochars,$upchars)" />

<xsl:template match="/document">
<html>
<head><title><xsl:apply-templates select="title" /></title></head>
<body>
  <h1><xsl:apply-templates select="title" /></h1>
  <xsl:for-each select="/document/section[count(. |
key('subhead',translate(substring(./title,1,1),$lochars,$upchars))[1]) =
1]">
	<xsl:sort select="translate(./title,$lochars,$upchars)" />
	<xsl:variable name="initial"
select="translate(substring(./title,1,1),$lochars,$upchars)" />
	<a name="{$initial}" />
	<h2><xsl:value-of select="$initial" /></h2>
	<h4>
	  <xsl:for-each select="key('subhead',$initial)">
		<xsl:sort select="translate(./title,$lochars,$upchars)" />
		<xsl:if test="position()=1">
		  <xsl:value-of select="./title" />
		</xsl:if>
	  </xsl:for-each>
	  <xsl:text> - </xsl:text>
	  <xsl:for-each select="key('subhead',$initial)">
		<xsl:sort select="translate(./title,$lochars,$upchars)" />
		<xsl:if test="position()=last()">
		  <xsl:value-of select="./title" />
		</xsl:if>
	  </xsl:for-each>
	</h4>
	<xsl:for-each select="key('subhead',$initial)">
	  <xsl:sort select="translate(./title,$lochars,$upchars)" />
	  <p><xsl:apply-templates select="."/></p>
	</xsl:for-each>
  </xsl:for-each>
</body>
</html>
</xsl:template>

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

<xsl:template match="title">
  <xsl:value-of select="." />
</xsl:template>

</xsl:stylesheet>

Thanks for any advice
Trevor


Current Thread
Keywords