Project

Profile

Help

How to connect?
Download (25.7 KB) Statistics
| Branch: | Revision:

he / tools / chunk-javadoc.xsl @ 01d6fdb6

1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="urn:local.function" xmlns:h="http://www.w3.org/1999/xhtml"
4
    exclude-result-prefixes="f xs h">
5

    
6
    <!--
7
Stylesheet by to produce XML output from JavaDoc suitable for use by a Saxon-CE
8
powered JavaDoc viewer. 
9

    
10
1.  principal input: the input to this stylesheet is the XML generated by a
11
    custom doclet,  jeldoclet.jar - a rewrite of the original open source
12
    tool designed to preserve markup in comments and to convert html-style
13
    markup to be well-formed XML (using tagsoup).
14
2.  secondary input: the file, p-jeldoclet-out.xml is retrieved from the 
15
    same location as the principle input
16

    
17
    Outputs:
18

    
19
3.  output 1. A set of files describing the Java source packages, with one 
20
    file for each Java package. Each file contains descriptions of all the
21
    classes for the represented package.
22
4.  output 2. The file 'javadoc-packages' containing the comments for
23
    each package.
24
5.  output 3 (not yet finished). The file 'javadoc-types' lists all types with codes to 
25
    indicate class or class-member
26
6   output 4. The file 'javadoc-tree.xml' used to generate the outline
27
    view of all packages/classes/sub-classes
28

    
29
About JavaDoc formatting
30

    
31
The format of JavaDoc comments conforms to a set of rules described here:
32
http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html
33

    
34
A comment comprises a first sentence, followed optionally by further comments.
35
HTML markup is used within the comments - of note: sometimes self-closed
36
<p/> tags are sometimes used as separators rather than wrappers. Following the
37
comments there is a blank line, and after this the parameters are described
38
with each parameter name prefixed with a '@' character
39

    
40
History
41

    
42
12 Sept 2012: First implementation by Phil Fearon for Saxonica
43

    
44
02 Dec 2015: Update by Debbie Lockett - fix bugs #1906 involving Enum classes (add enumConstants, etc); 
45
 #1821 to include all known implementing classes (for interfaces) and subclasses info
46
 
47
06 Jun 2018: Update by Debbie Lockett - bug #3795: fix broken javadoc links when fully
48
qualified class name not provided: update template match="tag[@kind]" to handle these (as for local
49
methods)
50

    
51
24 Aug 2018: Update by Debbie Lockett - update to fully qualified class name for @see tags
52
(attribute[@name='@see'])
53

    
54
12 Dec 2018: Update by Debbie Lockett - bug #4058: filter out 'package-private' classes, interfaces, members
55
as required; implementing-classes key correction
56

    
57
-->
58
    <xsl:param name="base-output" select="''"/>
59

    
60
    <xsl:output method="xml" indent="no"/>
61

    
62
    <xsl:template match="@*">
63
        <xsl:copy-of select="." />
64
    </xsl:template>
65
    
66
    <xsl:template match="*">
67
        <xsl:element name="{local-name(.)}">
68
            <xsl:apply-templates select="@*|node()"/>
69
        </xsl:element>
70
      
71
    </xsl:template>
72
    
73
    
74
    
75
    <xsl:template match="*" mode="tag-only">
76
        <xsl:apply-templates select="node()" mode="tag-only"/>
77
    </xsl:template>
78
    
79
    <xsl:template match="sentence">
80
        <sentence>
81
            <xsl:apply-templates select="node()" mode="tag-only" />
82
        </sentence>
83
    </xsl:template>
84
    
85

    
86

    
87
    <xsl:template match="attribute[@name = ('@param','@throws','@exception')]"/>
88

    
89
    <xsl:template match="attribute[@name eq '@return']">
90
        <return>
91
            <xsl:apply-templates/>
92
        </return>
93
    </xsl:template>
94
    
95
    <xsl:template match="attribute[@name eq '@see']">
96
        <xsl:choose>
