1<?xml version="1.0"?> 2<!DOCTYPE xsl:stylesheet [ 3 4<!ENTITY lowercase "'abcdefghijklmnopqrstuvwxyz'"> 5<!ENTITY uppercase "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"> 6 7<!ENTITY primary 'concat(primary/@sortas, primary[not(@sortas)])'> 8<!ENTITY secondary 'concat(secondary/@sortas, secondary[not(@sortas)])'> 9<!ENTITY tertiary 'concat(tertiary/@sortas, tertiary[not(@sortas)])'> 10 11<!ENTITY section '(ancestor-or-self::set 12 |ancestor-or-self::book 13 |ancestor-or-self::part 14 |ancestor-or-self::reference 15 |ancestor-or-self::partintro 16 |ancestor-or-self::chapter 17 |ancestor-or-self::appendix 18 |ancestor-or-self::preface 19 |ancestor-or-self::section 20 |ancestor-or-self::sect1 21 |ancestor-or-self::sect2 22 |ancestor-or-self::sect3 23 |ancestor-or-self::sect4 24 |ancestor-or-self::sect5 25 |ancestor-or-self::refsect1 26 |ancestor-or-self::refsect2 27 |ancestor-or-self::refsect3 28 |ancestor-or-self::simplesect 29 |ancestor-or-self::bibliography 30 |ancestor-or-self::glossary 31 |ancestor-or-self::index)[last()]'> 32 33<!ENTITY section.id 'generate-id(§ion;)'> 34<!ENTITY sep '" "'> 35]> 36<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 37 version="1.0"> 38 39<xsl:import href="docbook.xsl"/> 40 41<!-- ==================================================================== --> 42<!-- Jeni Tennison gets all the credit for what follows. 43 I think I understand it :-) Anyway, I've hacked it a bit, so the 44 bugs are mine. --> 45 46<xsl:key name="letter" 47 match="indexterm" 48 use="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/> 49 50<xsl:key name="primary" 51 match="indexterm" 52 use="&primary;"/> 53 54<xsl:key name="secondary" 55 match="indexterm" 56 use="concat(&primary;, &sep;, &secondary;)"/> 57 58<xsl:key name="tertiary" 59 match="indexterm" 60 use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/> 61 62<xsl:key name="primary-section" 63 match="indexterm[not(secondary) and not(see)]" 64 use="concat(&primary;, &sep;, §ion.id;)"/> 65 66<xsl:key name="secondary-section" 67 match="indexterm[not(tertiary) and not(see)]" 68 use="concat(&primary;, &sep;, &secondary;, &sep;, §ion.id;)"/> 69 70<xsl:key name="tertiary-section" 71 match="indexterm[not(see)]" 72 use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, §ion.id;)"/> 73 74<xsl:key name="see-also" 75 match="indexterm[seealso]" 76 use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso)"/> 77 78<xsl:key name="see" 79 match="indexterm[see]" 80 use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see)"/> 81 82<xsl:key name="sections" match="*[@id]" use="@id"/> 83 84<xsl:template name="generate-index"> 85 <xsl:variable name="terms" select="//indexterm[count(.|key('letter', 86 translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;))[1]) = 1]"/> 87 88 <xsl:variable name="alphabetical" 89 select="$terms[contains(concat(&lowercase;, &uppercase;), 90 substring(&primary;, 1, 1))]"/> 91 <xsl:variable name="others" select="$terms[not(contains(concat(&lowercase;, 92 &uppercase;), 93 substring(&primary;, 1, 1)))]"/> 94 <div class="index"> 95 <xsl:if test="$others"> 96 <div class="indexdiv"> 97 <h3> 98 <xsl:call-template name="gentext"> 99 <xsl:with-param name="key" select="'index symbols'"/> 100 </xsl:call-template> 101 </h3> 102 <dl> 103 <xsl:apply-templates select="$others[count(.|key('primary', 104 &primary;)[1]) = 1]" 105 mode="index-primary"> 106 <xsl:sort select="&primary;"/> 107 </xsl:apply-templates> 108 </dl> 109 </div> 110 </xsl:if> 111 <xsl:apply-templates select="$alphabetical[count(.|key('letter', 112 translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;))[1]) = 1]" 113 mode="index-div"> 114 <xsl:sort select="&primary;"/> 115 </xsl:apply-templates> 116 </div> 117</xsl:template> 118 119<xsl:template match="indexterm" mode="index-div"> 120 <xsl:variable name="key" select="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/> 121 <div class="indexdiv"> 122 <h3> 123 <xsl:value-of select="translate($key, &lowercase;, &uppercase;)"/> 124 </h3> 125 <dl> 126 <xsl:apply-templates select="key('letter', $key)[count(.|key('primary', &primary;)[1]) = 1]" 127 mode="index-primary"> 128 <xsl:sort select="&primary;"/> 129 </xsl:apply-templates> 130 </dl> 131 </div> 132</xsl:template> 133 134<xsl:template match="indexterm" mode="index-primary"> 135 <xsl:variable name="key" select="&primary;"/> 136 <xsl:variable name="refs" select="key('primary', $key)"/> 137 <dt> 138 <xsl:value-of select="primary"/> 139 <xsl:for-each select="$refs[generate-id() = generate-id(key('primary-section', concat($key, &sep;, §ion.id;))[1])]"> 140 <xsl:apply-templates select="." mode="reference"/> 141 </xsl:for-each> 142 </dt> 143 <xsl:if test="$refs/secondary or $refs[not(secondary)]/*[self::see or self::seealso]"> 144 <dd> 145 <dl> 146 <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[1])]" 147 mode="index-see"> 148 <xsl:sort select="see"/> 149 </xsl:apply-templates> 150 <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[1])]" 151 mode="index-seealso"> 152 <xsl:sort select="seealso"/> 153 </xsl:apply-templates> 154 <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[1]) = 1]" 155 mode="index-secondary"> 156 <xsl:sort select="&secondary;"/> 157 </xsl:apply-templates> 158 </dl> 159 </dd> 160 </xsl:if> 161</xsl:template> 162 163<xsl:template match="indexterm" mode="index-secondary"> 164 <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;)"/> 165 <xsl:variable name="refs" select="key('secondary', $key)"/> 166 <dt> 167 <xsl:value-of select="secondary"/> 168 <xsl:for-each select="$refs[generate-id() = generate-id(key('secondary-section', concat($key, &sep;, §ion.id;))[1])]"> 169 <xsl:apply-templates select="." mode="reference"/> 170 </xsl:for-each> 171 </dt> 172 <xsl:if test="$refs/tertiary or $refs[not(tertiary)]/*[self::see or self::seealso]"> 173 <dd> 174 <dl> 175 <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, see))[1])]" 176 mode="index-see"> 177 <xsl:sort select="see"/> 178 </xsl:apply-templates> 179 <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, seealso))[1])]" 180 mode="index-seealso"> 181 <xsl:sort select="seealso"/> 182 </xsl:apply-templates> 183 <xsl:apply-templates select="$refs[tertiary and count(.|key('tertiary', concat($key, &sep;, &tertiary;))[1]) = 1]" 184 mode="index-tertiary"> 185 <xsl:sort select="&tertiary;"/> 186 </xsl:apply-templates> 187 </dl> 188 </dd> 189 </xsl:if> 190</xsl:template> 191 192<xsl:template match="indexterm" mode="index-tertiary"> 193 <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/> 194 <xsl:variable name="refs" select="key('tertiary', $key)"/> 195 <dt> 196 <xsl:value-of select="tertiary"/> 197 <xsl:for-each select="$refs[generate-id() = generate-id(key('tertiary-section', concat($key, &sep;, §ion.id;))[1])]"> 198 <xsl:apply-templates select="." mode="reference"/> 199 </xsl:for-each> 200 </dt> 201 <xsl:variable name="see" select="$refs/see | $refs/seealso"/> 202 <xsl:if test="$see"> 203 <dd> 204 <dl> 205 <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see))[1])]" 206 mode="index-see"> 207 <xsl:sort select="see"/> 208 </xsl:apply-templates> 209 <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso))[1])]" 210 mode="index-seealso"> 211 <xsl:sort select="seealso"/> 212 </xsl:apply-templates> 213 </dl> 214 </dd> 215 </xsl:if> 216</xsl:template> 217 218<xsl:template match="indexterm" mode="reference"> 219 <xsl:text>, </xsl:text> 220 <xsl:choose> 221 <xsl:when test="@zone and string(@zone)"> 222 <xsl:call-template name="reference"> 223 <xsl:with-param name="zones" select="normalize-space(@zone)"/> 224 </xsl:call-template> 225 </xsl:when> 226 <xsl:otherwise> 227 <a> 228 <xsl:variable name="title"> 229 <xsl:apply-templates select="§ion;" mode="title.markup"/> 230 </xsl:variable> 231 232 <xsl:attribute name="href"> 233 <xsl:call-template name="href.target"> 234 <xsl:with-param name="object" select="§ion;"/> 235 </xsl:call-template> 236 </xsl:attribute> 237 238 <xsl:value-of select="$title"/> <!-- text only --> 239 </a> 240 </xsl:otherwise> 241 </xsl:choose> 242</xsl:template> 243 244<xsl:template name="reference"> 245 <xsl:param name="zones"/> 246 <xsl:choose> 247 <xsl:when test="contains($zones, ' ')"> 248 <xsl:variable name="zone" select="substring-before($zones, ' ')"/> 249 <xsl:variable name="target" select="key('sections', $zone)"/> 250 251 <a> 252 <xsl:attribute name="href"> 253 <xsl:call-template name="href.target"> 254 <xsl:with-param name="object" select="$target[1]"/> 255 </xsl:call-template> 256 </xsl:attribute> 257 <xsl:apply-templates select="$target[1]" mode="index-title-content"/> 258 </a> 259 <xsl:text>, </xsl:text> 260 <xsl:call-template name="reference"> 261 <xsl:with-param name="zones" select="substring-after($zones, ' ')"/> 262 </xsl:call-template> 263 </xsl:when> 264 <xsl:otherwise> 265 <xsl:variable name="zone" select="$zones"/> 266 <xsl:variable name="target" select="key('sections', $zone)"/> 267 268 <a> 269 <xsl:attribute name="href"> 270 <xsl:call-template name="href.target"> 271 <xsl:with-param name="object" select="$target[1]"/> 272 </xsl:call-template> 273 </xsl:attribute> 274 <xsl:apply-templates select="$target[1]" mode="index-title-content"/> 275 </a> 276 </xsl:otherwise> 277 </xsl:choose> 278</xsl:template> 279 280<xsl:template match="indexterm" mode="index-see"> 281 <dt><xsl:value-of select="see"/></dt> 282</xsl:template> 283 284<xsl:template match="indexterm" mode="index-seealso"> 285 <dt><xsl:value-of select="seealso"/></dt> 286</xsl:template> 287 288<xsl:template match="*" mode="index-title-content"> 289 <xsl:variable name="title"> 290 <xsl:apply-templates select="§ion;" mode="title.markup"/> 291 </xsl:variable> 292 293 <xsl:value-of select="$title"/> 294</xsl:template> 295 296</xsl:stylesheet> 297