1<?xml version="1.0"?>
2<!DOCTYPE xsl:stylesheet [
3
4<!ENTITY lowercase "'abcdefghijklmnopqrstuvwxyz'">
5<!ENTITY uppercase "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'">
6
7<!ENTITY primary   'normalize-space(concat(primary/@sortas, primary[not(@sortas) or @sortas = ""]))'>
8<!ENTITY secondary 'normalize-space(concat(secondary/@sortas, secondary[not(@sortas) or @sortas = ""]))'>
9<!ENTITY tertiary  'normalize-space(concat(tertiary/@sortas, tertiary[not(@sortas) or @sortas = ""]))'>
10
11
12<!ENTITY section   '(ancestor-or-self::set
13                     |ancestor-or-self::book
14                     |ancestor-or-self::part
15                     |ancestor-or-self::reference
16                     |ancestor-or-self::partintro
17                     |ancestor-or-self::chapter
18                     |ancestor-or-self::appendix
19                     |ancestor-or-self::preface
20                     |ancestor-or-self::article
21                     |ancestor-or-self::section
22                     |ancestor-or-self::sect1
23                     |ancestor-or-self::sect2
24                     |ancestor-or-self::sect3
25                     |ancestor-or-self::sect4
26                     |ancestor-or-self::sect5
27                     |ancestor-or-self::refentry
28                     |ancestor-or-self::refsect1
29                     |ancestor-or-self::refsect2
30                     |ancestor-or-self::refsect3
31                     |ancestor-or-self::simplesect
32                     |ancestor-or-self::bibliography
33                     |ancestor-or-self::glossary
34                     |ancestor-or-self::index
35                     |ancestor-or-self::webpage)[last()]'>
36
37<!ENTITY section.id 'generate-id(&section;)'>
38<!ENTITY sep '" "'>
39<!-- Documents using the kimber index method must have a lang attribute -->
40<!-- Only one of these should be present in the entity -->
41
42<!ENTITY lang 'concat(/*/@lang, /*/@xml:lang, "en")'>
43<!ENTITY scope 'count(ancestor::node()|$scope) = count(ancestor::node())
44                and ($role = @role or $type = @type or
45                (string-length($role) = 0 and string-length($type) = 0))'>
46]>
47<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
48                xmlns:i="urn:cz-kosek:functions:index"
49                xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"
50                xmlns:func="http://exslt.org/functions"
51                xmlns:k="java:com.isogen.saxoni18n.Saxoni18nService"
52                xmlns:exslt="http://exslt.org/common"
53                extension-element-prefixes="func exslt"
54                exclude-result-prefixes="func exslt i l k"
55                version="1.0">
56
57<!-- ********************************************************************
58     $Id: autoidx.xsl,v 1.28 2006/05/15 22:42:46 bobstayton Exp $
59     ********************************************************************
60
61     This file is part of the XSL DocBook Stylesheet distribution.
62     See /README or http://nwalsh.com/docbook/xsl/ for copyright
63     and other information.
64
65     ******************************************************************** -->
66
67<!-- ==================================================================== -->
68<!-- The "english" method derived from Jeni Tennison's work. -->
69<!-- The "kosek" method contributed by Jirka Kosek. -->
70<!-- The "kimber" method contributed by Eliot Kimber of Innodata Isogen. -->
71
72<xsl:key name="letter"
73         match="indexterm"
74         use="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
75
76<xsl:key name="primary"
77         match="indexterm"
78         use="&primary;"/>
79
80<xsl:key name="secondary"
81         match="indexterm"
82         use="concat(&primary;, &sep;, &secondary;)"/>
83
84<xsl:key name="tertiary"
85         match="indexterm"
86         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
87
88<xsl:key name="endofrange"
89         match="indexterm[@class='endofrange']"
90         use="@startref"/>
91
92<xsl:key name="primary-section"
93         match="indexterm[not(secondary) and not(see)]"
94         use="concat(&primary;, &sep;, &section.id;)"/>
95
96<xsl:key name="secondary-section"
97         match="indexterm[not(tertiary) and not(see)]"
98         use="concat(&primary;, &sep;, &secondary;, &sep;, &section.id;)"/>
99
100<xsl:key name="tertiary-section"
101         match="indexterm[not(see)]"
102         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, &section.id;)"/>
103
104<xsl:key name="see-also"
105         match="indexterm[seealso]"
106         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso)"/>
107
108<xsl:key name="see"
109         match="indexterm[see]"
110         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see)"/>
111
112<xsl:key name="sections" match="*[@id]" use="@id"/>
113
114<!-- The following key is used in the kimber indexing method.
115     To use this method, either copy this key to a
116     customization layer, or xsl:import common/autoidx.xsl. -->
117<!--
118<xsl:key name="k-group"
119         match="indexterm"
120         use="k:getIndexGroupKey(&lang;, &primary;)"/>
121-->
122
123
124<xsl:template name="generate-index">
125  <xsl:param name="scope" select="(ancestor::book|/)[last()]"/>
126
127  <xsl:choose>
128    <xsl:when test="$index.method = 'kosek'">
129      <xsl:call-template name="generate-kosek-index">
130        <xsl:with-param name="scope" select="$scope"/>
131      </xsl:call-template>
132    </xsl:when>
133    <xsl:when test="$index.method = 'kimber'">
134      <xsl:call-template name="generate-kimber-index">
135        <xsl:with-param name="scope" select="$scope"/>
136      </xsl:call-template>
137    </xsl:when>
138
139    <xsl:otherwise>
140      <xsl:call-template name="generate-english-index">
141        <xsl:with-param name="scope" select="$scope"/>
142      </xsl:call-template>
143    </xsl:otherwise>
144  </xsl:choose>
145</xsl:template>
146      
147<xsl:template name="generate-english-index">
148  <xsl:param name="scope" select="NOTANODE"/>
149
150  <xsl:variable name="role">
151    <xsl:if test="$index.on.role != 0">
152      <xsl:value-of select="@role"/>
153    </xsl:if>
154  </xsl:variable>
155
156  <xsl:variable name="type">
157    <xsl:if test="$index.on.type != 0">
158      <xsl:value-of select="@type"/>
159    </xsl:if>
160  </xsl:variable>
161
162  <xsl:variable name="terms"
163                select="//indexterm
164                        [count(.|key('letter',
165                          translate(substring(&primary;, 1, 1),
166                             &lowercase;,
167                             &uppercase;))
168                          [&scope;][1]) = 1
169                          and not(@class = 'endofrange')]"/>
170
171  <xsl:variable name="alphabetical"
172                select="$terms[contains(concat(&lowercase;, &uppercase;),
173                                        substring(&primary;, 1, 1))]"/>
174
175  <xsl:variable name="others" select="$terms[not(contains(concat(&lowercase;,
176                                                 &uppercase;),
177                                             substring(&primary;, 1, 1)))]"/>
178  <div class="index">
179    <xsl:if test="$others">
180      <div class="indexdiv">
181        <h3>
182          <xsl:call-template name="gentext">
183            <xsl:with-param name="key" select="'index symbols'"/>
184          </xsl:call-template>
185        </h3>
186        <dl>
187          <xsl:apply-templates select="$others[count(.|key('primary',
188                                       &primary;)[&scope;][1]) = 1]"
189                               mode="index-symbol-div">
190            <xsl:with-param name="position" select="position()"/>                                
191            <xsl:with-param name="scope" select="$scope"/>
192            <xsl:with-param name="role" select="$role"/>
193            <xsl:with-param name="type" select="$type"/>
194            <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
195          </xsl:apply-templates>
196        </dl>
197      </div>
198    </xsl:if>
199
200    <xsl:apply-templates select="$alphabetical[count(.|key('letter',
201                                 translate(substring(&primary;, 1, 1),
202                                           &lowercase;,&uppercase;))[&scope;][1]) = 1]"
203                         mode="index-div-english">
204      <xsl:with-param name="position" select="position()"/>
205      <xsl:with-param name="scope" select="$scope"/>
206      <xsl:with-param name="role" select="$role"/>
207      <xsl:with-param name="type" select="$type"/>
208      <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
209    </xsl:apply-templates>
210  </div>
211</xsl:template>
212
213<xsl:template name="generate-kosek-index">
214  <xsl:param name="scope" select="(ancestor::book|/)[last()]"/>
215
216  <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
217  <xsl:if test="contains($vendor, 'libxslt')">
218    <xsl:message terminate="yes">
219      <xsl:text>ERROR: the 'kosek' index method does not </xsl:text>
220      <xsl:text>work with the xsltproc XSLT processor.</xsl:text>
221    </xsl:message>
222  </xsl:if>
223
224
225  <xsl:if test="not(function-available('exslt:node-set'))">
226    <xsl:message terminate="yes">
227      <xsl:text>ERROR: the 'kosek' index method requires the </xsl:text>
228      <xsl:text>exslt:node-set() function. Use a processor that </xsl:text>
229      <xsl:text>has it, or use a different index method.</xsl:text>
230    </xsl:message>
231  </xsl:if>
232
233  <xsl:if test="not(function-available('i:group-index'))">
234    <xsl:message terminate="yes">
235      <xsl:text>ERROR: the 'kosek' index method requires the&#xA;</xsl:text>
236      <xsl:text>index extension functions be imported:&#xA;</xsl:text>
237      <xsl:text>  xsl:import href="common/autoidx-ng.xsl"</xsl:text>
238    </xsl:message>
239  </xsl:if>
240
241  <xsl:variable name="role">
242    <xsl:if test="$index.on.role != 0">
243      <xsl:value-of select="@role"/>
244    </xsl:if>
245  </xsl:variable>
246
247  <xsl:variable name="type">
248    <xsl:if test="$index.on.type != 0">
249      <xsl:value-of select="@type"/>
250    </xsl:if>
251  </xsl:variable>
252
253  <xsl:variable name="terms"
254                select="//indexterm[count(.|key('group-code',
255                                          i:group-index(&primary;))
256                                          [&scope;][1]) = 1
257                                    and not(@class = 'endofrange')]"/>
258
259  <div class="index">
260    <xsl:apply-templates select="$terms" mode="index-div-kosek">
261      <xsl:with-param name="scope" select="$scope"/>
262      <xsl:with-param name="role" select="$role"/>
263      <xsl:with-param name="type" select="$type"/>
264      <xsl:sort select="i:group-index(&primary;)" data-type="number"/>
265    </xsl:apply-templates>
266  </div>
267</xsl:template>
268
269<xsl:template name="generate-kimber-index">
270  <xsl:param name="scope" select="NOTANODE"/>
271
272  <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
273  <xsl:if test="not(contains($vendor, 'SAXON '))">
274    <xsl:message terminate="yes">
275      <xsl:text>ERROR: the 'kimber' index method requires the </xsl:text>
276      <xsl:text>Saxon version 6 XSLT processor.</xsl:text>
277    </xsl:message>
278  </xsl:if>
279
280  <xsl:if test="not(function-available('k:getIndexGroupKey'))">
281    <xsl:message terminate="yes">
282      <xsl:text>ERROR: the 'kimber' index method requires the </xsl:text>
283      <xsl:text>Innodata Isogen &#x0A;Java extensions for </xsl:text>
284      <xsl:text>internationalized indexes. &#x0A;Install those </xsl:text>
285      <xsl:text>extensions, or use a different index method.&#x0A;</xsl:text>
286      <xsl:text>For more information, see:&#x0A;</xsl:text>
287      <xsl:text>http://www.innodata-isogen.com/knowledge_center/tools_downloads/i18nsupport</xsl:text>
288    </xsl:message>
289  </xsl:if>
290
291  <xsl:if test="not(function-available('i:group-index'))">
292    <xsl:message terminate="yes">
293      <xsl:text>ERROR: the 'kimber' index method requires the&#xA;</xsl:text>
294      <xsl:text>index extension functions be imported:&#xA;</xsl:text>
295      <xsl:text>  xsl:import href="common/autoidx-ng.xsl"</xsl:text>
296    </xsl:message>
297  </xsl:if>
298
299  <xsl:variable name="role">
300    <xsl:if test="$index.on.role != 0">
301      <xsl:value-of select="@role"/>
302    </xsl:if>
303  </xsl:variable>
304
305  <xsl:variable name="type">
306    <xsl:if test="$index.on.type != 0">
307      <xsl:value-of select="@type"/>
308    </xsl:if>
309  </xsl:variable>
310
311  <xsl:variable name="terms"
312                select="//indexterm[count(.|key('k-group',
313                   k:getIndexGroupKey(&lang;, &primary;))
314                   [&scope;][1]) = 1
315                   and not(@class = 'endofrange')]"/>
316
317  <xsl:variable name="alphabetical"
318                select="$terms[not(starts-with(
319                k:getIndexGroupKey(&lang;, &primary;),
320                '#NUMERIC'
321                ))]"/>
322
323  <xsl:variable name="others"
324                select="$terms[starts-with(
325                k:getIndexGroupKey(&lang;, &primary;),
326                '#NUMERIC'
327                )]"/>
328
329  <div class="index">
330    <xsl:if test="$others">
331      <div class="indexdev">
332        <h3>
333          <xsl:call-template name="gentext">
334            <xsl:with-param name="key" select="'index symbols'"/>
335          </xsl:call-template>
336        </h3>
337        <dl>
338          <xsl:apply-templates select="$others"
339                               mode="index-symbol-div">
340            <xsl:with-param name="scope" select="$scope"/>
341            <xsl:with-param name="role" select="$role"/>
342            <xsl:with-param name="type" select="$type"/>
343            <xsl:sort lang="&lang;"
344                select="k:getIndexGroupSortKey(&lang;,
345                        k:getIndexGroupKey(&lang;, &primary;))"/>
346          </xsl:apply-templates>
347        </dl>
348      </div>
349    </xsl:if>
350
351    <xsl:apply-templates select="$alphabetical"
352                         mode="index-div-kimber">
353      <xsl:with-param name="scope" select="$scope"/>
354      <xsl:with-param name="role" select="$role"/>
355      <xsl:with-param name="type" select="$type"/>
356      <xsl:sort lang="&lang;"
357             select="k:getIndexGroupSortKey(&lang;,
358                     k:getIndexGroupKey(&lang;, &primary;))"/>
359    </xsl:apply-templates>
360  </div>
361
362</xsl:template>
363
364<xsl:template match="indexterm" mode="index-div-english">
365  <xsl:param name="scope" select="."/>
366  <xsl:param name="role" select="''"/>
367  <xsl:param name="type" select="''"/>
368
369  <xsl:variable name="key"
370                select="translate(substring(&primary;, 1, 1),
371                         &lowercase;,&uppercase;)"/>
372
373  <xsl:if test="key('letter', $key)[&scope;]
374                [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
375    <div class="indexdiv">
376      <xsl:if test="contains(concat(&lowercase;, &uppercase;), $key)">
377        <h3>
378          <xsl:value-of select="translate($key, &lowercase;, &uppercase;)"/>
379        </h3>
380      </xsl:if>
381      <dl>
382        <xsl:apply-templates select="key('letter', $key)[&scope;]
383                                     [count(.|key('primary', &primary;)
384                                     [&scope;][1])=1]"
385                             mode="index-primary">
386          <xsl:with-param name="position" select="position()"/>
387          <xsl:with-param name="scope" select="$scope"/>
388          <xsl:with-param name="role" select="$role"/>
389          <xsl:with-param name="type" select="$type"/>
390          <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
391        </xsl:apply-templates>
392      </dl>
393    </div>
394  </xsl:if>
395</xsl:template>
396
397<xsl:template match="indexterm" mode="index-symbol-div">
398  <xsl:param name="scope" select="/"/>
399  <xsl:param name="role" select="''"/>
400  <xsl:param name="type" select="''"/>
401
402  <xsl:variable name="key" select="translate(substring(&primary;, 1, 1),
403                                             &lowercase;,&uppercase;)"/>
404
405  <xsl:apply-templates select="key('letter', $key)
406                               [&scope;][count(.|key('primary', &primary;)[1]) = 1]"
407                       mode="index-primary">
408    <xsl:with-param name="position" select="position()"/>
409    <xsl:with-param name="scope" select="$scope"/>
410    <xsl:with-param name="role" select="$role"/>
411    <xsl:with-param name="type" select="$type"/>
412    <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
413  </xsl:apply-templates>
414</xsl:template>
415
416<xsl:template match="indexterm" mode="index-div-kosek">
417  <xsl:param name="scope" select="."/>
418  <xsl:param name="role" select="''"/>
419  <xsl:param name="type" select="''"/>
420
421  <xsl:variable name="key"
422                select="i:group-index(&primary;)"/>
423
424  <xsl:variable name="lang">
425    <xsl:call-template name="l10n.language"/>
426  </xsl:variable>
427
428  <xsl:if test="key('group-code', $key)[&scope;]
429                [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
430    <div class="indexdiv">
431      <h3>
432        <xsl:value-of select="i:group-letter($key)"/>
433      </h3>
434      <dl>
435        <xsl:apply-templates select="key('group-code', $key)[&scope;]
436                                     [count(.|key('primary', &primary;)[&scope;][1])=1]"
437                             mode="index-primary">
438          <xsl:sort select="&primary;" lang="{$lang}"/>
439          <xsl:with-param name="scope" select="$scope"/>
440          <xsl:with-param name="role" select="$role"/>
441          <xsl:with-param name="type" select="$type"/>
442        </xsl:apply-templates>
443      </dl>
444    </div>
445  </xsl:if>
446</xsl:template>
447
448<xsl:template match="indexterm" mode="index-div-kimber">
449  <xsl:param name="scope" select="."/>
450  <xsl:param name="role" select="''"/>
451  <xsl:param name="type" select="''"/>
452
453  <xsl:variable name="key"
454          select="k:getIndexGroupKey(&lang;, &primary;)"/>
455
456  <xsl:variable name="label"
457          select="k:getIndexGroupLabel(&lang;, $key)"/>
458
459  <xsl:if test="key('k-group', $label)[&scope;]
460                [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
461    <div class="indexdiv">
462      <h3>
463        <xsl:value-of select="$label"/>
464      </h3>
465      <dl>
466        <xsl:apply-templates select="key('k-group', $key)[&scope;]
467                            [count(.|key('primary', &primary;)[&scope;]
468                            [1])=1]"
469                             mode="index-primary">
470          <xsl:sort select="&primary;" lang="&lang;"/>
471          <xsl:with-param name="scope" select="$scope"/>
472          <xsl:with-param name="role" select="$role"/>
473          <xsl:with-param name="type" select="$type"/>
474        </xsl:apply-templates>
475      </dl>
476    </div>
477  </xsl:if>
478</xsl:template>
479
480<xsl:template match="indexterm" mode="index-primary">
481  <xsl:param name="scope" select="."/>
482  <xsl:param name="role" select="''"/>
483  <xsl:param name="type" select="''"/>
484
485  <xsl:variable name="key" select="&primary;"/>
486  <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
487  <dt>
488    <xsl:value-of select="primary"/>
489    <xsl:for-each select="$refs[generate-id() = generate-id(key('primary-section', concat($key, &sep;, &section.id;))[&scope;][1])]">
490      <xsl:apply-templates select="." mode="reference">
491        <xsl:with-param name="position" select="position()"/>
492        <xsl:with-param name="scope" select="$scope"/>
493        <xsl:with-param name="role" select="$role"/>
494        <xsl:with-param name="type" select="$type"/>
495      </xsl:apply-templates>
496    </xsl:for-each>
497
498    <xsl:if test="$refs[not(secondary)]/*[self::see]">
499      <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[&scope;][1])]"
500                           mode="index-see">
501        <xsl:with-param name="position" select="position()"/>
502        <xsl:with-param name="scope" select="$scope"/>
503        <xsl:with-param name="role" select="$role"/>
504        <xsl:with-param name="type" select="$type"/>
505        <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
506      </xsl:apply-templates>
507    </xsl:if>
508  </dt>
509  <xsl:if test="$refs/secondary or $refs[not(secondary)]/*[self::seealso]">
510    <dd>
511      <dl>
512        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[&scope;][1])]"
513                             mode="index-seealso">
514          <xsl:with-param name="position" select="position()"/>
515          <xsl:with-param name="scope" select="$scope"/>
516          <xsl:with-param name="role" select="$role"/>
517          <xsl:with-param name="type" select="$type"/>
518          <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
519        </xsl:apply-templates>
520        <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]" 
521                             mode="index-secondary">
522          <xsl:with-param name="position" select="position()"/>
523          <xsl:with-param name="scope" select="$scope"/>
524          <xsl:with-param name="role" select="$role"/>
525          <xsl:with-param name="type" select="$type"/>
526          <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
527        </xsl:apply-templates>
528      </dl>
529    </dd>
530  </xsl:if>
531</xsl:template>
532
533<xsl:template match="indexterm" mode="index-secondary">
534  <xsl:param name="scope" select="."/>
535  <xsl:param name="role" select="''"/>
536  <xsl:param name="type" select="''"/>
537
538  <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;)"/>
539  <xsl:variable name="refs" select="key('secondary', $key)[&scope;]"/>
540  <dt>
541    <xsl:value-of select="secondary"/>
542    <xsl:for-each select="$refs[generate-id() = generate-id(key('secondary-section', concat($key, &sep;, &section.id;))[&scope;][1])]">
543      <xsl:apply-templates select="." mode="reference">
544        <xsl:with-param name="position" select="position()"/>
545        <xsl:with-param name="scope" select="$scope"/>
546        <xsl:with-param name="role" select="$role"/>
547        <xsl:with-param name="type" select="$type"/>
548      </xsl:apply-templates>
549    </xsl:for-each>
550
551    <xsl:if test="$refs[not(tertiary)]/*[self::see]">
552      <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, see))[&scope;][1])]"
553                           mode="index-see">
554        <xsl:with-param name="position" select="position()"/>
555        <xsl:with-param name="scope" select="$scope"/>
556        <xsl:with-param name="role" select="$role"/>
557        <xsl:with-param name="type" select="$type"/>
558        <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
559      </xsl:apply-templates>
560    </xsl:if>
561  </dt>
562  <xsl:if test="$refs/tertiary or $refs[not(tertiary)]/*[self::seealso]">
563    <dd>
564      <dl>
565        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, seealso))[&scope;][1])]"
566                             mode="index-seealso">
567          <xsl:with-param name="position" select="position()"/>
568          <xsl:with-param name="scope" select="$scope"/>
569          <xsl:with-param name="role" select="$role"/>
570          <xsl:with-param name="type" select="$type"/>
571          <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
572        </xsl:apply-templates>
573        <xsl:apply-templates select="$refs[tertiary and count(.|key('tertiary', concat($key, &sep;, &tertiary;))[&scope;][1]) = 1]" 
574                             mode="index-tertiary">
575          <xsl:with-param name="position" select="position()"/>
576          <xsl:with-param name="scope" select="$scope"/>
577          <xsl:with-param name="role" select="$role"/>
578          <xsl:with-param name="type" select="$type"/>
579          <xsl:sort select="translate(&tertiary;, &lowercase;, &uppercase;)"/>
580        </xsl:apply-templates>
581      </dl>
582    </dd>
583  </xsl:if>
584</xsl:template>
585
586<xsl:template match="indexterm" mode="index-tertiary">
587  <xsl:param name="scope" select="."/>
588  <xsl:param name="role" select="''"/>
589  <xsl:param name="type" select="''"/>
590
591  <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
592  <xsl:variable name="refs" select="key('tertiary', $key)[&scope;]"/>
593  <dt>
594    <xsl:value-of select="tertiary"/>
595    <xsl:for-each select="$refs[generate-id() = generate-id(key('tertiary-section', concat($key, &sep;, &section.id;))[&scope;][1])]">
596      <xsl:apply-templates select="." mode="reference">
597        <xsl:with-param name="position" select="position()"/>
598        <xsl:with-param name="scope" select="$scope"/>
599        <xsl:with-param name="role" select="$role"/>
600        <xsl:with-param name="type" select="$type"/>
601      </xsl:apply-templates>
602    </xsl:for-each>
603
604    <xsl:if test="$refs/see">
605      <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see))[&scope;][1])]"
606                           mode="index-see">
607        <xsl:with-param name="position" select="position()"/>
608        <xsl:with-param name="scope" select="$scope"/>
609        <xsl:with-param name="role" select="$role"/>
610        <xsl:with-param name="type" select="$type"/>
611        <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
612      </xsl:apply-templates>
613    </xsl:if>
614  </dt>
615  <xsl:if test="$refs/seealso">
616    <dd>
617      <dl>
618        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso))[&scope;][1])]"
619                             mode="index-seealso">
620          <xsl:with-param name="position" select="position()"/>
621          <xsl:with-param name="scope" select="$scope"/>
622          <xsl:with-param name="role" select="$role"/>
623          <xsl:with-param name="type" select="$type"/>
624          <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
625        </xsl:apply-templates>
626      </dl>
627    </dd>
628  </xsl:if>
629</xsl:template>
630
631<xsl:template match="indexterm" mode="reference">
632  <xsl:param name="scope" select="."/>
633  <xsl:param name="role" select="''"/>
634  <xsl:param name="type" select="''"/>
635  <xsl:param name="position"/>
636  
637  <xsl:variable name="term.separator">
638    <xsl:call-template name="index.separator">
639      <xsl:with-param name="key" select="'index.term.separator'"/>
640    </xsl:call-template>
641  </xsl:variable>
642
643  <xsl:variable name="number.separator">
644    <xsl:call-template name="index.separator">
645      <xsl:with-param name="key" select="'index.number.separator'"/>
646    </xsl:call-template>
647  </xsl:variable>
648
649  <xsl:variable name="range.separator">
650    <xsl:call-template name="index.separator">
651      <xsl:with-param name="key" select="'index.range.separator'"/>
652    </xsl:call-template>
653  </xsl:variable>
654
655  <xsl:choose>
656    <xsl:when test="$position = 1">
657      <xsl:value-of select="$term.separator"/>
658    </xsl:when>
659    <xsl:otherwise>
660      <xsl:value-of select="$number.separator"/>
661    </xsl:otherwise>
662  </xsl:choose>
663
664  <xsl:choose>
665    <xsl:when test="@zone and string(@zone)">
666      <xsl:call-template name="reference">
667        <xsl:with-param name="zones" select="normalize-space(@zone)"/>
668        <xsl:with-param name="position" select="position()"/>
669        <xsl:with-param name="scope" select="$scope"/>
670        <xsl:with-param name="role" select="$role"/>
671        <xsl:with-param name="type" select="$type"/>
672      </xsl:call-template>
673    </xsl:when>
674    <xsl:otherwise>
675      <a>
676        <xsl:variable name="title">
677          <xsl:choose>
678            <xsl:when test="&section;/titleabbrev and $index.prefer.titleabbrev != 0">
679              <xsl:apply-templates select="&section;" mode="titleabbrev.markup"/>
680            </xsl:when>
681            <xsl:otherwise>
682              <xsl:apply-templates select="&section;" mode="title.markup"/>
683            </xsl:otherwise>
684          </xsl:choose>
685        </xsl:variable>
686
687        <xsl:attribute name="href">
688          <xsl:call-template name="href.target">
689            <xsl:with-param name="object" select="&section;"/>
690            <xsl:with-param name="context" select="//index[&scope;][1]"/>
691          </xsl:call-template>
692        </xsl:attribute>
693
694        <xsl:value-of select="$title"/> <!-- text only -->
695      </a>
696
697      <xsl:if test="key('endofrange', @id)[&scope;]">
698        <xsl:apply-templates select="key('endofrange', @id)[&scope;][last()]"
699                             mode="reference">
700          <xsl:with-param name="position" select="position()"/>
701          <xsl:with-param name="scope" select="$scope"/>
702          <xsl:with-param name="role" select="$role"/>
703          <xsl:with-param name="type" select="$type"/>
704          <xsl:with-param name="separator" select="$range.separator"/>
705        </xsl:apply-templates>
706      </xsl:if>
707    </xsl:otherwise>
708  </xsl:choose>
709</xsl:template>
710
711<xsl:template name="reference">
712  <xsl:param name="scope" select="."/>
713  <xsl:param name="role" select="''"/>
714  <xsl:param name="type" select="''"/>
715  <xsl:param name="zones"/>
716
717  <xsl:choose>
718    <xsl:when test="contains($zones, ' ')">
719      <xsl:variable name="zone" select="substring-before($zones, ' ')"/>
720      <xsl:variable name="target" select="key('sections', $zone)[&scope;]"/>
721
722      <a>
723        <xsl:attribute name="href">
724          <xsl:call-template name="href.target">
725            <xsl:with-param name="object" select="$target[1]"/>
726            <xsl:with-param name="context" select="//index[&scope;][1]"/>
727          </xsl:call-template>
728        </xsl:attribute>
729        <xsl:apply-templates select="$target[1]" mode="index-title-content"/>
730      </a>
731      <xsl:text>, </xsl:text>
732      <xsl:call-template name="reference">
733        <xsl:with-param name="zones" select="substring-after($zones, ' ')"/>
734        <xsl:with-param name="position" select="position()"/>
735        <xsl:with-param name="scope" select="$scope"/>
736        <xsl:with-param name="role" select="$role"/>
737        <xsl:with-param name="type" select="$type"/>
738      </xsl:call-template>
739    </xsl:when>
740    <xsl:otherwise>
741      <xsl:variable name="zone" select="$zones"/>
742      <xsl:variable name="target" select="key('sections', $zone)[&scope;]"/>
743
744      <a>
745        <xsl:attribute name="href">
746          <xsl:call-template name="href.target">
747            <xsl:with-param name="object" select="$target[1]"/>
748            <xsl:with-param name="context" select="//index[&scope;][1]"/>
749          </xsl:call-template>
750        </xsl:attribute>
751        <xsl:apply-templates select="$target[1]" mode="index-title-content"/>
752      </a>
753    </xsl:otherwise>
754  </xsl:choose>
755</xsl:template>
756
757<xsl:template match="indexterm" mode="index-see">
758  <xsl:param name="scope" select="."/>
759  <xsl:param name="role" select="''"/>
760  <xsl:param name="type" select="''"/>
761
762  <xsl:text> (</xsl:text>
763  <xsl:call-template name="gentext">
764    <xsl:with-param name="key" select="'see'"/>
765  </xsl:call-template>
766  <xsl:text> </xsl:text>
767  <xsl:value-of select="see"/>
768  <xsl:text>)</xsl:text>
769</xsl:template>
770
771<xsl:template match="indexterm" mode="index-seealso">
772  <xsl:param name="scope" select="."/>
773  <xsl:param name="role" select="''"/>
774  <xsl:param name="type" select="''"/>
775
776  <xsl:for-each select="seealso">
777    <xsl:sort select="translate(., &lowercase;, &uppercase;)"/>
778    <dt>
779    <xsl:text>(</xsl:text>
780    <xsl:call-template name="gentext">
781      <xsl:with-param name="key" select="'seealso'"/>
782    </xsl:call-template>
783    <xsl:text> </xsl:text>
784    <xsl:value-of select="."/>
785    <xsl:text>)</xsl:text>
786    </dt>
787  </xsl:for-each>
788</xsl:template>
789
790<xsl:template match="*" mode="index-title-content">
791  <xsl:variable name="title">
792    <xsl:apply-templates select="&section;" mode="title.markup"/>
793  </xsl:variable>
794
795  <xsl:value-of select="$title"/>
796</xsl:template>
797
798<xsl:template name="index.separator">
799  <xsl:param name="key" select="''"/>
800  <xsl:param name="lang">
801    <xsl:call-template name="l10n.language"/>
802  </xsl:param>
803
804  <xsl:choose>
805    <xsl:when test="$key = 'index.term.separator'">
806      <xsl:choose>
807        <!-- Use the override if not blank -->
808        <xsl:when test="$index.term.separator != ''">
809          <xsl:copy-of select="$index.term.separator"/>
810        </xsl:when>
811        <xsl:otherwise>
812          <xsl:call-template name="gentext.template">
813            <xsl:with-param name="lang" select="$lang"/>
814            <xsl:with-param name="context">index</xsl:with-param>
815            <xsl:with-param name="name">term-separator</xsl:with-param>
816          </xsl:call-template>
817        </xsl:otherwise>
818      </xsl:choose>
819    </xsl:when>
820    <xsl:when test="$key = 'index.number.separator'">
821      <xsl:choose>
822        <!-- Use the override if not blank -->
823        <xsl:when test="$index.number.separator != ''">
824          <xsl:copy-of select="$index.number.separator"/>
825        </xsl:when>
826        <xsl:otherwise>
827          <xsl:call-template name="gentext.template">
828            <xsl:with-param name="lang" select="$lang"/>
829            <xsl:with-param name="context">index</xsl:with-param>
830            <xsl:with-param name="name">number-separator</xsl:with-param>
831          </xsl:call-template>
832        </xsl:otherwise>
833      </xsl:choose>
834    </xsl:when>
835    <xsl:when test="$key = 'index.range.separator'">
836      <xsl:choose>
837        <!-- Use the override if not blank -->
838        <xsl:when test="$index.range.separator != ''">
839          <xsl:copy-of select="$index.range.separator"/>
840        </xsl:when>
841        <xsl:otherwise>
842          <xsl:call-template name="gentext.template">
843            <xsl:with-param name="lang" select="$lang"/>
844            <xsl:with-param name="context">index</xsl:with-param>
845            <xsl:with-param name="name">range-separator</xsl:with-param>
846          </xsl:call-template>
847        </xsl:otherwise>
848      </xsl:choose>
849    </xsl:when>
850  </xsl:choose>
851</xsl:template>
852
853</xsl:stylesheet>
854