97
            <!-- @see "string" or @see <a/> etc -->
98
            <xsl:when test='body/div/element() or starts-with(normalize-space(.), """")'>
99
                <attribute>
100
                    <xsl:apply-templates select="@*|node()"/>
101
                </attribute>
102
            </xsl:when>
103
            <!-- @see package.class#member
104
                Note, currently don't handle use of label: @see package.class#member label -->
105
            <xsl:otherwise>
106
                <attribute name="@see" see="java">
107
                    <xsl:value-of select="f:fully-qualified-ref(.)"/>
108
                </attribute>
109
            </xsl:otherwise>
110
        </xsl:choose>
111
    </xsl:template>
112

    
113
    <xsl:template match="methods">
114
        <methods>
115
            <xsl:apply-templates select="constructor[@visibility ne 'package-private']">
116
                <xsl:sort select="upper-case(@name)"/>
117
                <xsl:sort select="count(params/param)"/>
118
            </xsl:apply-templates>
119
            <xsl:apply-templates select="method[@visibility ne 'package-private']">
120
                <xsl:sort select="upper-case(@name)"/>
121
                <xsl:sort select="count(params/param)"/>
122
            </xsl:apply-templates>
123
        </methods>
124
    </xsl:template>
125

    
126
    <xsl:template match="fields">
127
        <fields>
128
            <xsl:apply-templates select="field[@visibility ne 'package-private']">
129
                <xsl:sort select="upper-case(@name)"/>
130
            </xsl:apply-templates>
131
        </fields>
132
    </xsl:template>
133
    
134
    <xsl:template match="enumConstants">
135
        <enumConstants>
136
            <xsl:apply-templates select="enumConstant[@visibility ne 'package-private']">
137
                <xsl:sort select="upper-case(@name)"/>
138
            </xsl:apply-templates>
139
        </enumConstants>
140
    </xsl:template>
141

    
142

    
143
    <!-- not yet required so omit from output -->
144
    <xsl:template match="interface/fields|interface/methods"/>
145

    
146
    <!-- we shouldn't show importedtypes - only for resolving tag links -->
147
    <xsl:template match="importedTypes"/>
148

    
149
    <!-- Only <tag kind="see"/> converted to links; <tag kind="code"/> should just be wrapped as <code/> -->
150
    <xsl:template match="tag[@kind eq 'code']" mode="tag-only">
151
        <code>
152
            <xsl:apply-templates select="node()" mode="tag-only" />
153
        </code>
154
    </xsl:template>
155
    
156
    <xsl:template match="tag[@kind eq 'see']" mode="#default tag-only">
157
        <xsl:choose>
158
            <xsl:when test="contains(., '#') and not(starts-with(., '#')) and not(contains(., '.'))">
159
                <tag>
160
                    <xsl:apply-templates select="@*"/>
161
                    <xsl:value-of select="f:fully-qualified-ref(.)"/>
162
                </tag>
163
            </xsl:when>
164
            <xsl:when test="not(contains(., '#')) and not(contains(., '.'))">
165
                <tag>
166
                    <xsl:apply-templates select="@*"/>
167
                    <xsl:value-of select="f:fully-qualified-ref(.)"/>
168
                </tag>
169
            </xsl:when>
170
            <xsl:otherwise>
171
                <xsl:copy>
172
                    <xsl:apply-templates select="node()|@*"/>
173
                </xsl:copy>
174
            </xsl:otherwise>
175
        </xsl:choose>
176
    </xsl:template>
177
    
178
    <!-- Obtain the fully qualified class name, for a class name given by a node 
179
        (e.g tag[@kind eq 'see'], or attribute[@name eq '@see']).
180
        Attempt to use local importedtypes first to resolve relative references to types. -->
181
    <xsl:function name="f:fully-qualified-ref" as="xs:string">
182
        <xsl:param name="node" as="element()"/>
183
        <xsl:variable name="ref" select="string($node)"/>
184
        <xsl:choose>
