69ee51accaef3a1dd8cab93971190e1db772448f
[apps/madmutt.git] / doc / xslt / common / olink.xsl
1 <?xml version="1.0"?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3                 version="1.0">
4
5 <!-- Create keys for quickly looking up olink targets -->
6 <xsl:key name="targetdoc-key" match="document" use="@targetdoc" />
7 <xsl:key name="targetptr-key"  match="div|obj"
8          use="concat(ancestor::document/@targetdoc, '/',
9                      @targetptr, '/', ancestor::document/@lang)" />
10
11 <!-- Return filename of database -->
12 <xsl:template name="select.target.database">
13   <xsl:param name="targetdoc.att" select="''"/>
14   <xsl:param name="targetptr.att" select="''"/>
15   <xsl:param name="olink.lang" select="''"/>
16
17   <!-- This selection can be customized if needed -->
18   <xsl:variable name="target.database.filename" 
19       select="$target.database.document"/>
20
21   <xsl:variable name="target.database" 
22       select="document($target.database.filename,/)"/>
23
24   <xsl:choose>
25     <!-- Was the database document parameter not set? -->
26     <xsl:when test="$target.database.document = ''">
27       <xsl:message>
28         <xsl:text>Olinks not processed: must specify a </xsl:text>
29         <xsl:text>$target.database.document parameter&#10;</xsl:text>
30         <xsl:text>when using olinks with targetdoc </xsl:text>
31         <xsl:text>and targetptr attributes.</xsl:text>
32       </xsl:message>
33     </xsl:when>
34     <!-- Did it not open? Should be a targetset element -->
35     <xsl:when test="not($target.database/*)">
36       <xsl:message>
37         <xsl:text>Olink error: could not open target database '</xsl:text>
38         <xsl:value-of select="$target.database.filename"/>
39         <xsl:text>'.</xsl:text>
40       </xsl:message>
41     </xsl:when>
42     <xsl:otherwise>
43       <xsl:value-of select="$target.database.filename"/>
44     </xsl:otherwise>
45   </xsl:choose>
46 </xsl:template>
47
48 <xsl:template name="select.olink.key">
49   <xsl:param name="targetdoc.att" select="''"/>
50   <xsl:param name="targetptr.att" select="''"/>
51   <xsl:param name="olink.lang" select="''"/>
52   <xsl:param name="target.database"/>
53
54   <xsl:if test="$target.database/*">
55     <xsl:variable name="olink.fallback.sequence">
56       <xsl:call-template name="select.olink.lang.fallback">
57         <xsl:with-param name="olink.lang" select="$olink.lang"/>
58       </xsl:call-template>
59     </xsl:variable>
60   
61     <!-- Recurse through the languages until you find a match -->
62     <xsl:call-template name="select.olink.key.in.lang">
63       <xsl:with-param name="targetdoc.att" select="$targetdoc.att"/>
64       <xsl:with-param name="targetptr.att" select="$targetptr.att"/>
65       <xsl:with-param name="olink.lang" select="$olink.lang"/>
66       <xsl:with-param name="target.database" select="$target.database"/>
67       <xsl:with-param name="fallback.index" select="1"/>
68       <xsl:with-param name="olink.fallback.sequence"
69                       select="$olink.fallback.sequence"/>
70     </xsl:call-template>
71   </xsl:if>
72   
73 </xsl:template>
74
75 <!-- Locate olink key in a particular language -->
76 <xsl:template name="select.olink.key.in.lang">
77   <xsl:param name="targetdoc.att" select="''"/>
78   <xsl:param name="targetptr.att" select="''"/>
79   <xsl:param name="olink.lang" select="''"/>
80   <xsl:param name="target.database"/>
81   <xsl:param name="fallback.index" select="1"/>
82   <xsl:param name="olink.fallback.sequence" select="''"/>
83   
84   <xsl:variable name="target.lang">
85     <xsl:call-template name="select.target.lang">
86       <xsl:with-param name="fallback.index" select="$fallback.index"/>
87       <xsl:with-param name="olink.fallback.sequence"
88                       select="$olink.fallback.sequence"/>
89     </xsl:call-template>
90   </xsl:variable>
91
92   <xsl:if test="$olink.debug != 0">
93     <xsl:message><xsl:text>Olink debug: cases for targetdoc='</xsl:text>
94       <xsl:value-of select="$targetdoc.att"/>
95       <xsl:text>' and targetptr='</xsl:text>
96       <xsl:value-of select="$targetptr.att"/>
97       <xsl:text>' in language '</xsl:text>
98       <xsl:value-of select="$target.lang"/>
99       <xsl:text>'.</xsl:text>
100     </xsl:message>
101   </xsl:if>
102
103   <!-- Customize these cases if you want different selection logic -->
104   <xsl:variable name="CaseA">
105     <!-- targetdoc.att = not blank
106          targetptr.att = not blank
107     -->
108     <xsl:if test="$targetdoc.att != '' and
109                   $targetptr.att != ''">
110       <xsl:for-each select="$target.database">
111         <xsl:variable name="key" 
112                       select="concat($targetdoc.att, '/', 
113                                      $targetptr.att, '/',
114                                      $target.lang)"/>
115         <xsl:choose>
116           <xsl:when test="key('targetptr-key', $key)/@href != ''">
117             <xsl:value-of select="$key"/>
118             <xsl:if test="$olink.debug != 0">
119               <xsl:message>Olink debug: CaseA matched.</xsl:message>
120             </xsl:if>
121           </xsl:when>
122           <xsl:when test="$olink.debug != 0">
123             <xsl:message>Olink debug: CaseA NOT matched</xsl:message>
124           </xsl:when>
125         </xsl:choose>
126       </xsl:for-each>
127     </xsl:if>
128   </xsl:variable>
129
130   <xsl:variable name="CaseB">
131     <!-- targetdoc.att = not blank
132          targetptr.att = not blank
133          prefer.internal.olink = not zero
134          current.docid = not blank 
135     -->
136     <xsl:if test="$targetdoc.att != '' and
137                   $targetptr.att != '' and
138                   $current.docid != '' and
139                   $prefer.internal.olink != 0">
140       <xsl:for-each select="$target.database">
141         <xsl:variable name="key" 
142                       select="concat($current.docid, '/', 
143                                      $targetptr.att, '/',
144                                      $target.lang)"/>
145         <xsl:choose>
146           <xsl:when test="key('targetptr-key', $key)/@href != ''">
147             <xsl:value-of select="$key"/>
148             <xsl:if test="$olink.debug != 0">
149               <xsl:message>Olink debug: CaseB matched.</xsl:message>
150             </xsl:if>
151           </xsl:when>
152           <xsl:when test="$olink.debug != 0">
153             <xsl:message>Olink debug: CaseB NOT matched</xsl:message>
154           </xsl:when>
155         </xsl:choose>
156       </xsl:for-each>
157     </xsl:if>
158   </xsl:variable>
159
160   <xsl:variable name="CaseC">
161     <!-- targetdoc.att = blank
162          targetptr.att = not blank
163          current.docid = not blank 
164     -->
165     <xsl:if test="string-length($targetdoc.att) = 0 and
166                   $targetptr.att != '' and
167                   $current.docid != ''">
168       <!-- Must use a for-each to change context for keys to work -->
169       <xsl:for-each select="$target.database">
170         <xsl:variable name="key" 
171                       select="concat($current.docid, '/', 
172                                      $targetptr.att, '/',
173                                      $target.lang)"/>
174         <xsl:choose>
175           <xsl:when test="key('targetptr-key', $key)/@href != ''">
176             <xsl:value-of select="$key"/>
177             <xsl:if test="$olink.debug != 0">
178               <xsl:message>Olink debug: CaseC matched.</xsl:message>
179             </xsl:if>
180           </xsl:when>
181           <xsl:when test="$olink.debug != 0">
182             <xsl:message>Olink debug: CaseC NOT matched.</xsl:message>
183           </xsl:when>
184         </xsl:choose>
185       </xsl:for-each>
186     </xsl:if>
187   </xsl:variable>
188
189   <xsl:variable name="CaseD">
190     <!-- targetdoc.att = blank
191          targetptr.att = not blank
192          current.docid = blank 
193     -->
194     <!-- This is possible if only one document in the database -->
195     <xsl:if test="string-length($targetdoc.att) = 0 and
196                   $targetptr.att != '' and
197                   string-length($current.docid) = 0 and
198                   count($target.database//document) = 1">
199       <xsl:for-each select="$target.database">
200         <xsl:variable name="key" 
201                       select="concat(.//document/@targetdoc, '/', 
202                                      $targetptr.att, '/',
203                                      $target.lang)"/>
204         <xsl:choose>
205           <xsl:when test="key('targetptr-key', $key)/@href != ''">
206             <xsl:value-of select="$key"/>
207             <xsl:if test="$olink.debug != 0">
208               <xsl:message>Olink debug: CaseD matched.</xsl:message>
209             </xsl:if>
210           </xsl:when>
211           <xsl:when test="$olink.debug != 0">
212             <xsl:message>Olink debug: CaseD NOT matched</xsl:message>
213           </xsl:when>
214         </xsl:choose>
215       </xsl:for-each>
216     </xsl:if>
217   </xsl:variable>
218
219   <xsl:variable name="CaseE">
220     <!-- targetdoc.att = not blank
221          targetptr.att = blank
222     -->
223     <xsl:if test="$targetdoc.att != '' and
224                   string-length($targetptr.att) = 0">
225
226       <!-- Try the document's root element id -->
227       <xsl:variable name="rootid">
228         <xsl:choose>
229           <xsl:when test="$target.lang != ''">
230             <xsl:value-of select="$target.database//document[@targetdoc = $targetdoc.att and @lang = $target.lang]/*[1]/@targetptr"/>
231           </xsl:when>
232           <xsl:otherwise>
233             <xsl:value-of select="$target.database//document[@targetdoc = $targetdoc.att and not(@lang)]/*[1]/@targetptr"/>
234           </xsl:otherwise>
235         </xsl:choose>
236       </xsl:variable>
237
238       <xsl:for-each select="$target.database">
239         <xsl:variable name="key" 
240                       select="concat($targetdoc.att, '/', 
241                                      $rootid, '/',
242                                      $target.lang)"/>
243         <xsl:choose>
244           <xsl:when test="key('targetptr-key', $key)/@href != ''">
245             <xsl:value-of select="$key"/>
246             <xsl:if test="$olink.debug != 0">
247               <xsl:message>Olink debug: CaseE matched.</xsl:message>
248             </xsl:if>
249           </xsl:when>
250           <xsl:when test="$olink.debug != 0">
251             <xsl:message>Olink debug: CaseE NOT matched.</xsl:message>
252           </xsl:when>
253         </xsl:choose>
254       </xsl:for-each>
255     </xsl:if>
256   </xsl:variable>
257
258   <xsl:variable name="CaseF">
259     <!-- targetdoc.att = not blank
260          targetptr.att = blank
261          prefer.internal.olink = not zero
262          current.docid = not blank 
263     -->
264     <xsl:if test="$targetdoc.att != '' and
265                   string-length($targetptr.att) = 0 and
266                   $current.docid != '' and
267                   $prefer.internal.olink != 0">
268       <!-- Try the document's root element id -->
269       <xsl:variable name="rootid">
270         <xsl:choose>
271           <xsl:when test="$target.lang != ''">
272             <xsl:value-of select="$target.database//document[@targetdoc = $current.docid and @lang = $target.lang]/*[1]/@targetptr"/>
273           </xsl:when>
274           <xsl:otherwise>
275             <xsl:value-of select="$target.database//document[@targetdoc = $current.docid and not(@lang)]/*[1]/@targetptr"/>
276           </xsl:otherwise>
277         </xsl:choose>
278       </xsl:variable>
279
280       <xsl:for-each select="$target.database">
281         <xsl:variable name="key" 
282                       select="concat($current.docid, '/', 
283                                      $rootid, '/',
284                                      $target.lang)"/>
285         <xsl:choose>
286           <xsl:when test="key('targetptr-key', $key)/@href != ''">
287             <xsl:value-of select="$key"/>
288             <xsl:if test="$olink.debug != 0">
289               <xsl:message>Olink debug: CaseF matched.</xsl:message>
290             </xsl:if>
291           </xsl:when>
292           <xsl:when test="$olink.debug != 0">
293             <xsl:message>Olink debug: CaseF NOT matched.</xsl:message>
294           </xsl:when>
295         </xsl:choose>
296       </xsl:for-each>
297     </xsl:if>
298   </xsl:variable>
299
300   <!-- Now select the best match. Customize the order if needed -->
301   <xsl:variable name="selected.key">
302     <xsl:choose>
303       <xsl:when test="$CaseB != ''">
304         <xsl:value-of select="$CaseB"/>
305         <xsl:if test="$olink.debug != 0">
306           <xsl:message>
307             <xsl:text>Olink debug: CaseB key is the final selection: </xsl:text>
308             <xsl:value-of select="$CaseB"/>
309           </xsl:message>
310         </xsl:if>
311       </xsl:when>
312       <xsl:when test="$CaseA != ''">
313         <xsl:value-of select="$CaseA"/>
314         <xsl:if test="$olink.debug != 0">
315           <xsl:message>
316             <xsl:text>Olink debug: CaseA key is the final selection: </xsl:text>
317             <xsl:value-of select="$CaseA"/>
318           </xsl:message>
319         </xsl:if>
320       </xsl:when>
321       <xsl:when test="$CaseC != ''">
322         <xsl:value-of select="$CaseC"/>
323         <xsl:if test="$olink.debug != 0">
324           <xsl:message>
325             <xsl:text>Olink debug: CaseC key is the final selection: </xsl:text>
326             <xsl:value-of select="$CaseC"/>
327           </xsl:message>
328         </xsl:if>
329       </xsl:when>
330       <xsl:when test="$CaseD != ''">
331         <xsl:value-of select="$CaseD"/>
332         <xsl:if test="$olink.debug != 0">
333           <xsl:message>
334             <xsl:text>Olink debug: CaseD key is the final selection: </xsl:text>
335             <xsl:value-of select="$CaseD"/>
336           </xsl:message>
337         </xsl:if>
338       </xsl:when>
339       <xsl:when test="$CaseF != ''">
340         <xsl:value-of select="$CaseF"/>
341         <xsl:if test="$olink.debug != 0">
342           <xsl:message>
343             <xsl:text>Olink debug: CaseF key is the final selection: </xsl:text>
344             <xsl:value-of select="$CaseF"/>
345           </xsl:message>
346         </xsl:if>
347       </xsl:when>
348       <xsl:when test="$CaseE != ''">
349         <xsl:value-of select="$CaseE"/>
350         <xsl:if test="$olink.debug != 0">
351           <xsl:message>
352             <xsl:text>Olink debug: CaseE key is the final selection: </xsl:text>
353             <xsl:value-of select="$CaseE"/>
354           </xsl:message>
355         </xsl:if>
356       </xsl:when>
357       <xsl:otherwise>
358         <xsl:if test="$olink.debug != 0">
359           <xsl:message>
360             <xsl:text>Olink debug: No case matched for lang '</xsl:text>
361             <xsl:value-of select="$target.lang"/>
362             <xsl:text>'.</xsl:text>
363           </xsl:message>
364         </xsl:if>
365       </xsl:otherwise>
366     </xsl:choose>
367   </xsl:variable>
368
369   <xsl:choose>
370     <xsl:when test="$selected.key != ''">
371       <xsl:value-of select="$selected.key"/>
372     </xsl:when>
373     <xsl:when test="string-length($selected.key) = 0 and 
374                     string-length($target.lang) = 0">
375       <!-- No match on last try, and we are done -->
376     </xsl:when>
377     <xsl:otherwise>
378       <!-- Recurse through next language -->
379       <xsl:call-template name="select.olink.key.in.lang">
380         <xsl:with-param name="targetdoc.att" select="$targetdoc.att"/>
381         <xsl:with-param name="targetptr.att" select="$targetptr.att"/>
382         <xsl:with-param name="olink.lang" select="$olink.lang"/>
383         <xsl:with-param name="target.database" select="$target.database"/>
384         <xsl:with-param name="fallback.index" select="$fallback.index + 1"/>
385         <xsl:with-param name="olink.fallback.sequence"
386                         select="$olink.fallback.sequence"/>
387       </xsl:call-template>
388     </xsl:otherwise>
389   </xsl:choose>
390
391 </xsl:template>
392
393 <xsl:template name="select.target.lang">
394   <xsl:param name="fallback.index" select="1"/>
395   <xsl:param name="olink.fallback.sequence" select="''"/>
396
397   <!-- recurse backwards to find the lang matching the index -->
398   <xsl:variable name="firstlang" 
399                 select="substring-before($olink.fallback.sequence, ' ')"/>
400   <xsl:variable name="rest" 
401                 select="substring-after($olink.fallback.sequence, ' ')"/>
402   <xsl:choose>
403     <xsl:when test="$fallback.index = 1">
404       <xsl:value-of select="$firstlang"/>
405     </xsl:when>
406     <xsl:when test="$fallback.index &gt; 1">
407       <xsl:call-template name="select.target.lang">
408         <xsl:with-param name="fallback.index" select="$fallback.index - 1"/>
409         <xsl:with-param name="olink.fallback.sequence"
410                         select="$rest"/>
411       </xsl:call-template>
412     </xsl:when>
413     <xsl:otherwise>
414     </xsl:otherwise>
415   </xsl:choose>
416 </xsl:template>
417
418 <xsl:template name="select.olink.lang.fallback">
419   <xsl:param name="olink.lang" select="''"/>
420
421   <!-- Prefer language of the olink element -->
422   <xsl:value-of select="concat(normalize-space(concat($olink.lang, ' ', 
423                         $olink.lang.fallback.sequence)), ' ')"/>
424 </xsl:template>
425
426 <!-- Returns the complete olink href value if found -->
427 <xsl:template name="make.olink.href">
428   <xsl:param name="olink.key" select="''"/>
429   <xsl:param name="target.database"/>
430
431   <xsl:if test="$olink.key != ''">
432     <xsl:variable name="target.href" >
433       <xsl:for-each select="$target.database" >
434         <xsl:value-of select="key('targetptr-key', $olink.key)/@href" />
435       </xsl:for-each>
436     </xsl:variable>
437   
438     <xsl:variable name="targetdoc">
439       <xsl:value-of select="substring-before($olink.key, '/')"/>
440     </xsl:variable>
441   
442     <!-- Does the target database use a sitemap? -->
443     <xsl:variable name="use.sitemap">
444       <xsl:choose>
445         <xsl:when test="$target.database//sitemap">1</xsl:when>
446         <xsl:otherwise>0</xsl:otherwise>
447       </xsl:choose>
448     </xsl:variable>
449   
450   
451     <!-- Get the baseuri for this targetptr -->
452     <xsl:variable name="baseuri" >
453       <xsl:choose>
454         <!-- Does the database use a sitemap? -->
455         <xsl:when test="$use.sitemap != 0" >
456           <xsl:choose>
457             <!-- Was current.docid parameter set? -->
458             <xsl:when test="$current.docid != ''">
459               <!-- Was it found in the database? -->
460               <xsl:variable name="currentdoc.key" >
461                 <xsl:for-each select="$target.database" >
462                   <xsl:value-of select="key('targetdoc-key',
463                                         $current.docid)/@targetdoc" />
464                 </xsl:for-each>
465               </xsl:variable>
466               <xsl:choose>
467                 <xsl:when test="$currentdoc.key != ''">
468                   <xsl:for-each select="$target.database" >
469                     <xsl:call-template name="targetpath" >
470                       <xsl:with-param name="dirnode" 
471                           select="key('targetdoc-key', $current.docid)/parent::dir"/>
472                       <xsl:with-param name="targetdoc" select="$targetdoc"/>
473                     </xsl:call-template>
474                   </xsl:for-each >
475                 </xsl:when>
476                 <xsl:otherwise>
477                   <xsl:message>
478                     <xsl:text>Olink error: cannot compute relative </xsl:text>
479                     <xsl:text>sitemap path because $current.docid '</xsl:text>
480                     <xsl:value-of select="$current.docid"/>
481                     <xsl:text>' not found in target database.</xsl:text>
482                   </xsl:message>
483                 </xsl:otherwise>
484               </xsl:choose>
485             </xsl:when>
486             <xsl:otherwise>
487               <xsl:message>
488                 <xsl:text>Olink warning: cannot compute relative </xsl:text>
489                 <xsl:text>sitemap path without $current.docid parameter</xsl:text>
490               </xsl:message>
491             </xsl:otherwise>
492           </xsl:choose> 
493           <!-- In either case, add baseuri from its document entry-->
494           <xsl:variable name="docbaseuri">
495             <xsl:for-each select="$target.database" >
496               <xsl:value-of select="key('targetdoc-key', $targetdoc)/@baseuri" />
497             </xsl:for-each>
498           </xsl:variable>
499           <xsl:if test="$docbaseuri != ''" >
500             <xsl:value-of select="$docbaseuri"/>
501           </xsl:if>
502         </xsl:when>
503         <!-- No database sitemap in use -->
504         <xsl:otherwise>
505           <!-- Just use any baseuri from its document entry -->
506           <xsl:variable name="docbaseuri">
507             <xsl:for-each select="$target.database" >
508               <xsl:value-of select="key('targetdoc-key', $targetdoc)/@baseuri" />
509             </xsl:for-each>
510           </xsl:variable>
511           <xsl:if test="$docbaseuri != ''" >
512             <xsl:value-of select="$docbaseuri"/>
513           </xsl:if>
514         </xsl:otherwise>
515       </xsl:choose>
516     </xsl:variable>
517   
518     <!-- Form the href information -->
519     <xsl:if test="$baseuri != ''">
520       <xsl:value-of select="$baseuri"/>
521       <xsl:if test="substring($target.href,1,1) != '#'">
522         <!--xsl:text>/</xsl:text-->
523       </xsl:if>
524     </xsl:if>
525     <!-- optionally turn off frag for PDF references -->
526     <xsl:if test="not($insert.olink.pdf.frag = 0 and
527           translate(substring($baseuri, string-length($baseuri) - 3),
528                     'PDF', 'pdf') = '.pdf'
529           and starts-with($target.href, '#') )">
530       <xsl:value-of select="$target.href"/>
531     </xsl:if>
532   </xsl:if>
533 </xsl:template>
534
535 <xsl:template name="olink.hottext">
536   <xsl:param name="target.database"/>
537   <xsl:param name="olink.lang" select="''"/>
538   <xsl:param name="olink.key" select="''"/>
539   <xsl:param name="referrer" select="."/>
540   <xsl:param name="xrefstyle">
541     <xsl:choose>
542       <xsl:when test="@role and not(@xrefstyle) 
543                       and $use.role.as.xrefstyle != 0">
544         <xsl:value-of select="@role"/>
545       </xsl:when>
546       <xsl:otherwise>
547         <xsl:value-of select="@xrefstyle"/>
548       </xsl:otherwise>
549     </xsl:choose>
550   </xsl:param>
551
552   <xsl:choose>
553     <!-- If it has elements or text (not just PI or comment) -->
554     <xsl:when test="child::text() or child::*">
555       <xsl:apply-templates/>
556     </xsl:when>
557     <xsl:when test="$olink.key != ''">
558       <!-- Get the xref text for this record -->
559       <xsl:variable name="xref.text" >
560         <xsl:for-each select="$target.database" >
561           <xsl:value-of select="key('targetptr-key', $olink.key)/xreftext" />
562         </xsl:for-each>
563       </xsl:variable>
564
565       <xsl:variable name="xref.number" >
566         <xsl:for-each select="$target.database" >
567           <xsl:value-of select="key('targetptr-key', $olink.key)/@number" />
568         </xsl:for-each>
569       </xsl:variable>
570
571       <xsl:variable name="target.elem" >
572         <xsl:for-each select="$target.database" >
573           <xsl:value-of select="key('targetptr-key', $olink.key)/@element" />
574         </xsl:for-each>
575       </xsl:variable>
576
577       <xsl:variable name="lang">
578         <xsl:variable name="candidate">
579           <xsl:for-each select="$target.database" >
580             <xsl:value-of 
581                       select="key('targetptr-key', $olink.key)/@lang" />
582           </xsl:for-each>
583         </xsl:variable>
584         <xsl:choose>
585           <xsl:when test="$candidate != ''">
586             <xsl:value-of select="$candidate"/>
587           </xsl:when>
588           <xsl:otherwise>
589             <xsl:value-of select="$olink.lang"/>
590           </xsl:otherwise>
591         </xsl:choose>
592       </xsl:variable>
593
594       <xsl:variable name="targetdoc">
595         <xsl:value-of select="substring-before($olink.key, '/')"/>
596       </xsl:variable>
597
598       <xsl:choose>
599         <xsl:when test="$xrefstyle != '' and
600                         starts-with(normalize-space($xrefstyle), 'select:') and
601                         (contains($xrefstyle, 'nodocname') or
602                         contains($xrefstyle, 'nopage')) and
603                         not(contains($xrefstyle, 'title')) and
604                         not(contains($xrefstyle, 'label'))"> 
605           <xsl:value-of select="$xref.text"/>
606         </xsl:when>
607         <xsl:when test="$xrefstyle != ''">
608           <xsl:if test="$olink.debug != 0">
609             <xsl:message>
610               <xsl:text>xrefstyle is '</xsl:text>
611               <xsl:value-of select="$xrefstyle"/>
612               <xsl:text>'.</xsl:text>
613             </xsl:message>
614           </xsl:if>
615           <xsl:variable name="template">
616             <xsl:choose>
617               <xsl:when test="starts-with(normalize-space($xrefstyle),
618                                           'select:')">
619                 <xsl:call-template name="make.gentext.template">
620                   <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
621                   <xsl:with-param name="purpose" select="'olink'"/>
622                   <xsl:with-param name="referrer" select="."/>
623                   <xsl:with-param name="target.elem" select="$target.elem"/>
624                 </xsl:call-template>
625               </xsl:when>
626               <xsl:when test="starts-with(normalize-space($xrefstyle),
627                                           'template:')">
628                 <xsl:value-of select="substring-after(
629                                  normalize-space($xrefstyle), 'template:')"/>
630               </xsl:when>
631               <xsl:otherwise>
632                 <!-- Look for Gentext template with @style attribute -->
633                 <!-- Must compare to no style value because gentext.template
634                      falls back to no style -->
635
636                 <xsl:variable name="xref-context">
637                   <xsl:call-template name="gentext.template">
638                     <xsl:with-param name="context" select="'xref'"/>
639                     <xsl:with-param name="name" select="$target.elem"/>
640                     <xsl:with-param name="lang" select="$lang"/>
641                   </xsl:call-template>
642                 </xsl:variable>
643
644                 <xsl:variable name="styled-xref-context">
645                   <xsl:call-template name="gentext.template">
646                     <xsl:with-param name="context" select="'xref'"/>
647                     <xsl:with-param name="name" select="$target.elem"/>
648                     <xsl:with-param name="lang" select="$lang"/>
649                     <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
650                   </xsl:call-template>
651                 </xsl:variable>
652
653                 <xsl:variable name="xref-number-context">
654                   <xsl:call-template name="gentext.template">
655                     <xsl:with-param name="context" select="'xref-number'"/>
656                     <xsl:with-param name="name" select="$target.elem"/>
657                     <xsl:with-param name="lang" select="$lang"/>
658                   </xsl:call-template>
659                 </xsl:variable>
660
661                 <xsl:variable name="styled-xref-number-context">
662                   <xsl:call-template name="gentext.template">
663                     <xsl:with-param name="context" select="'xref-number'"/>
664                     <xsl:with-param name="name" select="$target.elem"/>
665                     <xsl:with-param name="lang" select="$lang"/>
666                     <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
667                   </xsl:call-template>
668                 </xsl:variable>
669
670                 <xsl:variable name="xref-number-and-title-context">
671                   <xsl:call-template name="gentext.template">
672                     <xsl:with-param name="context" 
673                                     select="'xref-number-and-title'"/>
674                     <xsl:with-param name="name" select="$target.elem"/>
675                     <xsl:with-param name="lang" select="$lang"/>
676                   </xsl:call-template>
677                 </xsl:variable>
678
679                 <xsl:variable name="styled-xref-number-and-title-context">
680                   <xsl:call-template name="gentext.template">
681                     <xsl:with-param name="context" 
682                                     select="'xref-number-and-title'"/>
683                     <xsl:with-param name="name" select="$target.elem"/>
684                     <xsl:with-param name="lang" select="$lang"/>
685                     <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
686                   </xsl:call-template>
687                 </xsl:variable>
688
689                 <xsl:choose>
690                   <xsl:when test="$xref-number-and-title-context != 
691                                  $styled-xref-number-and-title-context and
692                                  $xref.number != '' and
693                                  $xref.with.number.and.title != 0">
694                     <xsl:value-of 
695                             select="$styled-xref-number-and-title-context"/>
696                   </xsl:when>
697                   <xsl:when test="$xref-number-context != 
698                                  $styled-xref-number-context and
699                                  $xref.number != ''">
700                     <xsl:value-of select="$styled-xref-number-context"/>
701                   </xsl:when>
702                   <xsl:when test="$xref-context != $styled-xref-context">
703                     <xsl:value-of select="$styled-xref-context"/>
704                   </xsl:when>
705                   <xsl:when test="$xref-number-and-title-context != '' and
706                                  $xref.number != '' and
707                                  $xref.with.number.and.title != 0">
708                     <xsl:value-of 
709                             select="$xref-number-and-title-context"/>
710                     <xsl:if test="$olink.debug">
711                       <xsl:message>
712                         <xsl:text>Olink error: no gentext template</xsl:text>
713                         <xsl:text> exists for xrefstyle '</xsl:text>
714                         <xsl:value-of select="$xrefstyle"/>
715                         <xsl:text>' for element '</xsl:text>
716                         <xsl:value-of select="$target.elem"/>
717                         <xsl:text>' in language '</xsl:text>
718                         <xsl:value-of select="$lang"/>
719                         <xsl:text>' in context 'xref-number-and-title</xsl:text>
720                         <xsl:text>'. Using template without @style.</xsl:text>
721                       </xsl:message>
722                     </xsl:if>
723                   </xsl:when>
724                   <xsl:when test="$xref-number-context != '' and
725                                  $xref.number != ''">
726                     <xsl:value-of select="$xref-number-context"/>
727                     <xsl:if test="$olink.debug">
728                       <xsl:message>
729                         <xsl:text>Olink error: no gentext template</xsl:text>
730                         <xsl:text> exists for xrefstyle '</xsl:text>
731                         <xsl:value-of select="$xrefstyle"/>
732                         <xsl:text>' for element '</xsl:text>
733                         <xsl:value-of select="$target.elem"/>
734                         <xsl:text>' in language '</xsl:text>
735                         <xsl:value-of select="$lang"/>
736                         <xsl:text>' in context 'xref-number</xsl:text>
737                         <xsl:text>'. Using template without @style.</xsl:text>
738                       </xsl:message>
739                     </xsl:if>
740                   </xsl:when>
741                   <xsl:when test="$xref-context != ''">
742                     <xsl:value-of select="$xref-context"/>
743                     <xsl:if test="$olink.debug">
744                       <xsl:message>
745                         <xsl:text>Olink error: no gentext template</xsl:text>
746                         <xsl:text> exists for xrefstyle '</xsl:text>
747                         <xsl:value-of select="$xrefstyle"/>
748                         <xsl:text>' for element '</xsl:text>
749                         <xsl:value-of select="$target.elem"/>
750                         <xsl:text>' in language '</xsl:text>
751                         <xsl:value-of select="$lang"/>
752                         <xsl:text>' in context 'xref</xsl:text>
753                         <xsl:text>'. Using template without @style.</xsl:text>
754                       </xsl:message>
755                     </xsl:if>
756                   </xsl:when>
757                   <xsl:otherwise>
758                     <xsl:message>
759                       <xsl:text>Olink error: no gentext template</xsl:text>
760                       <xsl:text> exists for xrefstyle '</xsl:text>
761                       <xsl:value-of select="$xrefstyle"/>
762                       <xsl:text>' for element '</xsl:text>
763                       <xsl:value-of select="$target.elem"/>
764                       <xsl:text>' in language '</xsl:text>
765                       <xsl:value-of select="$lang"/>
766                       <xsl:text>'. Trying '%t'.</xsl:text>
767                     </xsl:message>
768                     <xsl:value-of select="'%t'"/>
769                   </xsl:otherwise>
770                 </xsl:choose>
771               </xsl:otherwise>
772             </xsl:choose>
773           </xsl:variable>
774
775           <xsl:if test="$olink.debug != 0">
776             <xsl:message>
777               <xsl:text>Olink debug: xrefstyle template is '</xsl:text>
778               <xsl:value-of select="$template"/>
779               <xsl:text>'.</xsl:text>
780             </xsl:message>
781           </xsl:if>
782
783           <xsl:call-template name="substitute-markup">
784             <xsl:with-param name="template" select="$template"/>
785             <xsl:with-param name="title">
786               <xsl:for-each select="$target.database" >
787                 <xsl:value-of select="key('targetptr-key', $olink.key)/ttl" />
788               </xsl:for-each>
789             </xsl:with-param>
790             <xsl:with-param name="label">
791               <xsl:for-each select="$target.database" >
792                 <xsl:value-of 
793                         select="key('targetptr-key', $olink.key)/@number" />
794               </xsl:for-each>
795             </xsl:with-param>
796             <xsl:with-param name="pagenumber">
797               <xsl:for-each select="$target.database" >
798                 <xsl:value-of 
799                         select="key('targetptr-key', $olink.key)/@page" />
800               </xsl:for-each>
801             </xsl:with-param>
802             <xsl:with-param name="docname">
803               <xsl:for-each select="$target.database" >
804                 <xsl:value-of 
805                        select="key('targetdoc-key', $targetdoc)/div[1]/ttl" />
806               </xsl:for-each>
807             </xsl:with-param>
808           </xsl:call-template>
809         </xsl:when>
810
811         <xsl:when test="$use.local.olink.style != 0">
812
813           <xsl:variable name="template">
814             <xsl:call-template name="gentext.template">
815               <xsl:with-param name="context" select="'xref'"/>
816               <xsl:with-param name="name" select="$target.elem"/>
817               <xsl:with-param name="lang" select="$lang"/>
818             </xsl:call-template>
819           </xsl:variable>
820
821           <xsl:call-template name="substitute-markup">
822             <xsl:with-param name="template" select="$template"/>
823             <xsl:with-param name="title">
824               <xsl:for-each select="$target.database" >
825                 <xsl:value-of select="key('targetptr-key', $olink.key)/ttl" />
826               </xsl:for-each>
827             </xsl:with-param>
828             <xsl:with-param name="label">
829               <xsl:for-each select="$target.database" >
830                 <xsl:value-of 
831                           select="key('targetptr-key', $olink.key)/@number" />
832               </xsl:for-each>
833             </xsl:with-param>
834           </xsl:call-template>
835         </xsl:when>
836         <xsl:when test="$xref.text !=''">
837           <xsl:value-of select="$xref.text"/>
838         </xsl:when>
839         <xsl:otherwise>
840           <xsl:message>
841             <xsl:text>Olink error: no generated text for </xsl:text>
842             <xsl:text>targetdoc/targetptr/lang = '</xsl:text>
843             <xsl:value-of select="$olink.key"/>
844             <xsl:text>'.</xsl:text>
845           </xsl:message>
846           <xsl:text>????</xsl:text>
847         </xsl:otherwise>
848       </xsl:choose>
849     </xsl:when>
850     <xsl:when test="@targetdoc != '' or @targetptr != ''">
851       <xsl:message>
852         <xsl:text>Olink error: no generated text for </xsl:text>
853         <xsl:text>targetdoc/targetptr/lang = '</xsl:text>
854         <xsl:value-of select="$olink.key"/>
855         <xsl:text>'.</xsl:text>
856       </xsl:message>
857       <xsl:text>????</xsl:text>
858     </xsl:when>
859     <xsl:otherwise>
860       <!-- old style olink -->
861       <xsl:call-template name="olink.outline">
862         <xsl:with-param name="outline.base.uri"
863                         select="unparsed-entity-uri(@targetdocent)"/>
864         <xsl:with-param name="localinfo" select="@localinfo"/>
865         <xsl:with-param name="return" select="'xreftext'"/>
866       </xsl:call-template>
867     </xsl:otherwise>
868   </xsl:choose>
869 </xsl:template>
870
871 <xsl:template match="*" mode="olink.docname.markup">
872   <!-- No-op for now -->
873 </xsl:template>
874
875 <xsl:template name="targetpath">
876   <xsl:param name="dirnode" />
877   <xsl:param name="targetdoc" select="''"/>
878
879 <!-- 
880 <xsl:message>dirnode is <xsl:value-of select="$dirnode/@name"/></xsl:message>
881 <xsl:message>targetdoc is <xsl:value-of select="$targetdoc"/></xsl:message>
882 -->
883   <!-- recursive template generates path to olink target directory -->
884   <xsl:choose>
885     <!-- Have we arrived at the final path step? -->
886     <xsl:when test="$dirnode/child::document[@targetdoc = $targetdoc]">
887       <!-- We are done -->
888     </xsl:when>
889     <!-- Have we reached the top without a match? -->
890     <xsl:when test="name($dirnode) != 'dir'" >
891         <xsl:message>Olink error: cannot locate targetdoc <xsl:value-of select="$targetdoc"/> in sitemap</xsl:message>
892     </xsl:when>
893     <!-- Is the target in a descendant? -->
894     <xsl:when test="$dirnode/descendant::document/@targetdoc = $targetdoc">
895       <xsl:variable name="step" select="$dirnode/child::dir[descendant::document/@targetdoc = $targetdoc]"/>
896       <xsl:if test = "$step">
897         <xsl:value-of select="$step/@name"/>
898         <xsl:text>/</xsl:text>
899       </xsl:if>
900       <!-- Now recurse with the child -->
901       <xsl:call-template name="targetpath" >
902         <xsl:with-param name="dirnode" select="$step"/>
903         <xsl:with-param name="targetdoc" select="$targetdoc"/>
904       </xsl:call-template>
905     </xsl:when>
906     <!-- Otherwise we need to move up a step -->
907     <xsl:otherwise>
908       <xsl:if test="$dirnode/parent::dir">
909         <xsl:text>../</xsl:text>
910       </xsl:if>
911       <xsl:call-template name="targetpath" >
912         <xsl:with-param name="dirnode" select="$dirnode/parent::*"/>
913         <xsl:with-param name="targetdoc" select="$targetdoc"/>
914       </xsl:call-template>
915     </xsl:otherwise>
916   </xsl:choose>
917 </xsl:template>
918
919 <xsl:template name="olink.page.citation">
920   <xsl:param name="olink.key" select="''"/>
921   <xsl:param name="olink.lang" select="'en'"/>
922   <xsl:param name="target.database"/>
923   <xsl:param name="linkend" select="''"/>
924   <xsl:param name="xrefstyle">
925     <xsl:choose>
926       <xsl:when test="@role and not(@xrefstyle) 
927                       and $use.role.as.xrefstyle != 0">
928         <xsl:value-of select="@role"/>
929       </xsl:when>
930       <xsl:otherwise>
931         <xsl:value-of select="@xrefstyle"/>
932       </xsl:otherwise>
933     </xsl:choose>
934   </xsl:param>
935
936   <xsl:variable name="targetdoc">
937     <xsl:value-of select="substring-before($olink.key, '/')"/>
938   </xsl:variable>
939
940   <xsl:choose>
941     <xsl:when test="$linkend != ''">
942       <xsl:call-template name="xref.page.citation">
943         <xsl:with-param name="linkend" select="@linkend"/>
944         <xsl:with-param name="target" select="key('id', $linkend)"/>
945         <xsl:with-param name="xrefstyle" select="$xrefstyle"/>
946       </xsl:call-template>
947     </xsl:when>
948     <xsl:when test="not(starts-with(normalize-space($xrefstyle),
949                         'select:') 
950                 and (contains($xrefstyle, 'page')
951                      or contains($xrefstyle, 'Page')))
952                 and $current.docid != '' 
953                 and $current.docid != $targetdoc
954                 and $insert.olink.page.number = 'yes' ">
955   
956       <xsl:variable name="page-number">
957         <xsl:for-each select="$target.database" >
958           <xsl:value-of 
959                  select="key('targetptr-key', $olink.key)/@page" />
960         </xsl:for-each>
961       </xsl:variable>
962   
963       <xsl:if test="$page-number != ''">
964         <xsl:call-template name="substitute-markup">
965           <xsl:with-param name="template">
966             <xsl:call-template name="gentext.template">
967               <xsl:with-param name="name" select="'olink.page.citation'"/>
968               <xsl:with-param name="context" select="'xref'"/>
969               <xsl:with-param name="lang" select="$olink.lang"/>
970             </xsl:call-template>
971           </xsl:with-param>
972           <xsl:with-param name="pagenumber" select="$page-number"/>
973         </xsl:call-template>
974       </xsl:if>
975   
976     </xsl:when>
977   </xsl:choose>
978 </xsl:template>
979
980 <xsl:template name="olink.document.citation">
981   <xsl:param name="olink.key" select="''"/>
982   <xsl:param name="olink.lang" select="'en'"/>
983   <xsl:param name="target.database"/>
984   <xsl:param name="xrefstyle">
985     <xsl:choose>
986       <xsl:when test="@role and not(@xrefstyle) 
987                       and $use.role.as.xrefstyle != 0">
988         <xsl:value-of select="@role"/>
989       </xsl:when>
990       <xsl:otherwise>
991         <xsl:value-of select="@xrefstyle"/>
992       </xsl:otherwise>
993     </xsl:choose>
994   </xsl:param>
995
996   <xsl:variable name="page">
997     <xsl:for-each select="$target.database" >
998       <xsl:value-of 
999              select="key('targetptr-key', $olink.key)/@page" />
1000     </xsl:for-each>
1001   </xsl:variable>
1002
1003   <xsl:variable name="targetdoc">
1004     <xsl:value-of select="substring-before($olink.key, '/')"/>
1005   </xsl:variable>
1006
1007   <xsl:variable name="targetptr">
1008     <xsl:value-of 
1009           select="substring-before(substring-after($olink.key, '/'), '/')"/>
1010   </xsl:variable>
1011
1012   <!-- Don't add docname if pointing to root element -->
1013   <xsl:variable name="rootptr">
1014     <xsl:for-each select="$target.database" >
1015       <xsl:value-of 
1016              select="key('targetdoc-key', $targetdoc)/div[1]/@targetptr" />
1017     </xsl:for-each>
1018   </xsl:variable>
1019
1020   <xsl:variable name="docname">
1021     <xsl:for-each select="$target.database" >
1022       <xsl:value-of 
1023              select="key('targetdoc-key', $targetdoc)/div[1]/ttl" />
1024     </xsl:for-each>
1025   </xsl:variable>
1026
1027   <xsl:if test="not(starts-with(normalize-space($xrefstyle), 'select:') 
1028               and (contains($xrefstyle, 'docname')))
1029               and ($olink.doctitle = 'yes' or $olink.doctitle = '1')
1030               and $current.docid != '' 
1031               and $rootptr != $targetptr
1032               and $current.docid != $targetdoc
1033               and $docname != ''">
1034     <xsl:call-template name="substitute-markup">
1035       <xsl:with-param name="template">
1036         <xsl:call-template name="gentext.template">
1037           <xsl:with-param name="name" select="'olink.document.citation'"/>
1038           <xsl:with-param name="context" select="'xref'"/>
1039           <xsl:with-param name="lang" select="$olink.lang"/>
1040         </xsl:call-template>
1041       </xsl:with-param>
1042       <xsl:with-param name="docname" select="$docname"/>
1043       <xsl:with-param name="pagenumber" select="$page"/>
1044     </xsl:call-template>
1045   </xsl:if>
1046 </xsl:template>
1047
1048 <xsl:template name="xref.page.citation">
1049   <!-- Determine if this xref should have a page citation.
1050        Context node is the xref or local olink element -->
1051   <xsl:param name="linkend" select="@linkend"/>
1052   <xsl:param name="target" select="key('id', $linkend)"/>
1053   <xsl:param name="xrefstyle">
1054     <xsl:choose>
1055       <xsl:when test="@role and not(@xrefstyle) 
1056                       and $use.role.as.xrefstyle != 0">
1057         <xsl:value-of select="@role"/>
1058       </xsl:when>
1059       <xsl:otherwise>
1060         <xsl:value-of select="@xrefstyle"/>
1061       </xsl:otherwise>
1062     </xsl:choose>
1063   </xsl:param>
1064
1065   <xsl:if test="not(starts-with(normalize-space($xrefstyle),
1066                     'select:') != '' 
1067                 and (contains($xrefstyle, 'page')
1068                      or contains($xrefstyle, 'Page')))
1069                 and ( $insert.xref.page.number = 'yes' 
1070                    or $insert.xref.page.number = '1')
1071                 or local-name($target) = 'para'">
1072     <xsl:apply-templates select="$target" mode="page.citation">
1073       <xsl:with-param name="id" select="$linkend"/>
1074     </xsl:apply-templates>
1075   </xsl:if>
1076 </xsl:template>
1077
1078 </xsl:stylesheet>
1079