1<?xml version="1.0"?>
2<!DOCTYPE xsl:stylesheet [
3
4<!ENTITY lowercase "'abcdefghijklmnopqrstuvwxyz'">
5<!ENTITY uppercase "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'">
6
7<!ENTITY primary   'concat(primary/@sortas, primary[not(@sortas)])'>
8<!ENTITY secondary 'concat(secondary/@sortas, secondary[not(@sortas)])'>
9<!ENTITY tertiary  'concat(tertiary/@sortas, tertiary[not(@sortas)])'>
10
11<!ENTITY section   '(ancestor-or-self::set
12                     |ancestor-or-self::book
13                     |ancestor-or-self::part
14                     |ancestor-or-self::reference
15                     |ancestor-or-self::partintro
16                     |ancestor-or-self::chapter
17                     |ancestor-or-self::appendix
18                     |ancestor-or-self::preface
19                     |ancestor-or-self::section
20                     |ancestor-or-self::sect1
21                     |ancestor-or-self::sect2
22                     |ancestor-or-self::sect3
23                     |ancestor-or-self::sect4
24                     |ancestor-or-self::sect5
25                     |ancestor-or-self::refsect1
26                     |ancestor-or-self::refsect2
27                     |ancestor-or-self::refsect3
28                     |ancestor-or-self::simplesect
29                     |ancestor-or-self::bibliography
30                     |ancestor-or-self::glossary
31                     |ancestor-or-self::index)[last()]'>
32
33<!ENTITY section.id 'generate-id(&section;)'>
34<!ENTITY sep '" "'>
35]>
36<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
37                xmlns:fo="http://www.w3.org/1999/XSL/Format"
38                version="1.0">
39
40<xsl:import href="docbook.xsl"/>
41
42<!-- ==================================================================== -->
43<!-- Derived from Jeni Tennison's work in the HTML case -->
44
45<xsl:key name="letter"
46         match="indexterm"
47         use="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
48
49<xsl:key name="primary"
50         match="indexterm"
51         use="&primary;"/>
52
53<xsl:key name="secondary"
54         match="indexterm"
55         use="concat(&primary;, &sep;, &secondary;)"/>
56
57<xsl:key name="tertiary"
58         match="indexterm"
59         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
60
61<xsl:key name="primary-section"
62         match="indexterm[not(secondary) and not(see)]"
63         use="concat(&primary;, &sep;, &section.id;)"/>
64
65<xsl:key name="secondary-section"
66         match="indexterm[not(tertiary) and not(see)]"
67         use="concat(&primary;, &sep;, &secondary;, &sep;, &section.id;)"/>
68
69<xsl:key name="tertiary-section"
70         match="indexterm[not(see)]"
71         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, &section.id;)"/>
72
73<xsl:key name="see-also"
74         match="indexterm[seealso]"
75         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso)"/>
76
77<xsl:key name="see"
78         match="indexterm[see]"
79         use="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see)"/>
80
81<xsl:key name="sections" match="*[@id]" use="@id"/>
82
83<xsl:template name="generate-index">
84  <xsl:variable name="terms" select="//indexterm[count(.|key('letter',
85                                     translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;))[1]) = 1]"/>
86  <xsl:variable name="alphabetical"
87                select="$terms[contains(concat(&lowercase;, &uppercase;),
88                                        substring(&primary;, 1, 1))]"/>
89  <xsl:variable name="others" select="$terms[not(contains(concat(&lowercase;,
90                                                 &uppercase;),
91                                             substring(&primary;, 1, 1)))]"/>
92  <fo:block>
93    <xsl:if test="$others">
94      <fo:block font-size="16pt"
95                font-weight="bold"
96                keep-with-next.within-column="always"
97                space-before="1em">
98        <xsl:call-template name="gentext">
99          <xsl:with-param name="key" select="'index symbols'"/>
100        </xsl:call-template>
101      </fo:block>
102      <fo:block>
103        <xsl:apply-templates select="$others[count(.|key('primary',
104                                     &primary;)[1]) = 1]"
105                             mode="index-primary">
106          <xsl:sort select="&primary;"/>
107        </xsl:apply-templates>
108      </fo:block>
109    </xsl:if>
110    <xsl:apply-templates select="$alphabetical[count(.|key('letter',
111                                 translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;))[1]) = 1]"
112                         mode="index-div">
113      <xsl:sort select="&primary;"/>
114    </xsl:apply-templates>
115  </fo:block>
116</xsl:template>
117
118<xsl:template match="indexterm" mode="index-div">
119  <xsl:variable name="key" select="translate(substring(&primary;, 1, 1),&lowercase;,&uppercase;)"/>
120  <fo:block>
121    <!-- this isn't quite exactly right. ideally all the symbols would -->
122    <!-- be grouped together. as it stands, they all get separate divs -->
123    <!-- but at least this test makes sure that they don't all get     -->
124    <!-- separate titles as well. -->
125    <xsl:if test="contains(concat(&lowercase;, &uppercase;), $key)">
126      <fo:block font-size="16pt"
127                font-weight="bold"
128                keep-with-next.within-column="always"
129                space-before="1em">
130        <xsl:value-of select="translate($key, &lowercase;, &uppercase;)"/>
131      </fo:block>
132    </xsl:if>
133    <fo:block>
134      <xsl:apply-templates select="key('letter', $key)[count(.|key('primary', &primary;)[1]) = 1]"
135                           mode="index-primary">
136        <xsl:sort select="&primary;"/>
137      </xsl:apply-templates>
138    </fo:block>
139  </fo:block>
140</xsl:template>
141
142<xsl:template match="indexterm" mode="index-primary">
143  <xsl:variable name="key" select="&primary;"/>
144  <xsl:variable name="refs" select="key('primary', $key)"/>
145  <fo:block>
146    <xsl:value-of select="primary"/>
147
148    <xsl:variable name="page-number-citations">
149      <xsl:for-each select="$refs[generate-id() = generate-id(key('primary-section', concat($key, &sep;, &section.id;))[1])]">
150        <xsl:apply-templates select="." mode="reference"/>
151      </xsl:for-each>
152    </xsl:variable>
153
154    <xsl:choose>
155      <xsl:when test="$passivetex.extensions != '0'">
156        <fotex:sort xmlns:fotex="http://www.tug.org/fotex">
157          <xsl:copy-of select="$page-number-citations"/>
158        </fotex:sort>
159      </xsl:when>
160      <xsl:otherwise>
161        <xsl:copy-of select="$page-number-citations"/>
162      </xsl:otherwise>
163    </xsl:choose>
164  </fo:block>
165  <xsl:if test="$refs/secondary or $refs[not(secondary)]/*[self::see or self::seealso]">
166    <fo:block start-indent="1pc">
167      <fo:block>
168        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[1])]"
169                             mode="index-see">
170          <xsl:sort select="see"/>
171        </xsl:apply-templates>
172        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[1])]"
173                             mode="index-seealso">
174          <xsl:sort select="seealso"/>
175        </xsl:apply-templates>
176        <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[1]) = 1]" 
177                             mode="index-secondary">
178          <xsl:sort select="&secondary;"/>
179        </xsl:apply-templates>
180      </fo:block>
181    </fo:block>
182  </xsl:if>
183</xsl:template>
184
185<xsl:template match="indexterm" mode="index-secondary">
186  <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;)"/>
187  <xsl:variable name="refs" select="key('secondary', $key)"/>
188  <fo:block>
189    <xsl:value-of select="secondary"/>
190
191    <xsl:variable name="page-number-citations">
192      <xsl:for-each select="$refs[generate-id() = generate-id(key('secondary-section', concat($key, &sep;, &section.id;))[1])]">
193        <xsl:apply-templates select="." mode="reference"/>
194      </xsl:for-each>
195    </xsl:variable>
196
197    <xsl:choose>
198      <xsl:when test="$passivetex.extensions != '0'">
199        <fotex:sort xmlns:fotex="http://www.tug.org/fotex">
200          <xsl:copy-of select="$page-number-citations"/>
201        </fotex:sort>
202      </xsl:when>
203      <xsl:otherwise>
204        <xsl:copy-of select="$page-number-citations"/>
205      </xsl:otherwise>
206    </xsl:choose>
207  </fo:block>
208  <xsl:if test="$refs/tertiary or $refs[not(tertiary)]/*[self::see or self::seealso]">
209    <fo:block start-indent="2pc">
210      <fo:block>
211        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, see))[1])]"
212                             mode="index-see">
213          <xsl:sort select="see"/>
214        </xsl:apply-templates>
215        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &sep;, seealso))[1])]"
216                             mode="index-seealso">
217          <xsl:sort select="seealso"/>
218        </xsl:apply-templates>
219        <xsl:apply-templates select="$refs[tertiary and count(.|key('tertiary', concat($key, &sep;, &tertiary;))[1]) = 1]" 
220                             mode="index-tertiary">
221          <xsl:sort select="&tertiary;"/>
222        </xsl:apply-templates>
223      </fo:block>
224    </fo:block>
225  </xsl:if>
226</xsl:template>
227
228<xsl:template match="indexterm" mode="index-tertiary">
229  <xsl:variable name="key" select="concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;)"/>
230  <xsl:variable name="refs" select="key('tertiary', $key)"/>
231  <fo:block>
232    <xsl:value-of select="tertiary"/>
233
234    <xsl:variable name="page-number-citations">
235      <xsl:for-each select="$refs[generate-id() = generate-id(key('tertiary-section', concat($key, &sep;, &section.id;))[1])]">
236        <xsl:apply-templates select="." mode="reference"/>
237      </xsl:for-each>
238    </xsl:variable>
239
240    <xsl:choose>
241      <xsl:when test="$passivetex.extensions != '0'">
242        <fotex:sort xmlns:fotex="http://www.tug.org/fotex">
243          <xsl:copy-of select="$page-number-citations"/>
244        </fotex:sort>
245      </xsl:when>
246      <xsl:otherwise>
247        <xsl:copy-of select="$page-number-citations"/>
248      </xsl:otherwise>
249    </xsl:choose>
250  </fo:block>
251  <xsl:variable name="see" select="$refs/see | $refs/seealso"/>
252  <xsl:if test="$see">
253    <fo:block>
254      <fo:block>
255        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, see))[1])]"
256                             mode="index-see">
257          <xsl:sort select="see"/>
258        </xsl:apply-templates>
259        <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &secondary;, &sep;, &tertiary;, &sep;, seealso))[1])]"
260                             mode="index-seealso">
261          <xsl:sort select="seealso"/>
262        </xsl:apply-templates>
263      </fo:block>
264    </fo:block>
265  </xsl:if>
266</xsl:template>
267
268<xsl:template match="indexterm" mode="reference">
269  <xsl:if test="$passivetex.extensions = '0'">
270    <xsl:text>, </xsl:text>
271  </xsl:if>
272  <xsl:choose>
273    <xsl:when test="@zone and string(@zone)">
274      <xsl:call-template name="reference">
275        <xsl:with-param name="zones" select="normalize-space(@zone)"/>
276      </xsl:call-template>
277    </xsl:when>
278    <xsl:otherwise>
279      <xsl:variable name="id">
280        <xsl:call-template name="object.id"/>
281      </xsl:variable>
282      <fo:page-number-citation ref-id="{$id}"/>
283    </xsl:otherwise>
284  </xsl:choose>
285</xsl:template>
286
287<xsl:template name="reference">
288  <xsl:param name="zones"/>
289  <xsl:choose>
290    <xsl:when test="contains($zones, ' ')">
291      <xsl:variable name="zone" select="substring-before($zones, ' ')"/>
292      <xsl:variable name="target" select="key('sections', $zone)"/>
293
294      <xsl:variable name="id">
295        <xsl:call-template name="object.id">
296          <xsl:with-param name="object" select="$target[1]"/>
297        </xsl:call-template>
298      </xsl:variable>
299
300      <fo:page-number-citation ref-id="{$id}"/>
301
302      <xsl:if test="$passivetex.extensions = '0'">
303        <xsl:text>, </xsl:text>
304      </xsl:if>
305      <xsl:call-template name="reference">
306        <xsl:with-param name="zones" select="substring-after($zones, ' ')"/>
307      </xsl:call-template>
308    </xsl:when>
309    <xsl:otherwise>
310      <xsl:variable name="zone" select="$zones"/>
311      <xsl:variable name="target" select="key('sections', $zone)"/>
312
313      <xsl:variable name="id">
314        <xsl:call-template name="object.id">
315          <xsl:with-param name="object" select="$target[1]"/>
316        </xsl:call-template>
317      </xsl:variable>
318
319      <fo:page-number-citation ref-id="{$id}"/>
320    </xsl:otherwise>
321  </xsl:choose>
322</xsl:template>
323
324<xsl:template match="indexterm" mode="index-see">
325   <fo:block><xsl:value-of select="see"/></fo:block>
326</xsl:template>
327
328<xsl:template match="indexterm" mode="index-seealso">
329   <fo:block><xsl:value-of select="seealso"/></fo:block>
330</xsl:template>
331
332</xsl:stylesheet>
333