185
            <xsl:when test="contains($ref, '#') and not(starts-with($ref, '#')) and not(contains($ref, '.'))">
186
                <xsl:variable name="pre" select="substring-before($ref,'#')"/>
187
                <xsl:variable name="resolved-class" as="element()?">
188
                    <xsl:variable name="local" select="($node/ancestor::class[1]//*[@type eq $pre])[1]"/>
189
                    <xsl:choose>
190
                        <xsl:when test="exists($local)">
191
                            <xsl:sequence select="$local"/>
192
                        </xsl:when>
193
                        <xsl:otherwise>
194
                            <xsl:variable name="global" select="(root($node)//*[@type eq $pre])[1]"/>
195
                            <xsl:choose>
196
                                <xsl:when test="exists($global)">
197
                                    <xsl:sequence select="$global"/>
198
                                </xsl:when>
199
                                <xsl:otherwise>
200
                                    <xsl:variable name="inner"
201
                                        select="($node/ancestor::class[1]/class[@type eq
202
                                        concat(ancestor::class[1]/@type, '.', $pre)])[1]"/>
203
                                    <xsl:choose>
204
                                        <xsl:when test="exists($inner)">
205
                                            <xsl:sequence select="$inner"/>
206
                                        </xsl:when>
207
                                        <xsl:otherwise>
208
                                            <xsl:message>not found!!! <xsl:value-of select="$ref"/>
209
                                                pre <xsl:value-of select="$pre"/>
210
                                            </xsl:message>
211
                                        </xsl:otherwise>
212
                                    </xsl:choose>
213
                                </xsl:otherwise>
214
                            </xsl:choose>
215
                        </xsl:otherwise>
216
                    </xsl:choose>
217
                </xsl:variable>
218
                <xsl:variable name="resolved"
219
                    select="concat(
220
                    $resolved-class/@fulltype,
221
                    substring($ref, string-length($pre) + 1))"/>
222
                <xsl:value-of select="$resolved"/>
223
            </xsl:when>
224
            <xsl:when test="not(contains($ref, '#')) and not(contains($ref, '.'))">
225
                <xsl:variable name="pre" select="$ref"/>
226
                <xsl:variable name="resolved-class" as="element()?">
227
                    <xsl:variable name="local" select="($node/ancestor::class[1]//*[@type eq $pre])[1]"/>
228
                    <xsl:choose>
229
                        <xsl:when test="exists($local)">
230
                            <xsl:sequence select="$local"/>
231
                        </xsl:when>
232
                        <xsl:otherwise>
233
                            <xsl:variable name="global" select="(root($node)//*[@type eq $pre])[1]"/>
234
                            <xsl:choose>
235
                                <xsl:when test="exists($global)">
236
                                    <xsl:sequence select="$global"/>
237
                                </xsl:when>
238
                                <xsl:otherwise>
239
                                    <xsl:variable name="inner"
240
                                        select="($node/ancestor::class[1]/class[@type eq
241
                                        concat(ancestor::class[1]/@type, '.', $pre)])[1]"/>
242
                                    <xsl:choose>
243
                                        <xsl:when test="exists($inner)">
244
                                            <xsl:sequence select="$inner"/>
245
                                        </xsl:when>
246
                                        <xsl:otherwise>
247
                                            <xsl:message>not found!!! <xsl:value-of select="$ref"/>
248
                                                pre <xsl:value-of select="$pre"/>
249
                                            </xsl:message>
250
                                        </xsl:otherwise>
251
                                    </xsl:choose>
252
                                </xsl:otherwise>
253
                            </xsl:choose>
254
                        </xsl:otherwise>
255
                    </xsl:choose>
256
                </xsl:variable>
257
                <xsl:variable name="resolved" select="$resolved-class/@fulltype"/>
258
                <xsl:value-of select="($resolved, $pre)[1]"/>
259
            </xsl:when>
260
            <xsl:otherwise>
261
                <xsl:value-of select="$ref"/>
262
            </xsl:otherwise>
