Imported Upstream version 1.79.2
[platform/upstream/docbook-xsl-stylesheets.git] / fo / autoidx.xsl
1 <?xml version="1.0"?>
2 <!DOCTYPE xsl:stylesheet [
3 <!ENTITY % common.entities SYSTEM "../common/entities.ent">
4 %common.entities;
5 ]>
6 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
7                 xmlns:d="http://docbook.org/ns/docbook"
8                 xmlns:fo="http://www.w3.org/1999/XSL/Format"
9                 xmlns:rx="http://www.renderx.com/XSL/Extensions"
10                 xmlns:xlink='http://www.w3.org/1999/xlink'
11                 xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
12                 xmlns:exslt="http://exslt.org/common"
13                 extension-element-prefixes="exslt"
14                 exclude-result-prefixes="exslt d"
15                 version="1.0">
16
17 <!-- ********************************************************************
18
19      This file is part of the DocBook XSL Stylesheet distribution.
20      See ../README or http://cdn.docbook.org/release/xsl/ for copyright
21      copyright and other information.
22
23      ******************************************************************** -->
24
25 <!-- ==================================================================== -->
26 <!-- The "basic" method derived from Jeni Tennison's work. -->
27 <!-- The "kosek" method contributed by Jirka Kosek. -->
28 <!-- The "kimber" method contributed by Eliot Kimber of Innodata Isogen. -->
29
30 <!-- Importing module for kimber or kosek method overrides one of these -->
31 <xsl:param name="kimber.imported" select="0"/>
32 <xsl:param name="kosek.imported" select="0"/>
33
34 <!-- These keys used primary in all methods -->
35 <xsl:key name="letter"
36          match="d:indexterm"
37          use="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
38
39 <xsl:key name="primary"
40          match="d:indexterm"
41          use="&primary;"/>
42
43 <xsl:key name="primaryonly"
44          match="d:indexterm"
45          use="normalize-space(d:primary)"/>
46
47 <xsl:key name="secondary"
48          match="d:indexterm"
49          use="concat(&primary;, &sep;, &secondary;)"/>
50
51 <xsl:key name="tertiary"
52          match="d:indexterm"
53          use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
54
55 <xsl:key name="endofrange"
56          match="d:indexterm[@class='endofrange']"
57          use="@startref"/>
58
59 <xsl:key name="see-also"
60          match="d:indexterm[d:seealso]"
61          use="concat(&primary;, &sep;, 
62                      &secondary;, &sep;, 
63                      &tertiary;, &sep;, d:seealso)"/>
64
65 <xsl:key name="see"
66          match="d:indexterm[d:see]"
67          use="concat(&primary;, &sep;, 
68                      &secondary;, &sep;, 
69                      &tertiary;, &sep;, d:see)"/>
70
71
72 <xsl:template name="generate-index">
73   <xsl:param name="scope" select="(ancestor::d:book|/)[last()]"/>
74
75   <xsl:choose>
76     <xsl:when test="$index.method = 'kosek'">
77       <xsl:call-template name="generate-kosek-index">
78         <xsl:with-param name="scope" select="$scope"/>
79       </xsl:call-template>
80     </xsl:when>
81     <xsl:when test="$index.method = 'kimber'">
82       <xsl:call-template name="generate-kimber-index">
83         <xsl:with-param name="scope" select="$scope"/>
84       </xsl:call-template>
85     </xsl:when>
86
87     <xsl:otherwise>
88       <xsl:call-template name="generate-basic-index">
89         <xsl:with-param name="scope" select="$scope"/>
90       </xsl:call-template>
91     </xsl:otherwise>
92   </xsl:choose>
93 </xsl:template>
94       
95 <xsl:template name="generate-basic-index">
96   <xsl:param name="scope" select="NOTANODE"/>
97
98   <xsl:variable name="role">
99     <xsl:if test="$index.on.role != 0">
100       <xsl:value-of select="@role"/>
101     </xsl:if>
102   </xsl:variable>
103
104   <xsl:variable name="type">
105     <xsl:if test="$index.on.type != 0">
106       <xsl:value-of select="@type"/>
107     </xsl:if>
108   </xsl:variable>
109
110   <xsl:variable name="terms"
111                 select="//d:indexterm
112                         [count(.|key('letter',
113                           translate(substring(&primary;, 1, 1),
114                              &lowercase;,
115                              &uppercase;))
116                           [&scope;][1]) = 1
117                           and not(@class = 'endofrange')]"/>
118
119   <xsl:variable name="alphabetical"
120                 select="$terms[contains(concat(&lowercase;, &uppercase;),
121                                         substring(&primary;, 1, 1))]"/>
122
123   <xsl:variable name="others" select="$terms[not(contains(
124                                         concat(&lowercase;,
125                                         &uppercase;),
126                                         substring(&primary;, 1, 1)))]"/>
127   <fo:block>
128     <xsl:if test="$others">
129       <xsl:call-template name="indexdiv.title">
130         <xsl:with-param name="titlecontent">
131           <xsl:call-template name="gentext">
132             <xsl:with-param name="key" select="'index symbols'"/>
133           </xsl:call-template>
134         </xsl:with-param>
135       </xsl:call-template>
136
137       <fo:block>
138         <xsl:apply-templates select="$others[count(.|key('primary',
139                                      &primary;)[&scope;][1]) = 1]"
140                              mode="index-symbol-div">
141           <xsl:with-param name="scope" select="$scope"/>
142           <xsl:with-param name="role" select="$role"/>
143           <xsl:with-param name="type" select="$type"/>
144           <xsl:sort select="translate(&primary;, &lowercase;, 
145                             &uppercase;)"/>
146         </xsl:apply-templates>
147       </fo:block>
148     </xsl:if>
149
150     <xsl:apply-templates select="$alphabetical[count(.|key('letter',
151                                  translate(substring(&primary;, 1, 1),
152                                            &lowercase;,&uppercase;))
153                                            [&scope;][1]) = 1]"
154                          mode="index-div-basic">
155       <xsl:with-param name="scope" select="$scope"/>
156       <xsl:with-param name="role" select="$role"/>
157       <xsl:with-param name="type" select="$type"/>
158       <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
159     </xsl:apply-templates>
160   </fo:block>
161 </xsl:template>
162
163 <!-- This template not used if fo/autoidx-kosek.xsl is imported -->
164 <xsl:template name="generate-kosek-index">
165   <xsl:param name="scope" select="NOTANODE"/>
166
167   <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
168   <xsl:if test="contains($vendor, 'libxslt')">
169     <xsl:message terminate="yes">
170       <xsl:text>ERROR: the 'kosek' index method does not </xsl:text>
171       <xsl:text>work with the xsltproc XSLT processor.</xsl:text>
172     </xsl:message>
173   </xsl:if>
174
175
176   <xsl:if test="$exsl.node.set.available = 0">
177     <xsl:message terminate="yes">
178       <xsl:text>ERROR: the 'kosek' index method requires the </xsl:text>
179       <xsl:text>exslt:node-set() function. Use a processor that </xsl:text>
180       <xsl:text>has it, or use a different index method.</xsl:text>
181     </xsl:message>
182   </xsl:if>
183
184   <xsl:if test="$kosek.imported = 0">
185     <xsl:message terminate="yes">
186       <xsl:text>ERROR: the 'kosek' index method requires the&#xA;</xsl:text>
187       <xsl:text>kosek index extensions be imported:&#xA;</xsl:text>
188       <xsl:text>  xsl:import href="fo/autoidx-kosek.xsl"</xsl:text>
189     </xsl:message>
190   </xsl:if>
191
192 </xsl:template>
193
194
195 <!-- This template not used if fo/autoidx-kimber.xsl is imported -->
196 <xsl:template name="generate-kimber-index">
197   <xsl:param name="scope" select="NOTANODE"/>
198
199   <xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
200   <xsl:if test="not(contains($vendor, 'SAXON '))">
201     <xsl:message terminate="yes">
202       <xsl:text>ERROR: the 'kimber' index method requires the </xsl:text>
203       <xsl:text>Saxon version 6 or 8 XSLT processor.</xsl:text>
204     </xsl:message>
205   </xsl:if>
206
207   <xsl:if test="$kimber.imported = 0">
208     <xsl:message terminate="yes">
209       <xsl:text>ERROR: the 'kimber' index method requires the&#xA;</xsl:text>
210       <xsl:text>kimber index extensions be imported:&#xA;</xsl:text>
211       <xsl:text>  xsl:import href="fo/autoidx-kimber.xsl"</xsl:text>
212     </xsl:message>
213   </xsl:if>
214
215 </xsl:template>
216
217 <xsl:template match="d:indexterm" mode="index-div-basic">
218   <xsl:param name="scope" select="."/>
219   <xsl:param name="role" select="''"/>
220   <xsl:param name="type" select="''"/>
221
222   <xsl:variable name="key"
223                 select="translate(substring(&primary;, 1, 1),
224                          &lowercase;,&uppercase;)"/>
225
226   <xsl:if test="key('letter', $key)[&scope;]
227                 [count(.|key('primary', &primary;)[&scope;][1]) = 1]">
228     <fo:block>
229       <xsl:if test="contains(concat(&lowercase;, &uppercase;), $key)">
230         <xsl:call-template name="indexdiv.title">
231           <xsl:with-param name="titlecontent">
232             <xsl:value-of select="translate($key, &lowercase;, &uppercase;)"/>
233           </xsl:with-param>
234         </xsl:call-template>
235       </xsl:if>
236       <fo:block xsl:use-attribute-sets="index.entry.properties">
237         <xsl:apply-templates select="key('letter', $key)[&scope;]
238                                      [count(.|key('primary', &primary;)
239                                      [&scope;][1])=1]"
240                              mode="index-primary">
241           <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
242           <xsl:with-param name="scope" select="$scope"/>
243           <xsl:with-param name="role" select="$role"/>
244           <xsl:with-param name="type" select="$type"/>
245         </xsl:apply-templates>
246       </fo:block>
247     </fo:block>
248   </xsl:if>
249 </xsl:template>
250
251 <xsl:template match="d:indexterm" mode="index-symbol-div">
252   <xsl:param name="scope" select="."/>
253   <xsl:param name="role" select="''"/>
254   <xsl:param name="type" select="''"/>
255
256   <xsl:variable name="key"
257                 select="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
258
259   <fo:block xsl:use-attribute-sets="index.entry.properties">
260     <xsl:apply-templates select="key('letter', $key)[&scope;][count(.|key('primary', &primary;)[&scope;][1]) = 1]"
261                          mode="index-primary">
262       <xsl:with-param name="scope" select="$scope"/>
263       <xsl:with-param name="role" select="$role"/>
264       <xsl:with-param name="type" select="$type"/>
265       <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
266     </xsl:apply-templates>
267   </fo:block>
268 </xsl:template>
269
270 <xsl:template match="d:indexterm" mode="index-primary">
271   <xsl:param name="scope" select="."/>
272   <xsl:param name="role" select="''"/>
273   <xsl:param name="type" select="''"/>
274
275   <xsl:variable name="key" select="&primary;"/>
276   <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
277
278   <xsl:variable name="term.separator">
279     <xsl:call-template name="index.separator">
280       <xsl:with-param name="key" select="'index.term.separator'"/>
281     </xsl:call-template>
282   </xsl:variable>
283
284   <xsl:variable name="range.separator">
285     <xsl:call-template name="index.separator">
286       <xsl:with-param name="key" select="'index.range.separator'"/>
287     </xsl:call-template>
288   </xsl:variable>
289
290   <xsl:variable name="number.separator">
291     <xsl:call-template name="index.separator">
292       <xsl:with-param name="key" select="'index.number.separator'"/>
293     </xsl:call-template>
294   </xsl:variable>
295
296   <fo:block>
297     <xsl:if test="$autolink.index.see != 0">
298       <xsl:attribute name="id">
299         <xsl:value-of select="concat('ientry-', generate-id())"/>
300       </xsl:attribute>
301     </xsl:if>
302     <xsl:if test="$axf.extensions != 0">
303       <xsl:attribute name="axf:suppress-duplicate-page-number">true</xsl:attribute>
304     </xsl:if>
305
306     <xsl:for-each select="$refs/d:primary">
307       <xsl:if test="@id or @xml:id">
308         <fo:inline id="{(@id|@xml:id)[1]}"/>
309       </xsl:if>
310     </xsl:for-each>
311
312     <xsl:value-of select="d:primary"/>
313
314     <xsl:choose>
315       <xsl:when test="$xep.extensions != 0">
316         <xsl:if test="$refs[not(d:see) and not(d:secondary)]">
317           <xsl:copy-of select="$term.separator"/>
318           <xsl:variable name="primary" select="&primary;"/>
319           <xsl:variable name="primary.significant" select="concat(&primary;, $significant.flag)"/>
320           <rx:page-index list-separator="{$number.separator}"
321                          range-separator="{$range.separator}">
322             <xsl:if test="$refs[@significance='preferred'][not(d:see) and not(d:secondary)]">
323               <rx:index-item xsl:use-attribute-sets="index.preferred.page.properties xep.index.item.properties"
324                 ref-key="{$primary.significant}"/>
325             </xsl:if>
326             <xsl:if test="$refs[not(@significance) or @significance!='preferred'][not(d:see) and not(d:secondary)]">
327               <rx:index-item xsl:use-attribute-sets="xep.index.item.properties"
328                 ref-key="{$primary}"/>
329             </xsl:if>
330           </rx:page-index>        
331         </xsl:if>
332       </xsl:when>
333       <xsl:otherwise>
334         <xsl:variable name="page-number-citations">
335           <xsl:for-each select="$refs[not(d:see)
336                                 and not(d:secondary)]">
337             <xsl:apply-templates select="." mode="reference">
338               <xsl:with-param name="scope" select="$scope"/>
339               <xsl:with-param name="role" select="$role"/>
340               <xsl:with-param name="type" select="$type"/>
341               <xsl:with-param name="position" select="position()"/>
342             </xsl:apply-templates>
343           </xsl:for-each>
344         </xsl:variable>
345
346         <xsl:copy-of select="$page-number-citations"/>
347       </xsl:otherwise>
348     </xsl:choose>
349
350     <xsl:if test="$refs[not(d:secondary)]/*[self::d:see]">
351       <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, d:see))[&scope;][1])]"
352                            mode="index-see">
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 select="translate(d:see, &lowercase;, &uppercase;)"/>
357       </xsl:apply-templates>
358     </xsl:if>
359
360   </fo:block>
361
362   <xsl:if test="$refs/d:secondary or $refs[not(d:secondary)]/*[self::d:seealso]">
363     <fo:block start-indent="1pc">
364       <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, d:seealso))[&scope;][1])]"
365                            mode="index-seealso">
366          <xsl:with-param name="scope" select="$scope"/>
367          <xsl:with-param name="role" select="$role"/>
368          <xsl:with-param name="type" select="$type"/>
369          <xsl:sort select="translate(d:seealso, &lowercase;, &uppercase;)"/>
370       </xsl:apply-templates>
371       <xsl:apply-templates select="$refs[d:secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]"
372                            mode="index-secondary">
373        <xsl:with-param name="scope" select="$scope"/>
374        <xsl:with-param name="role" select="$role"/>
375        <xsl:with-param name="type" select="$type"/>
376        <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
377       </xsl:apply-templates>
378     </fo:block>
379   </xsl:if>
380 </xsl:template>
381
382 <xsl:template match="d:indexterm" mode="index-secondary">
383   <xsl:param name="scope" select="."/>
384   <xsl:param name="role" select="''"/>
385   <xsl:param name="type" select="''"/>
386
387   <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;)"/>
388   <xsl:variable name="refs" select="key('secondary', $key)[&scope;]"/>
389
390   <xsl:variable name="term.separator">
391     <xsl:call-template name="index.separator">
392       <xsl:with-param name="key" select="'index.term.separator'"/>
393     </xsl:call-template>
394   </xsl:variable>
395
396   <xsl:variable name="range.separator">
397     <xsl:call-template name="index.separator">
398       <xsl:with-param name="key" select="'index.range.separator'"/>
399     </xsl:call-template>
400   </xsl:variable>
401
402   <xsl:variable name="number.separator">
403     <xsl:call-template name="index.separator">
404       <xsl:with-param name="key" select="'index.number.separator'"/>
405     </xsl:call-template>
406   </xsl:variable>
407
408   <fo:block>
409     <xsl:if test="$axf.extensions != 0">
410       <xsl:attribute name="axf:suppress-duplicate-page-number">true</xsl:attribute>
411     </xsl:if>
412
413     <xsl:for-each select="$refs/d:secondary">
414       <xsl:if test="@id or @xml:id">
415         <fo:inline id="{(@id|@xml:id)[1]}"/>
416       </xsl:if>
417     </xsl:for-each>
418
419     <xsl:value-of select="d:secondary"/>
420
421     <xsl:choose>
422       <xsl:when test="$xep.extensions != 0">
423         <xsl:if test="$refs[not(d:see) and not(d:tertiary)]">
424           <xsl:copy-of select="$term.separator"/>
425           <xsl:variable name="primary" select="&primary;"/>
426           <xsl:variable name="secondary" select="&secondary;"/>
427           <xsl:variable name="primary.significant" select="concat(&primary;, $significant.flag)"/>
428           <rx:page-index list-separator="{$number.separator}"
429                          range-separator="{$range.separator}">
430             <xsl:if test="$refs[@significance='preferred'][not(d:see) and not(d:tertiary)]">
431               <rx:index-item xsl:use-attribute-sets="index.preferred.page.properties xep.index.item.properties">
432                 <xsl:attribute name="ref-key">
433                   <xsl:value-of select="$primary.significant"/>
434                   <xsl:text>, </xsl:text>
435                   <xsl:value-of select="$secondary"/>
436                 </xsl:attribute>
437               </rx:index-item>
438             </xsl:if>
439             <xsl:if test="$refs[not(@significance) or @significance!='preferred'][not(d:see) and not(d:tertiary)]">
440               <rx:index-item xsl:use-attribute-sets="xep.index.item.properties">
441                 <xsl:attribute name="ref-key">
442                   <xsl:value-of select="$primary"/>
443                   <xsl:text>, </xsl:text>
444                   <xsl:value-of select="$secondary"/>
445                 </xsl:attribute>
446               </rx:index-item>
447             </xsl:if>
448           </rx:page-index>
449         </xsl:if>
450       </xsl:when>
451       <xsl:otherwise>
452         <xsl:variable name="page-number-citations">
453           <xsl:for-each select="$refs[not(d:see)
454                                 and not(d:tertiary)]">
455             <xsl:apply-templates select="." mode="reference">
456               <xsl:with-param name="scope" select="$scope"/>
457               <xsl:with-param name="role" select="$role"/>
458               <xsl:with-param name="type" select="$type"/>
459               <xsl:with-param name="position" select="position()"/>
460             </xsl:apply-templates>
461           </xsl:for-each>
462         </xsl:variable>
463
464         <xsl:copy-of select="$page-number-citations"/>
465       </xsl:otherwise>
466     </xsl:choose>
467
468     <xsl:if test="$refs[not(d:tertiary)]/*[self::d:see]">
469       <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, d:see))[&scope;][1])]"
470                            mode="index-see">
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:sort select="translate(d:see, &lowercase;, &uppercase;)"/>
475       </xsl:apply-templates>
476     </xsl:if>
477
478   </fo:block>
479
480   <xsl:if test="$refs/d:tertiary or $refs[not(d:tertiary)]/*[self::d:seealso]">
481     <fo:block start-indent="2pc">
482       <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, d:seealso))[&scope;][1])]"
483                            mode="index-seealso">
484           <xsl:with-param name="scope" select="$scope"/>
485           <xsl:with-param name="role" select="$role"/>
486           <xsl:with-param name="type" select="$type"/>
487           <xsl:sort select="translate(d:seealso, &lowercase;, &uppercase;)"/>
488       </xsl:apply-templates>
489       <xsl:apply-templates select="$refs[d:tertiary and count(.|key('tertiary', concat($key, &sep;, &tertiary;))[&scope;][1]) = 1]"
490                            mode="index-tertiary">
491           <xsl:with-param name="scope" select="$scope"/>
492           <xsl:with-param name="role" select="$role"/>
493           <xsl:with-param name="type" select="$type"/>
494           <xsl:sort select="translate(&tertiary;, &lowercase;, &uppercase;)"/>
495       </xsl:apply-templates>
496     </fo:block>
497   </xsl:if>
498 </xsl:template>
499
500 <xsl:template match="d:indexterm" mode="index-tertiary">
501   <xsl:param name="scope" select="."/>
502   <xsl:param name="role" select="''"/>
503   <xsl:param name="type" select="''"/>
504   <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
505   <xsl:variable name="refs" select="key('tertiary', $key)[&scope;]"/>
506
507   <xsl:variable name="term.separator">
508     <xsl:call-template name="index.separator">
509       <xsl:with-param name="key" select="'index.term.separator'"/>
510     </xsl:call-template>
511   </xsl:variable>
512
513   <xsl:variable name="range.separator">
514     <xsl:call-template name="index.separator">
515       <xsl:with-param name="key" select="'index.range.separator'"/>
516     </xsl:call-template>
517   </xsl:variable>
518
519   <xsl:variable name="number.separator">
520     <xsl:call-template name="index.separator">
521       <xsl:with-param name="key" select="'index.number.separator'"/>
522     </xsl:call-template>
523   </xsl:variable>
524
525   <fo:block>
526     <xsl:if test="$axf.extensions != 0">
527       <xsl:attribute name="axf:suppress-duplicate-page-number">true</xsl:attribute>
528     </xsl:if>
529
530     <xsl:for-each select="$refs/d:tertiary">
531       <xsl:if test="@id or @xml:id">
532         <fo:inline id="{(@id|@xml:id)[1]}"/>
533       </xsl:if>
534     </xsl:for-each>
535
536     <xsl:value-of select="d:tertiary"/>
537
538     <xsl:choose>
539       <xsl:when test="$xep.extensions != 0">
540         <xsl:if test="$refs[not(d:see)]">
541           <xsl:copy-of select="$term.separator"/>
542           <xsl:variable name="primary" select="&primary;"/>
543           <xsl:variable name="secondary" select="&secondary;"/>
544           <xsl:variable name="tertiary" select="&tertiary;"/>
545           <xsl:variable name="primary.significant" select="concat(&primary;, $significant.flag)"/>
546           <rx:page-index list-separator="{$number.separator}"
547                          range-separator="{$range.separator}">
548             <xsl:if test="$refs[@significance='preferred'][not(d:see)]">
549               <rx:index-item xsl:use-attribute-sets="index.preferred.page.properties xep.index.item.properties">
550                 <xsl:attribute name="ref-key">
551                   <xsl:value-of select="$primary.significant"/>
552                   <xsl:text>, </xsl:text>
553                   <xsl:value-of select="$secondary"/>
554                   <xsl:text>, </xsl:text>
555                   <xsl:value-of select="$tertiary"/>
556                 </xsl:attribute>
557               </rx:index-item>
558             </xsl:if>
559             <xsl:if test="$refs[not(@significance) or @significance!='preferred'][not(d:see)]">
560               <rx:index-item xsl:use-attribute-sets="xep.index.item.properties">
561                 <xsl:attribute name="ref-key">
562                   <xsl:value-of select="$primary"/>
563                   <xsl:text>, </xsl:text>
564                   <xsl:value-of select="$secondary"/>
565                   <xsl:text>, </xsl:text>
566                   <xsl:value-of select="$tertiary"/>
567                 </xsl:attribute>
568               </rx:index-item>
569             </xsl:if>
570           </rx:page-index>
571         </xsl:if>
572       </xsl:when>
573       <xsl:otherwise>
574         <xsl:variable name="page-number-citations">
575           <xsl:for-each select="$refs[not(d:see)]">
576             <xsl:apply-templates select="." mode="reference">
577               <xsl:with-param name="scope" select="$scope"/>
578               <xsl:with-param name="role" select="$role"/>
579               <xsl:with-param name="type" select="$type"/>
580               <xsl:with-param name="position" select="position()"/>
581             </xsl:apply-templates>
582           </xsl:for-each>
583         </xsl:variable>
584
585         <xsl:copy-of select="$page-number-citations"/>
586       </xsl:otherwise>
587     </xsl:choose>
588
589     <xsl:if test="$refs/d:see">
590       <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, d:see))[&scope;][1])]"
591                            mode="index-see">
592         <xsl:with-param name="scope" select="$scope"/>
593         <xsl:with-param name="role" select="$role"/>
594         <xsl:with-param name="type" select="$type"/>
595         <xsl:sort select="translate(d:see, &lowercase;, &uppercase;)"/>
596       </xsl:apply-templates>
597     </xsl:if>
598
599   </fo:block>
600
601   <xsl:if test="$refs/d:seealso">
602     <fo:block>
603       <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, d:seealso))[&scope;][1])]"
604                            mode="index-seealso">
605         <xsl:with-param name="scope" select="$scope"/>
606         <xsl:with-param name="role" select="$role"/>
607         <xsl:with-param name="type" select="$type"/>
608         <xsl:sort select="translate(d:seealso, &lowercase;, &uppercase;)"/>
609       </xsl:apply-templates>
610     </fo:block>
611   </xsl:if>
612 </xsl:template>
613
614 <xsl:template match="d:indexterm" mode="reference">
615   <xsl:param name="scope" select="."/>
616   <xsl:param name="role" select="''"/>
617   <xsl:param name="type" select="''"/>
618   <xsl:param name="position" select="0"/>
619   <xsl:param name="separator" select="''"/>
620
621   <xsl:variable name="term.separator">
622     <xsl:call-template name="index.separator">
623       <xsl:with-param name="key" select="'index.term.separator'"/>
624     </xsl:call-template>
625   </xsl:variable>
626
627   <xsl:variable name="range.separator">
628     <xsl:call-template name="index.separator">
629       <xsl:with-param name="key" select="'index.range.separator'"/>
630     </xsl:call-template>
631   </xsl:variable>
632
633   <xsl:variable name="number.separator">
634     <xsl:call-template name="index.separator">
635       <xsl:with-param name="key" select="'index.number.separator'"/>
636     </xsl:call-template>
637   </xsl:variable>
638
639   <xsl:choose>
640     <xsl:when test="$separator != ''">
641       <xsl:value-of select="$separator"/>
642     </xsl:when>
643     <xsl:when test="$position = 1">
644       <xsl:value-of select="$term.separator"/>
645     </xsl:when>
646     <xsl:otherwise>
647       <xsl:value-of select="$number.separator"/>
648     </xsl:otherwise>
649   </xsl:choose>
650
651   <xsl:choose>
652     <xsl:when test="@zone and string(@zone)">
653       <xsl:call-template name="reference">
654         <xsl:with-param name="zones" select="normalize-space(@zone)"/>
655         <xsl:with-param name="scope" select="$scope"/>
656         <xsl:with-param name="role" select="$role"/>
657         <xsl:with-param name="type" select="$type"/>
658       </xsl:call-template>
659     </xsl:when>
660     <xsl:when test="ancestor::*[contains(local-name(),'info') and not(starts-with(local-name(),'info'))]">
661       <xsl:call-template name="info.reference">
662         <xsl:with-param name="scope" select="$scope"/>
663         <xsl:with-param name="role" select="$role"/>
664         <xsl:with-param name="type" select="$type"/>
665       </xsl:call-template>
666     </xsl:when>
667     <xsl:otherwise>
668       <xsl:variable name="id">
669         <xsl:call-template name="object.id"/>
670       </xsl:variable>
671
672       <fo:basic-link internal-destination="{$id}"
673                      xsl:use-attribute-sets="index.page.number.properties">
674         <fo:page-number-citation ref-id="{$id}"/>
675       </fo:basic-link>
676
677       <xsl:if test="key('endofrange', $id)[&scope;]">
678         <xsl:apply-templates select="key('endofrange', $id)[&scope;][last()]"
679                              mode="reference">
680           <xsl:with-param name="scope" select="$scope"/>
681           <xsl:with-param name="role" select="$role"/>
682           <xsl:with-param name="type" select="$type"/>
683           <xsl:with-param name="separator" select="$range.separator"/>
684         </xsl:apply-templates>
685       </xsl:if>
686     </xsl:otherwise>
687   </xsl:choose>
688 </xsl:template>
689
690 <xsl:template name="reference">
691   <xsl:param name="scope" select="."/>
692   <xsl:param name="role" select="''"/>
693   <xsl:param name="type" select="''"/>
694   <xsl:param name="zones"/>
695
696   <xsl:variable name="number.separator">
697     <xsl:call-template name="index.separator">
698       <xsl:with-param name="key" select="'index.number.separator'"/>
699     </xsl:call-template>
700   </xsl:variable>
701
702   <xsl:choose>
703     <xsl:when test="contains($zones, ' ')">
704       <xsl:variable name="zone" select="substring-before($zones, ' ')"/>
705       <xsl:variable name="target" select="key('id', $zone)"/>
706
707       <xsl:variable name="id">
708         <xsl:call-template name="object.id">
709            <xsl:with-param name="object" select="$target[1]"/>
710         </xsl:call-template>
711       </xsl:variable>
712
713       <fo:basic-link internal-destination="{$id}"
714                      xsl:use-attribute-sets="index.page.number.properties">
715         <fo:page-number-citation ref-id="{$id}"/>
716       </fo:basic-link>
717
718       <xsl:copy-of select="$number.separator"/>
719       <xsl:call-template name="reference">
720         <xsl:with-param name="zones" select="substring-after($zones, ' ')"/>
721         <xsl:with-param name="scope" select="$scope"/>
722         <xsl:with-param name="role" select="$role"/>
723         <xsl:with-param name="type" select="$type"/>
724       </xsl:call-template>
725     </xsl:when>
726     <xsl:otherwise>
727       <xsl:variable name="zone" select="$zones"/>
728       <xsl:variable name="target" select="key('id', $zone)"/>
729
730       <xsl:variable name="id">
731         <xsl:call-template name="object.id">
732           <xsl:with-param name="object" select="$target[1]"/>
733         </xsl:call-template>
734       </xsl:variable>
735
736       <fo:basic-link internal-destination="{$id}"
737                      xsl:use-attribute-sets="index.page.number.properties">
738         <fo:page-number-citation ref-id="{$id}"/>
739       </fo:basic-link>
740     </xsl:otherwise>
741   </xsl:choose>
742 </xsl:template>
743
744 <xsl:template name="info.reference">
745   <!-- This is not perfect. It doesn't treat indexterm inside info element as a range covering whole parent of info.
746        It also not work when there is no ID generated for parent element. But it works in the most common cases. -->
747   <xsl:param name="scope" select="."/>
748   <xsl:param name="role" select="''"/>
749   <xsl:param name="type" select="''"/>
750
751   <xsl:variable name="target" select="(ancestor::d:appendix|ancestor::d:article|ancestor::d:bibliography|ancestor::d:book|
752                                        ancestor::d:chapter|ancestor::d:glossary|ancestor::d:part|ancestor::d:preface|
753                                        ancestor::d:refentry|ancestor::d:reference|ancestor::d:refsect1|ancestor::d:refsect2|
754                                        ancestor::d:refsect3|ancestor::d:refsection|ancestor::d:refsynopsisdiv|
755                                        ancestor::d:sect1|ancestor::d:sect2|ancestor::d:sect3|ancestor::d:sect4|ancestor::d:sect5|
756                                        ancestor::d:section|ancestor::d:setindex|ancestor::d:set|ancestor::d:sidebar|ancestor::d:mediaobject)[&scope;]"/>
757   
758   <xsl:variable name="id">
759     <xsl:call-template name="object.id">
760       <xsl:with-param name="object" select="$target[position() = last()]"/>
761     </xsl:call-template>
762   </xsl:variable>
763   
764   <fo:basic-link internal-destination="{$id}"
765                  xsl:use-attribute-sets="index.page.number.properties">
766     <fo:page-number-citation ref-id="{$id}"/>
767   </fo:basic-link>
768 </xsl:template>
769
770 <xsl:template match="d:indexterm" mode="index-see">
771   <xsl:param name="scope" select="."/>
772   <xsl:param name="role" select="''"/>
773   <xsl:param name="type" select="''"/>
774
775   <xsl:variable name="see" select="normalize-space(d:see)"/>
776
777   <!-- can only link to primary, which should appear before comma
778   in see "primary, secondary" entry -->
779   <xsl:variable name="seeprimary">
780     <xsl:choose>
781       <xsl:when test="contains($see, ',')">
782         <xsl:value-of select="substring-before($see, ',')"/>
783       </xsl:when>
784       <xsl:otherwise>
785         <xsl:value-of select="$see"/>
786       </xsl:otherwise>
787     </xsl:choose>
788   </xsl:variable> 
789
790   <xsl:variable name="seetarget" select="key('primaryonly', $seeprimary)[1]"/>
791
792   <xsl:variable name="linkend">
793     <xsl:if test="$seetarget">
794       <xsl:value-of select="concat('ientry-', generate-id($seetarget))"/>
795     </xsl:if>
796   </xsl:variable>
797   
798   <fo:inline>
799     <xsl:text> (</xsl:text>
800     <xsl:call-template name="gentext">
801       <xsl:with-param name="key" select="'see'"/>
802     </xsl:call-template>
803     <xsl:text> </xsl:text>
804     <xsl:choose>
805       <!-- manual links have precedence -->
806       <xsl:when test="d:see/@linkend or d:see/@xlink:href">
807         <xsl:call-template name="simple.xlink">
808           <xsl:with-param name="node" select="d:see"/>
809           <xsl:with-param name="content" select="$see"/>
810         </xsl:call-template>
811       </xsl:when>
812       <xsl:when test="$autolink.index.see = 0">
813          <xsl:value-of select="$see"/>
814       </xsl:when>
815       <xsl:when test="$seetarget">
816         <fo:basic-link internal-destination="{$linkend}"
817                        xsl:use-attribute-sets="xref.properties">
818           <xsl:value-of select="$see"/>
819         </fo:basic-link>
820       </xsl:when>
821       <xsl:otherwise>
822         <xsl:value-of select="$see"/>
823       </xsl:otherwise>
824     </xsl:choose>
825     <xsl:text>)</xsl:text>
826   </fo:inline>
827 </xsl:template>
828
829 <xsl:template match="d:indexterm" mode="index-seealso">
830    <xsl:param name="scope" select="."/>
831   <xsl:param name="role" select="''"/>
832   <xsl:param name="type" select="''"/>
833
834   <xsl:for-each select="d:seealso">
835     <xsl:sort select="translate(., &lowercase;, &uppercase;)"/>
836
837     <xsl:variable name="seealso" select="normalize-space(.)"/>
838
839     <!-- can only link to primary, which should appear before comma
840     in seealso "primary, secondary" entry -->
841     <xsl:variable name="seealsoprimary">
842       <xsl:choose>
843         <xsl:when test="contains($seealso, ',')">
844           <xsl:value-of select="substring-before($seealso, ',')"/>
845         </xsl:when>
846         <xsl:otherwise>
847           <xsl:value-of select="$seealso"/>
848         </xsl:otherwise>
849       </xsl:choose>
850     </xsl:variable> 
851
852     <xsl:variable name="seealsotarget" select="key('primaryonly', $seealsoprimary)[1]"/>
853
854     <xsl:variable name="linkend">
855       <xsl:if test="$seealsotarget">
856         <xsl:value-of select="concat('ientry-', generate-id($seealsotarget))"/>
857       </xsl:if>
858     </xsl:variable>
859
860     <fo:block>
861       <xsl:text>(</xsl:text>
862       <xsl:call-template name="gentext">
863         <xsl:with-param name="key" select="'seealso'"/>
864       </xsl:call-template>
865       <xsl:text> </xsl:text>
866       <xsl:choose>
867         <!-- manual links have precedence -->
868         <xsl:when test="@linkend or @xlink:href">
869           <xsl:call-template name="simple.xlink">
870             <xsl:with-param name="node" select="."/>
871             <xsl:with-param name="content" select="$seealso"/>
872           </xsl:call-template>
873         </xsl:when>
874         <xsl:when test="$autolink.index.see = 0">
875           <xsl:value-of select="$seealso"/>
876         </xsl:when>
877         <xsl:when test="$seealsotarget">
878           <fo:basic-link internal-destination="{$linkend}"
879                          xsl:use-attribute-sets="xref.properties">
880             <xsl:value-of select="$seealso"/>
881           </fo:basic-link>
882         </xsl:when>
883         <xsl:otherwise>
884           <xsl:value-of select="$seealso"/>
885         </xsl:otherwise>
886       </xsl:choose>
887       <xsl:text>)</xsl:text>
888     </fo:block>
889
890   </xsl:for-each>
891
892 </xsl:template>
893
894 <!-- ====================================================================== -->
895
896 <xsl:template name="generate-index-markup">
897   <xsl:param name="scope" select="(ancestor::d:book|/)[last()]"/>
898   <xsl:param name="role" select="@role"/>
899   <xsl:param name="type" select="@type"/>
900
901   <xsl:variable name="terms" select="$scope//d:indexterm[count(.|key('letter',
902                                      translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;))[&scope;][1]) = 1]"/>
903   <xsl:variable name="alphabetical"
904                 select="$terms[contains(concat(&lowercase;, &uppercase;),
905                                         substring(&primary;, 1, 1))]"/>
906   <xsl:variable name="others" select="$terms[not(contains(concat(&lowercase;,
907                                                  &uppercase;),
908                                              substring(&primary;, 1, 1)))]"/>
909
910   <xsl:text>&lt;index&gt;&#10;</xsl:text>
911   <xsl:if test="$others">
912     <xsl:text>&#10;&lt;indexdiv&gt;&#10;</xsl:text>
913     <xsl:text>&lt;title&gt;</xsl:text>
914     <xsl:call-template name="gentext">
915       <xsl:with-param name="key" select="'index symbols'"/>
916     </xsl:call-template>
917     <xsl:text>&lt;/title&gt;&#10;</xsl:text>
918     <xsl:apply-templates select="$others[count(.|key('primary',
919                                  &primary;)[&scope;][1]) = 1]"
920                          mode="index-symbol-div-markup">
921       <xsl:with-param name="scope" select="$scope"/>
922       <xsl:with-param name="role" select="$role"/>
923       <xsl:with-param name="type" select="$type"/>
924       <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
925     </xsl:apply-templates>
926     <xsl:text>&lt;/indexdiv&gt;&#10;</xsl:text>
927   </xsl:if>
928
929   <xsl:apply-templates select="$alphabetical[count(.|key('letter',
930                                translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;))[&scope;][1]) = 1]"
931                        mode="index-div-markup">
932       <xsl:with-param name="scope" select="$scope"/>
933       <xsl:with-param name="role" select="$role"/>
934       <xsl:with-param name="type" select="$type"/>
935       <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
936   </xsl:apply-templates>
937   <xsl:text>&lt;/index&gt;&#10;</xsl:text>
938 </xsl:template>
939
940 <xsl:template match="*" mode="index-markup">
941   <xsl:param name="scope" select="."/>
942   <xsl:param name="role" select="''"/>
943   <xsl:param name="type" select="''"/>
944
945   <xsl:text>&lt;</xsl:text>
946   <xsl:value-of select="local-name(.)"/>
947   <xsl:text>&gt;&#10;</xsl:text>
948   <xsl:apply-templates mode="index-markup">
949     <xsl:with-param name="scope" select="$scope"/>
950     <xsl:with-param name="role" select="$role"/>
951     <xsl:with-param name="type" select="$type"/>
952   </xsl:apply-templates>
953 </xsl:template>
954
955 <xsl:template match="d:indexterm" mode="index-div-markup">
956   <xsl:param name="scope" select="."/>
957   <xsl:param name="role" select="''"/>
958   <xsl:param name="type" select="''"/>
959   <xsl:variable name="key" select="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
960   <xsl:text>&#10;&lt;indexdiv&gt;&#10;</xsl:text>
961   <xsl:text>&lt;title&gt;</xsl:text>
962   <xsl:value-of select="translate($key, &lowercase;, &uppercase;)"/>
963   <xsl:text>&lt;/title&gt;&#10;</xsl:text>
964
965   <xsl:apply-templates select="key('letter', $key)[&scope;][count(.|key('primary', &primary;)[&scope;][1]) = 1]"
966                        mode="index-primary-markup">
967     <xsl:with-param name="scope" select="$scope"/>
968     <xsl:with-param name="role" select="$role"/>
969     <xsl:with-param name="type" select="$type"/>
970     <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
971   </xsl:apply-templates>
972   <xsl:text>&lt;/indexdiv&gt;&#10;</xsl:text>
973 </xsl:template>
974
975 <xsl:template match="d:indexterm" mode="index-symbol-div-markup">
976   <xsl:param name="scope" select="."/>
977   <xsl:param name="role" select="''"/>
978   <xsl:param name="type" select="''"/>
979   <xsl:variable name="key" select="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
980
981   <xsl:apply-templates select="key('letter', $key)[&scope;][count(.|key('primary', &primary;)[&scope;][1]) = 1]"
982                        mode="index-primary-markup">
983     <xsl:with-param name="scope" select="$scope"/>
984     <xsl:with-param name="role" select="$role"/>
985     <xsl:with-param name="type" select="$type"/>
986     <xsl:sort select="translate(&primary;, &lowercase;, &uppercase;)"/>
987   </xsl:apply-templates>
988 </xsl:template>
989
990 <xsl:template match="d:indexterm" mode="index-primary-markup">
991   <xsl:param name="scope" select="."/>
992   <xsl:param name="role" select="''"/>
993   <xsl:param name="type" select="''"/>
994   <xsl:variable name="key" select="&primary;"/>
995   <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
996   <xsl:variable name="pages" select="$refs[not(d:see) and not(d:seealso)]"/>
997
998   <xsl:text>&#10;&lt;indexentry&gt;&#10;</xsl:text>
999   <xsl:text>&lt;primaryie&gt;</xsl:text>
1000   <xsl:text>&lt;phrase&gt;</xsl:text>
1001   <xsl:call-template name="escape-text">
1002     <xsl:with-param name="text" select="string(d:primary)"/>
1003   </xsl:call-template>
1004   <xsl:text>&lt;/phrase&gt;</xsl:text>
1005   <xsl:if test="$pages">,</xsl:if>
1006   <xsl:text>&#10;</xsl:text>
1007
1008   <xsl:for-each select="$pages">
1009     <xsl:apply-templates select="." mode="reference-markup">
1010       <xsl:with-param name="scope" select="$scope"/>
1011       <xsl:with-param name="role" select="$role"/>
1012       <xsl:with-param name="type" select="$type"/>
1013     </xsl:apply-templates>
1014   </xsl:for-each>
1015
1016   <xsl:text>&lt;/primaryie&gt;&#10;</xsl:text>
1017
1018   <xsl:if test="$refs/d:secondary or $refs[not(d:secondary)]/*[self::d:see or self::d:seealso]">
1019     <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, d:see))[&scope;][1])]"
1020                          mode="index-see-markup">
1021       <xsl:with-param name="scope" select="$scope"/>
1022       <xsl:with-param name="role" select="$role"/>
1023       <xsl:with-param name="type" select="$type"/>
1024       <xsl:sort select="translate(d:see, &lowercase;, &uppercase;)"/>
1025     </xsl:apply-templates>
1026
1027     <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, d:seealso))[&scope;][1])]"
1028                          mode="index-seealso-markup">
1029       <xsl:with-param name="scope" select="$scope"/>
1030       <xsl:with-param name="role" select="$role"/>
1031       <xsl:with-param name="type" select="$type"/>
1032       <xsl:sort select="translate(d:seealso, &lowercase;, &uppercase;)"/>
1033     </xsl:apply-templates>
1034
1035     <xsl:apply-templates select="$refs[d:secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]"
1036                          mode="index-secondary-markup">
1037       <xsl:with-param name="scope" select="$scope"/>
1038       <xsl:with-param name="role" select="$role"/>
1039       <xsl:with-param name="type" select="$type"/>
1040       <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
1041     </xsl:apply-templates>
1042   </xsl:if>
1043   <xsl:text>&lt;/indexentry&gt;&#10;</xsl:text>
1044 </xsl:template>
1045
1046 <xsl:template match="d:indexterm" mode="index-secondary-markup">
1047   <xsl:param name="scope" select="."/>
1048   <xsl:param name="role" select="''"/>
1049   <xsl:param name="type" select="''"/>
1050   <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;)"/>
1051   <xsl:variable name="refs" select="key('secondary', $key)[&scope;]"/>
1052   <xsl:variable name="pages" select="$refs[not(d:see) and not(d:seealso)]"/>
1053
1054   <xsl:text>&lt;secondaryie&gt;</xsl:text>
1055   <xsl:text>&lt;phrase&gt;</xsl:text>
1056   <xsl:call-template name="escape-text">
1057     <xsl:with-param name="text" select="string(d:secondary)"/>
1058   </xsl:call-template>
1059   <xsl:text>&lt;/phrase&gt;</xsl:text>
1060   <xsl:if test="$pages">,</xsl:if>
1061   <xsl:text>&#10;</xsl:text>
1062
1063   <xsl:for-each select="$pages">
1064     <xsl:apply-templates select="." mode="reference-markup">
1065       <xsl:with-param name="scope" select="$scope"/>
1066       <xsl:with-param name="role" select="$role"/>
1067       <xsl:with-param name="type" select="$type"/>
1068     </xsl:apply-templates>
1069   </xsl:for-each>
1070
1071   <xsl:text>&lt;/secondaryie&gt;&#10;</xsl:text>
1072
1073   <xsl:if test="$refs/d:tertiary or $refs[not(d:tertiary)]/*[self::d:see or self::d:seealso]">
1074     <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, d:see))[&scope;][1])]"
1075                          mode="index-see-markup">
1076       <xsl:with-param name="scope" select="$scope"/>
1077       <xsl:with-param name="role" select="$role"/>
1078       <xsl:with-param name="type" select="$type"/>
1079       <xsl:sort select="translate(d:see, &lowercase;, &uppercase;)"/>
1080     </xsl:apply-templates>
1081     <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, d:seealso))[&scope;][1])]"
1082                          mode="index-seealso-markup">
1083       <xsl:with-param name="scope" select="$scope"/>
1084       <xsl:with-param name="role" select="$role"/>
1085       <xsl:with-param name="type" select="$type"/>
1086       <xsl:sort select="translate(d:seealso, &lowercase;, &uppercase;)"/>
1087     </xsl:apply-templates>
1088     <xsl:apply-templates select="$refs[d:tertiary and count(.|key('tertiary', concat($key, &sep;, &tertiary;))[&scope;][1]) = 1]"
1089                          mode="index-tertiary-markup">
1090       <xsl:with-param name="scope" select="$scope"/>
1091       <xsl:with-param name="role" select="$role"/>
1092       <xsl:with-param name="type" select="$type"/>
1093       <xsl:sort select="translate(&tertiary;, &lowercase;, &uppercase;)"/>
1094     </xsl:apply-templates>
1095   </xsl:if>
1096 </xsl:template>
1097
1098 <xsl:template match="d:indexterm" mode="index-tertiary-markup">
1099   <xsl:param name="scope" select="."/>
1100   <xsl:param name="role" select="''"/>
1101   <xsl:param name="type" select="''"/>
1102   <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
1103   <xsl:variable name="refs" select="key('tertiary', $key)[&scope;]"/>
1104   <xsl:variable name="pages" select="$refs[not(d:see) and not(d:seealso)]"/>
1105
1106   <xsl:text>&lt;tertiaryie&gt;</xsl:text>
1107   <xsl:text>&lt;phrase&gt;</xsl:text>
1108   <xsl:call-template name="escape-text">
1109     <xsl:with-param name="text" select="string(d:tertiary)"/>
1110   </xsl:call-template>
1111   <xsl:text>&lt;/phrase&gt;</xsl:text>
1112   <xsl:if test="$pages">,</xsl:if>
1113   <xsl:text>&#10;</xsl:text>
1114
1115   <xsl:for-each select="$pages">
1116     <xsl:apply-templates select="." mode="reference-markup">
1117       <xsl:with-param name="scope" select="$scope"/>
1118       <xsl:with-param name="role" select="$role"/>
1119       <xsl:with-param name="type" select="$type"/>
1120     </xsl:apply-templates>
1121   </xsl:for-each>
1122
1123   <xsl:text>&lt;/tertiaryie&gt;&#10;</xsl:text>
1124
1125   <xsl:variable name="see" select="$refs/d:see | $refs/d:seealso"/>
1126   <xsl:if test="$see">
1127     <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, d:see))[&scope;][1])]"
1128                          mode="index-see-markup">
1129       <xsl:with-param name="scope" select="$scope"/>
1130       <xsl:with-param name="role" select="$role"/>
1131       <xsl:with-param name="type" select="$type"/>
1132       <xsl:sort select="translate(d:see, &lowercase;, &uppercase;)"/>
1133     </xsl:apply-templates>
1134     <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, d:seealso))[&scope;][1])]"
1135                          mode="index-seealso-markup">
1136       <xsl:with-param name="scope" select="$scope"/>
1137       <xsl:with-param name="role" select="$role"/>
1138       <xsl:with-param name="type" select="$type"/>
1139       <xsl:sort select="translate(d:seealso, &lowercase;, &uppercase;)"/>
1140     </xsl:apply-templates>
1141   </xsl:if>
1142 </xsl:template>
1143
1144 <xsl:template match="d:indexterm" mode="reference-markup">
1145   <xsl:param name="scope" select="."/>
1146   <xsl:param name="role" select="''"/>
1147   <xsl:param name="type" select="''"/>
1148
1149   <xsl:choose>
1150     <xsl:when test="@zone and string(@zone)">
1151       <xsl:call-template name="reference-markup">
1152         <xsl:with-param name="zones" select="normalize-space(@zone)"/>
1153         <xsl:with-param name="scope" select="$scope"/>
1154         <xsl:with-param name="role" select="$role"/>
1155         <xsl:with-param name="type" select="$type"/>
1156       </xsl:call-template>
1157     </xsl:when>
1158     <xsl:otherwise>
1159       <xsl:variable name="id">
1160         <xsl:call-template name="object.id"/>
1161       </xsl:variable>
1162
1163
1164       <xsl:choose>
1165         <xsl:when test="@startref and @class='endofrange'">
1166           <xsl:text>&lt;phrase role="pageno"&gt;</xsl:text>
1167           <xsl:text>&lt;link linkend="</xsl:text>
1168           <xsl:value-of select="@startref"/>
1169           <xsl:text>"&gt;</xsl:text>
1170           <fo:basic-link internal-destination="{@startref}"
1171                      xsl:use-attribute-sets="index.page.number.properties">
1172             <fo:page-number-citation ref-id="{@startref}"/>
1173             <xsl:text>-</xsl:text>
1174             <fo:page-number-citation ref-id="{$id}"/>
1175           </fo:basic-link>
1176           <xsl:text>&lt;/link&gt;</xsl:text>
1177           <xsl:text>&lt;/phrase&gt;&#10;</xsl:text>
1178         </xsl:when>
1179         <xsl:otherwise>
1180           <xsl:text>&lt;phrase role="pageno"&gt;</xsl:text>
1181           <xsl:if test="$id">
1182             <xsl:text>&lt;link linkend="</xsl:text>
1183             <xsl:value-of select="$id"/>
1184             <xsl:text>"&gt;</xsl:text>
1185           </xsl:if>
1186           <fo:basic-link internal-destination="{$id}"
1187                      xsl:use-attribute-sets="index.page.number.properties">
1188             <fo:page-number-citation ref-id="{$id}"/>
1189           </fo:basic-link>
1190           <xsl:if test="$id">
1191             <xsl:text>&lt;/link&gt;</xsl:text>
1192           </xsl:if>
1193           <xsl:text>&lt;/phrase&gt;&#10;</xsl:text>
1194         </xsl:otherwise>
1195       </xsl:choose>
1196     </xsl:otherwise>
1197   </xsl:choose>
1198 </xsl:template>
1199
1200 <xsl:template name="reference-markup">
1201   <xsl:param name="scope" select="."/>
1202   <xsl:param name="role" select="''"/>
1203   <xsl:param name="type" select="''"/>
1204   <xsl:param name="zones"/>
1205   <xsl:choose>
1206     <xsl:when test="contains($zones, ' ')">
1207       <xsl:variable name="zone" select="substring-before($zones, ' ')"/>
1208       <xsl:variable name="target" select="key('id', $zone)[&scope;]"/>
1209
1210       <xsl:variable name="id">
1211         <xsl:call-template name="object.id">
1212           <xsl:with-param name="object" select="$target[1]"/>
1213         </xsl:call-template>
1214       </xsl:variable>
1215
1216       <xsl:text>&lt;phrase role="pageno"&gt;</xsl:text>
1217       <xsl:if test="$target[1]/@id or $target[1]/@xml:id">
1218         <xsl:text>&lt;link linkend="</xsl:text>
1219         <xsl:value-of select="$id"/>
1220         <xsl:text>"&gt;</xsl:text>
1221       </xsl:if>
1222       <fo:basic-link internal-destination="{$id}"
1223                      xsl:use-attribute-sets="index.page.number.properties">
1224         <fo:page-number-citation ref-id="{$id}"/>
1225       </fo:basic-link>
1226       <xsl:if test="$target[1]/@id or $target[1]/@xml:id">
1227         <xsl:text>&lt;/link&gt;</xsl:text>
1228       </xsl:if>
1229       <xsl:text>&lt;/phrase&gt;&#10;</xsl:text>
1230
1231       <xsl:call-template name="reference">
1232         <xsl:with-param name="zones" select="substring-after($zones, ' ')"/>
1233         <xsl:with-param name="scope" select="$scope"/>
1234         <xsl:with-param name="role" select="$role"/>
1235         <xsl:with-param name="type" select="$type"/>
1236       </xsl:call-template>
1237     </xsl:when>
1238     <xsl:otherwise>
1239       <xsl:variable name="zone" select="$zones"/>
1240       <xsl:variable name="target" select="key('id', $zone)[&scope;]"/>
1241
1242       <xsl:variable name="id">
1243         <xsl:call-template name="object.id">
1244           <xsl:with-param name="object" select="$target[1]"/>
1245         </xsl:call-template>
1246       </xsl:variable>
1247
1248       <xsl:text>&lt;phrase role="pageno"&gt;</xsl:text>
1249       <xsl:if test="$target[1]/@id or d:target[1]/@xml:id">
1250         <xsl:text>&lt;link linkend="</xsl:text>
1251         <xsl:value-of select="$id"/>
1252         <xsl:text>"&gt;</xsl:text>
1253       </xsl:if>
1254       <fo:basic-link internal-destination="{$id}"
1255                      xsl:use-attribute-sets="index.page.number.properties">
1256         <fo:page-number-citation ref-id="{$id}"/>
1257       </fo:basic-link>
1258       <xsl:if test="$target[1]/@id or d:target[1]/@xml:id">
1259         <xsl:text>&lt;/link&gt;</xsl:text>
1260       </xsl:if>
1261       <xsl:text>&lt;/phrase&gt;&#10;</xsl:text>
1262     </xsl:otherwise>
1263   </xsl:choose>
1264 </xsl:template>
1265
1266 <xsl:template match="d:indexterm" mode="index-see-markup">
1267   <xsl:param name="scope" select="."/>
1268   <xsl:param name="role" select="''"/>
1269   <xsl:param name="type" select="''"/>
1270   <fo:block>
1271     <xsl:text>&lt;seeie&gt;</xsl:text>
1272     <xsl:text>&lt;phrase&gt;</xsl:text>
1273     <xsl:call-template name="escape-text">
1274       <xsl:with-param name="text" select="string(d:see)"/>
1275     </xsl:call-template>
1276     <xsl:text>&lt;/phrase&gt;</xsl:text>
1277     <xsl:text>&lt;/seeie&gt;&#10;</xsl:text>
1278   </fo:block>
1279 </xsl:template>
1280
1281 <xsl:template match="d:indexterm" mode="index-seealso-markup">
1282   <xsl:param name="scope" select="."/>
1283   <xsl:param name="role" select="''"/>
1284   <xsl:param name="type" select="''"/>
1285   <fo:block>
1286     <xsl:text>&lt;seealsoie&gt;</xsl:text>
1287     <xsl:text>&lt;phrase&gt;</xsl:text>
1288     <xsl:call-template name="escape-text">
1289       <xsl:with-param name="text" select="string(d:seealso)"/>
1290     </xsl:call-template>
1291     <xsl:text>&lt;/phrase&gt;</xsl:text>
1292     <xsl:text>&lt;/seealsoie&gt;&#10;</xsl:text>
1293   </fo:block>
1294 </xsl:template>
1295
1296 <xsl:template name="escape-text">
1297   <xsl:param name="text" select="''"/>
1298
1299   <xsl:variable name="ltpos" select="substring-before($text, '&lt;')"/>
1300   <xsl:variable name="amppos" select="substring-before($text, '&amp;')"/>
1301
1302   <xsl:choose>
1303     <xsl:when test="contains($text,'&lt;') and contains($text, '&amp;')
1304                     and string-length($ltpos) &lt; string-length($amppos)">
1305       <xsl:value-of select="$ltpos"/>
1306       <xsl:text>&amp;lt;</xsl:text>
1307       <xsl:call-template name="escape-text">
1308         <xsl:with-param name="text" select="substring-after($text, '&lt;')"/>
1309       </xsl:call-template>
1310     </xsl:when>
1311
1312     <xsl:when test="contains($text,'&lt;') and contains($text, '&amp;')
1313                     and string-length($amppos) &lt; string-length($ltpos)">
1314       <xsl:value-of select="$amppos"/>
1315       <xsl:text>&amp;amp;</xsl:text>
1316       <xsl:call-template name="escape-text">
1317         <xsl:with-param name="text" select="substring-after($text, '&amp;')"/>
1318       </xsl:call-template>
1319     </xsl:when>
1320
1321     <xsl:when test="contains($text, '&lt;')">
1322       <xsl:value-of select="$ltpos"/>
1323       <xsl:text>&amp;lt;</xsl:text>
1324       <xsl:call-template name="escape-text">
1325         <xsl:with-param name="text" select="substring-after($text, '&lt;')"/>
1326       </xsl:call-template>
1327     </xsl:when>
1328
1329     <xsl:when test="contains($text, '&amp;')">
1330       <xsl:value-of select="$amppos"/>
1331       <xsl:text>&amp;amp;</xsl:text>
1332       <xsl:call-template name="escape-text">
1333         <xsl:with-param name="text" select="substring-after($text, '&amp;')"/>
1334       </xsl:call-template>
1335     </xsl:when>
1336
1337     <xsl:otherwise>
1338       <xsl:value-of select="$text"/>
1339     </xsl:otherwise>
1340   </xsl:choose>
1341 </xsl:template>
1342
1343 <xsl:template name="index.separator">
1344   <xsl:param name="key" select="''"/>
1345   <xsl:param name="lang">
1346     <xsl:call-template name="l10n.language"/>
1347   </xsl:param>
1348
1349   <xsl:choose>
1350     <xsl:when test="$key = 'index.term.separator'">
1351       <xsl:choose>
1352         <!-- Use the override if not blank -->
1353         <xsl:when test="$index.term.separator != ''">
1354           <xsl:copy-of select="$index.term.separator"/>
1355         </xsl:when>
1356         <xsl:otherwise>
1357           <xsl:call-template name="gentext.template">
1358             <xsl:with-param name="lang" select="$lang"/>
1359             <xsl:with-param name="context">index</xsl:with-param>
1360             <xsl:with-param name="name">term-separator</xsl:with-param>
1361           </xsl:call-template>
1362         </xsl:otherwise>
1363       </xsl:choose>
1364     </xsl:when>
1365     <xsl:when test="$key = 'index.number.separator'">
1366       <xsl:choose>
1367         <!-- Use the override if not blank -->
1368         <xsl:when test="$index.number.separator != ''">
1369           <xsl:copy-of select="$index.number.separator"/>
1370         </xsl:when>
1371         <xsl:otherwise>
1372           <xsl:call-template name="gentext.template">
1373             <xsl:with-param name="lang" select="$lang"/>
1374             <xsl:with-param name="context">index</xsl:with-param>
1375             <xsl:with-param name="name">number-separator</xsl:with-param>
1376           </xsl:call-template>
1377         </xsl:otherwise>
1378       </xsl:choose>
1379     </xsl:when>
1380     <xsl:when test="$key = 'index.range.separator'">
1381       <xsl:choose>
1382         <!-- Use the override if not blank -->
1383         <xsl:when test="$index.range.separator != ''">
1384           <xsl:copy-of select="$index.range.separator"/>
1385         </xsl:when>
1386         <xsl:otherwise>
1387           <xsl:call-template name="gentext.template">
1388             <xsl:with-param name="lang" select="$lang"/>
1389             <xsl:with-param name="context">index</xsl:with-param>
1390             <xsl:with-param name="name">range-separator</xsl:with-param>
1391           </xsl:call-template>
1392         </xsl:otherwise>
1393       </xsl:choose>
1394     </xsl:when>
1395   </xsl:choose>
1396 </xsl:template>
1397
1398 </xsl:stylesheet>