263
        </xsl:choose>
264
    </xsl:function>
265

    
266
    <xsl:template match="param/type|method/type">
267
        <!-- Use of @preamble may now be unnecessary: type/@fulltype should not contain spaces anymore.
268
            But retain just in case. -->
269
        <xsl:variable name="post-space" select="f:last-substring-after(@fulltype, 32)"/>
270
        <xsl:variable name="fulltype"
271
            select="if ($post-space eq '') then @fulltype else $post-space"/>
272

    
273
        <type fulltype="{$fulltype}">
274
            <xsl:copy-of select="@* except @fulltype"/>
275
            <xsl:variable name="preamble"
276
                select="substring(@fulltype, 0, string-length(@fulltype) - (string-length($post-space) - 1))"/>
277
            <xsl:if test="$preamble ne ''">
278
                <xsl:attribute name="preamble" select="$preamble"/>
279
            </xsl:if>
280
            <xsl:apply-templates/>
281
        </type>
282

    
283
    </xsl:template>
284

    
285
    <xsl:function name="f:last-substring-after">
286
        <xsl:param name="text"/>
287
        <xsl:param name="char" as="xs:double"/>
288
        <xsl:variable name="last" as="xs:integer?"
289
            select="index-of(string-to-codepoints($text), $char)[last()]"/>
290
        <xsl:sequence select="if (exists($last)) then substring($text, $last + 1) else $text"/>
291
    </xsl:function>
292
    
293
    <!-- This template is not actually called anywhere, but it exists to be able to produce javadoc-packages.xml output only. -->
294
    <xsl:template name="javadoc-package">
295
       <!-- <xsl:result-document href="javadoc-packages.xml">-->
296
        <xsl:message><xsl:copy-of select="doc(resolve-uri('p-jeldoclet-out.xml', base-uri()))/package-comments/comment"/></xsl:message>
297
            <article id="javadoc-packages">
298
                <xsl:apply-templates mode="pack"
299
                    select="doc(resolve-uri('p-jeldoclet-out.xml', base-uri()))/package-comments/comment" />
300
            </article>
301
        <!--</xsl:result-document>-->
302
    </xsl:template>
303

    
304
    <xsl:template match="/">
305

    
306
        <!-- chunk xml at package level (default) -->
307

    
308
        <xsl:for-each-group select="jel/class" group-by="@package">
309
            <xsl:sort select="@package"/>
310
            <xsl:variable name="package" select="current-grouping-key()"/>
311
            <xsl:result-document href="{$base-output}/{concat('packages/', $package, '.xml')}">
312
                <package id="{$package}">
313
                    <xsl:for-each select="current-group()">
314
                        <xsl:sort select="upper-case(@type)"/>
315
                        <xsl:apply-templates select="."/>
316
                    </xsl:for-each>
317
                </package>
318
            </xsl:result-document>
319
        </xsl:for-each-group>
320

    
321

    
322
        <xsl:result-document href="{$base-output}/javadoc-packages.xml">
323
            <article id="javadoc-packages">
324
                <xsl:apply-templates mode="pack"
325
                    select="doc(resolve-uri('p-jeldoclet-out.xml', base-uri()))/package-comments/comment" />
326
            </article>
327
        </xsl:result-document>
328

    
329
        <!-- Produce index of classes and members - used in javadoc search.
330
            Group into hierarchy of packages, classes and members. -->
331
        <xsl:result-document href="{$base-output}/javadoc-types.xml">
332
            <packages title="Search Data">
333

    
334
                <xsl:for-each-group select="jel/class" group-by="@package">
335
                    <xsl:sort select="@package"/>
336
                    <j id="{@package}" in="p">
337

    
338
                        <xsl:apply-templates select="current-group()" mode="deeptree">
339
                            <xsl:sort select="upper-case(@type)"/>
340
                        </xsl:apply-templates>
341

    
342
                    </j>
343
                </xsl:for-each-group>
344

    
345
            </packages>
346
        </xsl:result-document>
347

    
348
        <!-- Group into hierarchy of packages, classes and nestedclasses (those with a '.' in their name).
349
            javadoc-tree.xml used for index in nav list. -->
350
        <xsl:result-document href="{$base-output}/javadoc-tree.xml">
351
            <packages id="javadoc" title="Java API">
352

    
353
                <xsl:for-each-group select="jel/class" group-by="@package">
354
                    <xsl:sort select="@package"/>
355
                    <j id="{@package}" in="p">
356

    
357
                        <xsl:apply-templates select="current-group()" mode="tree">
358
                            <xsl:sort select="upper-case(@type)"/>
359
                        </xsl:apply-templates>
360

    
361
                    </j>
362
                </xsl:for-each-group>
363

    
364
            </packages>
365
        </xsl:result-document>
366

    
367
    </xsl:template>
368

    
369
    <xsl:template match="class" mode="tree">
370
        <xsl:variable name="afterDot" select="substring-after(@type,'.')"/>
371
        <xsl:variable name="type"
372
            select="if (string-length($afterDot) gt 0) then $afterDot else @type"/>
373
        <xsl:variable name="has-nonPP-implementing-classes" as="xs:boolean" 
374
            select="exists(@interface) and exists(key('implementing-classes', @fulltype)[@visibility ne 'package-private'])" />
375
        <xsl:variable name="has-nonPP-subclasses" as="xs:boolean"
376
            select="exists(key('subclasses-key', @fulltype)[@visibility ne 'package-private'])"/>
377
        <xsl:variable name="has-PP-members-only" as="xs:boolean" 
378
            select="empty((methods/method|methods/constructor|fields/field|enumConstants/enumConstant)[@visibility ne 'package-private'])"/>
379
        
380
        <xsl:if test="@visibility ne 'package-private' or (not($has-PP-members-only) and ($has-nonPP-implementing-classes
381
            or $has-nonPP-subclasses))">
382
            <j id="{$type}" in="{f:get-att-name(.)}">
383
                <xsl:apply-templates select="class" mode="tree">
384
                    <xsl:sort select="@type"/>
385
                </xsl:apply-templates>
386
            </j>
387
        </xsl:if>
388
    </xsl:template>
389
    
390
    <xsl:template match="field|method|enumConstant" mode="deeptree">
391
        <j id="{@name}" in="{substring(name(.), 1, 1)}" qy="{lower-case(@name)}"/>
392
    </xsl:template>
393
    
394
    <xsl:template match="class" mode="deeptree">
395
        <xsl:variable name="afterDot" select="substring-after(@type,'.')"/>
396
        <xsl:variable name="type"
397
            select="if (string-length($afterDot) gt 0) then $afterDot else @type"/>
398
        <xsl:variable name="has-nonPP-implementing-classes" as="xs:boolean" 
399
            select="exists(@interface) and exists(key('implementing-classes', @fulltype)[@visibility ne 'package-private'])" />
400
        <xsl:variable name="has-nonPP-subclasses" as="xs:boolean"
401
            select="exists(key('subclasses-key', @fulltype)[@visibility ne 'package-private'])"/>
402
        <xsl:variable name="has-PP-members-only" as="xs:boolean" 
403
            select="empty((methods/method|methods/constructor|fields/field|enumConstants/enumConstant)[@visibility ne 'package-private'])"/>
404
        
405
        <xsl:if test="@visibility ne 'package-private' or (not($has-PP-members-only) and ($has-nonPP-implementing-classes
406
            or $has-nonPP-subclasses))">
407
            <j id="{$type}" in="{substring(name(.), 1, 1)}" qy="{lower-case($type)}">
408
                <xsl:variable name="methods" select="distinct-values(./methods/method[@visibility ne 'package-private']/@name)"
409
                    as="xs:string*"/>
410
                <xsl:apply-templates select="class|fields/field[@visibility ne'package-private']
411
                    |enumConstants/enumConstant[@visibility ne 'package-private']" mode="deeptree">
412
                    <xsl:sort select="@type"/>
413
                </xsl:apply-templates>
414
                <xsl:variable name="class" select="."/>
415
                <xsl:for-each select="$methods">
416
                    <xsl:variable name="name" select="."/>
417
                    <xsl:apply-templates select="($class/methods/method[@name=$name])[1]" mode="deeptree">
418
                        <xsl:sort select="@name"/>
419
                    </xsl:apply-templates>
420
                </xsl:for-each>
421
            </j>
422
        </xsl:if>
423
    </xsl:template>
424

    
425

    
426
    <xsl:template match="comment" mode="pack">
427
        <section id="{@id}">
428
            <xsl:apply-templates mode="pack" select="*:body/*"/>
429
        </section>
430
    </xsl:template>
431

    
432
    <xsl:template match="*" mode="pack">
433
        <xsl:element name="{local-name(.)}">
434
            <xsl:apply-templates select="node()|@*" mode="pack"/>
435
        </xsl:element>
436
        
437
    </xsl:template>
438
    
439
    <xsl:template match="@*" mode="pack">
440
        <xsl:copy-of select="." />
441
        
442
    </xsl:template>
443
    
444

    
445

    
446
    <xsl:template match="*:hr" mode="pack"/>
447
    <!-- DTD default value - not required -->
448
    <xsl:template match="@shape" mode="pack"/>
449

    
450
    <xsl:template match="*:p[@align = 'center']" mode="pack">
451
        <xsl:if test="not(contains(., 'Saxonica Limited') or contains(., 'Michael H. Kay'))">
452
            <p>
453
                <xsl:apply-templates select="node()|@*" mode="pack"/>
454
            </p>
455
        </xsl:if>
456
    </xsl:template>
457

    
458
    <xsl:template match="text()" mode="pack">
459
        <xsl:analyze-string regex="\{{\s*(@.+?\s+?)(.+?)\}}" select=".">
460
            <xsl:matching-substring>
461
                <xsl:variable name="tag" select="substring(regex-group(1), 2)"/>
462
                <a href="{regex-group(2)}">
463
                    <xsl:attribute name="class" select="concat('java',normalize-space($tag))"/>
464
                    <xsl:value-of select="regex-group(2)"/>
465
                </a>
466
            </xsl:matching-substring>
467
            <xsl:non-matching-substring>
468
                <xsl:sequence select="."/>
469
            </xsl:non-matching-substring>
470
        </xsl:analyze-string>
471
    </xsl:template>
472

    
473
    <xsl:template match="class/@package"/>
474

    
475

    
476
    <xsl:function name="f:get-att-name" as="xs:string">
477
        <xsl:param name="class" as="element()"/>
478
        <xsl:for-each select="$class">
479
            <xsl:choose>
480
                <xsl:when test="exists(@abstract) and xs:boolean(@abstract) eq true()">a</xsl:when>
481
                <xsl:when test="exists(@interface) and xs:boolean(@interface) eq true()">i</xsl:when>
482
                <xsl:otherwise>c</xsl:otherwise>
483
            </xsl:choose>
484
        </xsl:for-each>
485
    </xsl:function>
486

    
487
    <xsl:template match="@*|node()" mode="type">
488
        <xsl:apply-templates select="@* | node()" mode="type"/>
489
    </xsl:template>
490

    
491
    <xsl:template match="method/@name|field/@name|constructor/@name|exception/@type" mode="type">
492
        <m>
493
            <xsl:value-of select="concat(ancestor::class[1]/@fulltype,'.', .)"/>
494
        </m>
495
    </xsl:template>
496

    
497
    <xsl:template match="class/@type" mode="type">
498
        <c>
499
            <xsl:value-of select="../@fulltype"/>
500
        </c>
501
    </xsl:template>
502

    
503
    <xsl:template match="class">
504
        <!-- Don't include class if 'package-private' and no non-package-private classes-implemented-by-interface or
505
            subclasses, or no non-package-private members -->
506
        <xsl:variable name="implementing-classes" as="element(implemented-by)?">
507
            <xsl:call-template name="classes-which-implement-interface"/>
508
        </xsl:variable>
509
        <xsl:variable name="subclasses" as="element(subclasses)?">
510
            <xsl:call-template name="subclasses"/>
511
        </xsl:variable>
512
        <xsl:variable name="has-nonPP-implementing-classes" as="xs:boolean" 
513
            select="exists($implementing-classes)" />
514
        <xsl:variable name="has-nonPP-subclasses" as="xs:boolean" 
515
            select="exists($subclasses)" />
516
        <xsl:variable name="has-PP-members-only" as="xs:boolean" 
517
            select="empty((methods/method|methods/constructor|fields/field|enumConstants/enumConstant)[@visibility ne 'package-private'])"/>
518
        
519
        <!--<xsl:if test="@visibility eq 'package-private' and $has-PP-members-only">
520
            <xsl:message>isPP with PP-members only: <xsl:value-of select="@fulltype"/></xsl:message>
521
        </xsl:if>
522
        <xsl:if test="@visibility eq 'package-private' and empty($implementing-classes) and empty($subclasses)">
523
            <xsl:message>isPP with no nonPP implementing classes or subclasses: <xsl:value-of select="@fulltype"/></xsl:message>
524
        </xsl:if>-->
525
        
526
        <xsl:if test="@visibility ne 'package-private' or (not($has-PP-members-only) and ($has-nonPP-implementing-classes
527
            or $has-nonPP-subclasses))">
528
            <!--<xsl:if test="@visibility eq 'package-private'">
529
                <xsl:message>isPP: <xsl:value-of select="@fulltype"/></xsl:message>
530
            </xsl:if>-->
531
            <class id="{@type}">
532
                <xsl:apply-templates select="@* except @type"/>
533
                <xsl:apply-templates select="node() except class"/>
534
                <xsl:apply-templates select="class">
535
                    <xsl:sort select="upper-case(@type)"/>
536
                </xsl:apply-templates>
537
                <xsl:sequence select="$implementing-classes"/>
538
                <xsl:sequence select="$subclasses"/>
539
            </class>
540
        </xsl:if>
541
    </xsl:template>
542
    
543
    <xsl:template name="classes-which-implement-interface">
544
        <xsl:if test="exists(@interface) and xs:boolean(@interface) eq true() and 
545
            exists(key('implementing-classes', @fulltype)[@visibility ne 'package-private'])">
546
            <implemented-by>
547
                <xsl:for-each select="key('implementing-classes', @fulltype)[@visibility ne 'package-private']">
548
                    <xsl:sort select="upper-case(@type)"/>
549
                    <class fulltype="{@fulltype}" type="{@type}"/>
550
                </xsl:for-each>
551
            </implemented-by>
552
        </xsl:if>
553
    </xsl:template>
554
    
555
    <xsl:key name="implementing-classes" match="class" 
556
        use="(extends/descendant::inherits/interface/@fulltype, implements/descendant::interface/@fulltype)"/>
557
    
558
    <xsl:template name="subclasses">
559
        <xsl:if test="exists(key('subclasses-key', @fulltype)[@visibility ne 'package-private'])">
560
            <subclasses>
561
                <xsl:for-each select="key('subclasses-key', @fulltype)[@visibility ne 'package-private']">
562
                    <xsl:sort select="upper-case(@type)"/>
563
                    <class fulltype="{@fulltype}" type="{@type}"/>
564
                </xsl:for-each>
565
            </subclasses>
566
        </xsl:if>
567
    </xsl:template>
568
    
569
    <xsl:key name="subclasses-key" match="class" use="@superclassfulltype"/>
570

    
571
    <xsl:template match="method/@name|field/@name|constructor/@name|exception/@type|enumConstant/@name">
572
        <xsl:attribute name="id" select="."/>
573
    </xsl:template>
574

    
575
</xsl:stylesheet>
(2-2/15)