Bug 15527: Add a stylesheet for OAI-PMH to aid usability
[koha_ffzg] / koha-tmpl / opac-tmpl / xslt / OAI.xslt
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--
3
4     The contents of this file are subject to the license and copyright
5     detailed in the LICENSE and NOTICE files at the root of the source
6     tree and available online at
7
8     http://www.dspace.org/license/
9
10 -->
11 <xsl:stylesheet version="1.0"
12     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:oai="http://www.openarchives.org/OAI/2.0/"
13     xmlns:koha="http://koha-community.org" xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
14     xmlns:dc="http://purl.org/dc/doc:elements/1.1/" xmlns:marc="http://www.loc.gov/MARC21/slim"
15     xmlns:verb="http://informatik.hu-berlin.de/xmlverbatim"
16     xmlns:oai_id="http://www.openarchives.org/OAI/2.0/oai-identifier"
17     exclude-result-prefixes="oai oai_dc dc marc marcxml verb oai_id">
18
19     <xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01//EN" doctype-system="http://www.w3.org/TR/html4/strict.dtd" />
20
21     <xsl:template match="/">
22         <html>
23             <head>
24                 <title>Koha OAI-PMH Data Provider</title>
25                 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
26                 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
27                 <script src="/opac-tmpl/bootstrap/lib/jquery/jquery.js" type="text/javascript" />
28                 <script src="/opac-tmpl/bootstrap/lib/bootstrap/js/bootstrap.min.js" type="text/javascript" />
29                 <link rel="stylesheet" href="/opac-tmpl/bootstrap/css/bootstrap-theme-oai.css" type="text/css" />
30                 <link rel="stylesheet" href="/opac-tmpl/bootstrap/css/oai.css" type="text/css" />
31             </head>
32             <body>
33                 <div class="container">
34                     <div class="navbar navbar-default" role="navigation">
35                         <div class="navbar-header">
36                             <a class="navbar-brand" href="#">Koha OAI-PMH Data Provider</a>
37                         </div>
38                         <div class="navbar-collapse collapse">
39                             <ul class="nav navbar-nav navbar-right">
40                                 <li>
41                                     <a title="Institutional information">
42                                         <xsl:if test="/oai:OAI-PMH/oai:request/@verb = 'Identify'">
43                                             <xsl:attribute name="class">active</xsl:attribute>
44                                         </xsl:if>
45                                         <xsl:attribute name="href">
46                                             <xsl:value-of
47                                                     select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=Identify')"></xsl:value-of>
48                                         </xsl:attribute>
49                                         Identify
50                                     </a>
51                                 </li>
52                                 <li>
53                                     <a title="Listing available sets">
54                                         <xsl:if test="/oai:OAI-PMH/oai:request/@verb = 'ListSets'">
55                                             <xsl:attribute name="class">active</xsl:attribute>
56                                         </xsl:if>
57                                         <xsl:attribute name="href">
58                                             <xsl:value-of
59                                                     select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListSets')"></xsl:value-of>
60                                         </xsl:attribute>
61                                         Sets
62                                     </a>
63                                 </li>
64                                 <li>
65                                     <a title="Listing records (with metadata)">
66                                         <xsl:if test="/oai:OAI-PMH/oai:request/@verb = 'ListRecords'">
67                                             <xsl:attribute name="class">active</xsl:attribute>
68                                         </xsl:if>
69                                         <xsl:attribute name="href">
70                                             <xsl:value-of
71                                                     select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListRecords&amp;metadataPrefix=oai_dc')"></xsl:value-of>
72                                         </xsl:attribute>
73                                         Records
74                                     </a>
75                                 </li>
76                                 <li>
77                                     <a title="Listing identifiers only">
78                                         <xsl:if test="/oai:OAI-PMH/oai:request/@verb = 'ListIdentifiers'">
79                                             <xsl:attribute name="class">active</xsl:attribute>
80                                         </xsl:if>
81                                         <xsl:attribute name="href">
82                                             <xsl:value-of
83                                                     select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListIdentifiers&amp;metadataPrefix=oai_dc')"></xsl:value-of>
84                                         </xsl:attribute>
85                                         Identifiers
86                                     </a>
87                                 </li>
88                                 <li>
89                                     <a title="Metadata Formats available">
90                                         <xsl:if
91                                                 test="/oai:OAI-PMH/oai:request/@verb = 'ListMetadataFormats'">
92                                             <xsl:attribute name="class">active</xsl:attribute>
93                                         </xsl:if>
94                                         <xsl:attribute name="href">
95                                             <xsl:value-of
96                                                     select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListMetadataFormats')"></xsl:value-of>
97                                         </xsl:attribute>
98                                         Metadata Formats
99                                     </a>
100                                 </li>
101                             </ul>
102                         </div><!--/.nav-collapse -->
103                     </div>
104                     <div class="row">
105                         <div class="col-lg-offset-1 col-lg-10">
106                             <div class="row">
107                                 <h5>Response Date <small><xsl:value-of select="translate(oai:OAI-PMH/oai:responseDate/text(), 'TZ', ' ')" /></small></h5>
108                             </div>
109                             <div class="row">
110                                 <xsl:apply-templates select="oai:OAI-PMH/oai:error" />
111                                 <xsl:apply-templates select="oai:OAI-PMH/oai:Identify" />
112                                 <xsl:apply-templates select="oai:OAI-PMH/oai:ListSets" />
113                                 <xsl:apply-templates select="oai:OAI-PMH/oai:ListRecords" />
114                                 <xsl:apply-templates select="oai:OAI-PMH/oai:ListIdentifiers" />
115                                 <xsl:apply-templates select="oai:OAI-PMH/oai:ListMetadataFormats" />
116                                 <xsl:apply-templates select="oai:OAI-PMH/oai:GetRecord" />
117                             </div>
118                         </div>
119                     </div>
120
121                     <div class="row-fluid text-center">
122                         <div class="vertical-space"></div>
123                         <p><small>Powered by <a href="http://koha-community.org">Koha</a></small></p>
124                     </div>
125                 </div>
126             </body>
127         </html>
128     </xsl:template>
129
130     <xsl:template match="oai:OAI-PMH/oai:error">
131         <div class="alert alert-danger">
132             <h4>Error</h4>
133             <p>
134                 <xsl:value-of select="text()"></xsl:value-of>
135             </p>
136         </div>
137     </xsl:template>
138
139     <xsl:template match="oai:OAI-PMH/oai:Identify">
140         <h2>Repository Information</h2>
141         <hr />
142         <table class="table table-striped table-bordered">
143             <tr>
144                 <td><b>Repository Name</b></td>
145                 <td><xsl:value-of select="oai:repositoryName/text()" /></td>
146             </tr>
147             <xsl:for-each select="oai:adminEmail">
148                 <tr>
149                     <td><b>E-Mail Contact</b></td>
150                     <td>
151                         <a>
152                             <xsl:attribute name="href">
153                                 <xsl:value-of select="concat('mailto:', text())" />
154                             </xsl:attribute>
155                             <xsl:value-of select="text()" />
156                         </a>
157                     </td>
158                 </tr>
159             </xsl:for-each>
160             <tr>
161                 <td><b>Repository identifier</b></td>
162                 <td>
163                     <xsl:value-of select="oai:description/oai_id:oai-identifier/oai_id:repositoryIdentifier/text()" />
164                 </td>
165             </tr>
166             <tr>
167                 <td><b>Sample identifier</b></td>
168                 <td>
169                     <xsl:value-of
170                             select="oai:description/oai_id:oai-identifier/oai_id:sampleIdentifier/text()" />
171                 </td>
172             </tr>
173             <tr>
174                 <td><b>Protocol Version</b></td>
175                 <td>
176                     <xsl:value-of
177                             select="oai:protocolVersion/text()" />
178                 </td>
179
180             </tr>
181             <tr>
182                 <td><b>Earliest Registered Date</b></td>
183                 <td>
184                     <xsl:value-of
185                             select="translate(oai:earliestDatestamp/text(), 'TZ' ,' ')" />
186                 </td>
187
188             </tr>
189             <tr>
190                 <td><b>Date Granularity</b></td>
191                 <td>
192                     <xsl:value-of
193                             select="translate(oai:granularity/text(), 'TZ', ' ')" />
194                 </td>
195
196             </tr>
197             <tr>
198                 <td><b>Deletion Mode</b></td>
199                 <td>
200                     <xsl:value-of
201                             select="oai:deletedRecord/text()" />
202                 </td>
203
204             </tr>
205         </table>
206     </xsl:template>
207
208     <xsl:template match="oai:OAI-PMH/oai:ListSets">
209         <h2>List of Sets</h2>
210         <hr />
211         <div class="well well-sm">
212             <h4>Results fetched
213                 <small>
214                     <xsl:call-template name="result-count">
215                         <xsl:with-param name="path" select="oai:set" />
216                     </xsl:call-template>
217                 </small>
218             </h4>
219         </div>
220         <div class="list-group">
221             <xsl:for-each select="oai:set">
222                 <div class="list-group-item">
223                     <h5 class="list-group-item-heading">
224                         <xsl:choose>
225                             <xsl:when test="string-length(oai:setName/text()) &gt; 83">
226                                 <xsl:value-of select="substring(oai:setName/text(),0, 80 )" />
227                                 ...
228                             </xsl:when>
229                             <xsl:otherwise>
230                                 <xsl:value-of select="oai:setName/text()" />
231                             </xsl:otherwise>
232                         </xsl:choose>
233                         <small>
234                             [<xsl:value-of select="oai:setSpec/text()" />]
235                         </small>
236                     </h5>
237                     <div class="spec">
238                         <a>
239                             <xsl:attribute name="href">
240                                 <xsl:value-of
241                                         select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListRecords&amp;metadataPrefix=oai_dc&amp;set=', oai:setSpec/text())" />
242                             </xsl:attribute>
243                             Records
244                         </a>
245                         <a>
246                             <xsl:attribute name="href">
247                                 <xsl:value-of
248                                         select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListIdentifiers&amp;metadataPrefix=oai_dc&amp;set=', oai:setSpec/text())" />
249                             </xsl:attribute>
250                             Identifiers
251                         </a>
252                     </div>
253                 </div>
254             </xsl:for-each>
255         </div>
256
257         <xsl:apply-templates select="oai:resumptionToken"/>
258     </xsl:template>
259
260     <xsl:template match="oai:OAI-PMH/oai:ListRecords">
261         <h2>List of Records</h2>
262         <hr />
263         <div class="well well-sm">
264             <h4>Results fetched
265                 <small>
266                     <xsl:call-template name="result-count">
267                         <xsl:with-param name="path" select="oai:record" />
268                     </xsl:call-template>
269                 </small>
270             </h4>
271         </div>
272         <xsl:for-each select="oai:record">
273             <div class="panel panel-default">
274                 <div class="panel-heading">
275                     <div class="row">
276                         <div class="col-lg-6">
277                             <h5>Identifier <small><xsl:value-of select="oai:header/oai:identifier/text()"></xsl:value-of></small></h5>
278                         </div>
279                         <div class="col-lg-6">
280                             <h5>Last Modified <small><xsl:value-of select="translate(oai:header/oai:datestamp/text(), 'TZ', ' ')"></xsl:value-of></small></h5>
281                         </div>
282                     </div>
283                 </div>
284                 <div class="panel-body">
285                     <!-- If this record has a "status", display it as a warning -->
286                     <xsl:if test="oai:header/@status">
287                       <div class="alert alert-warning">Record Status: <xsl:value-of select="oai:header/@status"/></div>
288                     </xsl:if>
289                     <div class="panel panel-success">
290                         <a data-toggle="collapse">
291                             <xsl:attribute name="href">#sets<xsl:value-of select="translate(oai:header/oai:identifier/text(), ':/.', '')"></xsl:value-of></xsl:attribute>
292                             <div class="panel-heading">
293                                 <h5 class="panel-title">
294                                     Sets
295                                 </h5>
296                             </div>
297                         </a>
298                         <div class="panel-collapse collapse">
299                             <xsl:attribute name="id">sets<xsl:value-of select="translate(oai:header/oai:identifier/text(), ':/.', '')"></xsl:value-of></xsl:attribute>
300                             <div class="panel-body list-group">
301                                 <xsl:for-each select="oai:header/oai:setSpec">
302                                     <div class="list-group-item">
303                                         <a>
304                                             <xsl:attribute name="href">
305                                                 <xsl:value-of
306                                                         select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListRecords&amp;metadataPrefix=oai_dc&amp;set=', text())" />
307                                             </xsl:attribute>
308                                             <xsl:value-of select="text()" />
309                                         </a>
310                                     </div>
311                                 </xsl:for-each>
312                             </div>
313                         </div>
314                     </div>
315                     <div class="panel panel-info">
316                         <a data-toggle="collapse">
317                             <xsl:attribute name="href">#<xsl:value-of select="translate(oai:header/oai:identifier/text(), ':/.', '')"></xsl:value-of></xsl:attribute>
318                             <div class="panel-heading">
319                                 <h5 class="panel-title">
320                                         Metadata
321                                 </h5>
322                             </div>
323                         </a>
324                         <div class="panel-collapse collapse">
325                             <xsl:attribute name="id"><xsl:value-of select="translate(oai:header/oai:identifier/text(), ':/.', '')"></xsl:value-of></xsl:attribute>
326                             <div class="panel-body">
327                                 <xsl:apply-templates select="oai:metadata/*" />
328                             </div>
329                         </div>
330                     </div>
331                 </div>
332             </div>
333         </xsl:for-each>
334
335         <xsl:apply-templates select="oai:resumptionToken"/>
336     </xsl:template>
337
338     <xsl:template match="oai:OAI-PMH/oai:GetRecord">
339         <h2>Record Details</h2>
340         <hr />
341         <xsl:for-each select="oai:record">
342             <div class="panel panel-default">
343                 <div class="panel-heading">
344                     <div class="row">
345                         <div class="col-lg-6">
346                             <h5>Identifier <small><xsl:value-of select="oai:header/oai:identifier/text()"></xsl:value-of></small></h5>
347                         </div>
348                         <div class="col-lg-6">
349                             <h5>Last Modified <small><xsl:value-of select="translate(oai:header/oai:datestamp/text(), 'TZ', ' ')"></xsl:value-of></small></h5>
350                         </div>
351                     </div>
352                 </div>
353                 <div class="panel-body">
354                     <!-- If this record has a "status", display it as a warning -->
355                     <xsl:if test="oai:header/@status">
356                       <div class="alert alert-warning">Record Status: <xsl:value-of select="oai:header/@status"/></div>
357                     </xsl:if>
358                     <div class="panel panel-success">
359                             <div class="panel-heading">
360                                 <h5 class="panel-title">
361                                     Sets
362                                 </h5>
363                             </div>
364                             <div class="panel-body list-group">
365                                 <xsl:for-each select="oai:header/oai:setSpec">
366                                     <div class="list-group-item">
367                                         <a>
368                                             <xsl:attribute name="href">
369                                                 <xsl:value-of
370                                                         select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListRecords&amp;metadataPrefix=oai_dc&amp;set=', text())" />
371                                             </xsl:attribute>
372                                             <xsl:value-of select="text()" />
373                                         </a>
374                                     </div>
375                                 </xsl:for-each>
376                             </div>
377                     </div>
378                     <div class="panel panel-info">
379                             <div class="panel-heading">
380                                 <h5 class="panel-title">
381                                     Metadata
382                                 </h5>
383                             </div>
384                             <div class="panel-body">
385                                 <xsl:apply-templates select="oai:metadata/*" />
386                             </div>
387                     </div>
388                 </div>
389             </div>
390         </xsl:for-each>
391     </xsl:template>
392
393     <xsl:template match="oai:OAI-PMH/oai:ListIdentifiers">
394         <h2>List of Identifiers</h2>
395         <hr />
396         <div class="well well-sm">
397             <h4>Results fetched
398                 <small>
399                     <xsl:call-template name="result-count">
400                         <xsl:with-param name="path" select="oai:header" />
401                     </xsl:call-template>
402                 </small>
403             </h4>
404         </div>
405         <xsl:for-each select="oai:header">
406             <div class="panel panel-default">
407                 <div class="panel-heading">
408                     <div class="row">
409                         <div class="col-lg-4">
410                             <h5>Identifier <small><xsl:value-of select="oai:identifier/text()"></xsl:value-of></small></h5>
411                         </div>
412                         <div class="col-lg-4">
413                             <h5>Last Modified <small><xsl:value-of select="translate(oai:datestamp/text(), 'TZ', ' ')"></xsl:value-of></small></h5>
414                         </div>
415                         <div class="col-lg-4">
416                             <a class="btn btn-default pull-right">
417                                 <xsl:attribute name="href">
418                                     <xsl:value-of select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=GetRecord&amp;metadataPrefix=oai_dc&amp;identifier=', oai:identifier/text())" />
419                                 </xsl:attribute>
420                                 View Details
421                             </a>
422                         </div>
423                     </div>
424                 </div>
425                 <div class="panel-body">
426                     <!-- If this record has a "status", display it as a warning -->
427                     <xsl:if test="@status">
428                       <div class="alert alert-warning">Record Status: <xsl:value-of select="@status"/></div>
429                     </xsl:if>
430                     <div class="panel panel-success">
431                         <a data-toggle="collapse">
432                             <xsl:attribute name="href">#sets<xsl:value-of select="translate(oai:identifier/text(), ':/.', '')"></xsl:value-of></xsl:attribute>
433                             <div class="panel-heading">
434                                 <h5 class="panel-title">
435                                     Sets
436                                 </h5>
437                             </div>
438                         </a>
439                         <div class="panel-collapse collapse">
440                             <xsl:attribute name="id">sets<xsl:value-of select="translate(oai:identifier/text(), ':/.', '')"></xsl:value-of></xsl:attribute>
441                             <div class="panel-body list-group">
442                                 <xsl:for-each select="oai:setSpec">
443                                     <div class="list-group-item">
444                                         <a>
445                                             <xsl:attribute name="href">
446                                                 <xsl:value-of
447                                                         select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListRecords&amp;metadataPrefix=oai_dc&amp;set=', text())" />
448                                             </xsl:attribute>
449                                             <xsl:value-of select="text()" />
450                                         </a>
451                                     </div>
452                                 </xsl:for-each>
453                             </div>
454                         </div>
455                     </div>
456                 </div>
457             </div>
458         </xsl:for-each>
459
460         <xsl:apply-templates select="oai:resumptionToken"/>
461     </xsl:template>
462
463     <xsl:template match="oai:OAI-PMH/oai:ListMetadataFormats">
464         <h2>List of Metadata Formats</h2>
465         <hr />
466         <div class="well well-sm">
467             <h4>Results fetched
468                 <small>
469                     <xsl:value-of select="count(oai:OAI-PMH/oai:ListMetadataFormats/oai:metadataFormat)" />
470                 </small>
471             </h4>
472         </div>
473         <xsl:for-each select="oai:metadataFormat">
474             <div class="panel panel-default">
475                 <div class="panel-heading">
476                     <div class="row">
477                         <div class="col-lg-9">
478                             <h5><xsl:value-of select="oai:metadataPrefix/text()"></xsl:value-of></h5>
479                         </div>
480                         <div class="col-lg-3">
481                             <a class="btn btn-default pull-right">
482                                 <xsl:attribute name="href">
483                                     <xsl:value-of
484                                             select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=ListRecords&amp;metadataPrefix=', oai:metadataPrefix/text())" />
485                                 </xsl:attribute>
486                                 List Records
487                             </a>
488                         </div>
489                     </div>
490                 </div>
491                 <div class="panel-body">
492                     <div class="row">
493                         <div class="col-lg-9">
494                             <h5>Namespace <small><xsl:value-of select="oai:metadataNamespace/text()"></xsl:value-of></small></h5>
495                             <h5>Schema <small><xsl:value-of select="oai:schema/text()"></xsl:value-of></small></h5>
496                         </div>
497                     </div>
498                 </div>
499             </div>
500         </xsl:for-each>
501     </xsl:template>
502
503     <xsl:template match="oai:resumptionToken">
504         <xsl:if test="text() != ''">
505             <div class="text-center">
506                 <a class="btn btn-primary">
507                 <xsl:attribute name="href">
508                     <xsl:value-of select="concat(/oai:OAI-PMH/oai:request/text(), '?verb=',/oai:OAI-PMH/oai:request/@verb,'&amp;resumptionToken=', text())"></xsl:value-of>
509                 </xsl:attribute>
510                     Show More
511                 </a>
512             </div>
513         </xsl:if>
514     </xsl:template>
515
516     <xsl:template name="result-count">
517         <xsl:param name="path" />
518         <xsl:variable name="cursor" select="$path/../oai:resumptionToken/@cursor" />
519         <xsl:variable name="count" select="count($path)" />
520         <xsl:variable name="total" select="$path/../oai:resumptionToken/@completeListSize" />
521         <xsl:choose>
522             <xsl:when test="$cursor">
523                 <xsl:choose>
524                     <xsl:when test="normalize-space($path/../oai:resumptionToken/text()) = ''">
525                     <!-- on the last page of results we have to assume that @completeListSize is available -->
526                         <xsl:value-of
527                             select="$total - $count" />
528                         -
529                         <xsl:value-of select="$total" />
530                     </xsl:when>
531                     <xsl:otherwise>
532                         <xsl:value-of select="$cursor * $count" />
533                         -
534                         <xsl:value-of select="($cursor+1) * $count" />
535                     </xsl:otherwise>
536                 </xsl:choose>
537             </xsl:when>
538             <xsl:otherwise>
539                 <xsl:value-of select="$count" />
540             </xsl:otherwise>
541         </xsl:choose>
542         <xsl:if test="$total">
543             of
544             <xsl:value-of select="$total" />
545         </xsl:if>
546     </xsl:template>
547
548     <xsl:template match="oai:metadata/*" priority='-20'>
549         <xsl:apply-templates select="." mode='xmlverb' />
550     </xsl:template>
551
552     <xsl:param name="indent-elements" select="false()" />
553
554     <xsl:template match="/" mode="xmlverb">
555         <xsl:text>&#xA;</xsl:text>
556         <xsl:comment>
557             <xsl:text> converted by xmlverbatim.xsl 1.1, (c) O. Becker </xsl:text>
558         </xsl:comment>
559         <xsl:text>&#xA;</xsl:text>
560         <div class="xmlverb-default">
561             <xsl:apply-templates mode="xmlverb">
562                 <xsl:with-param name="indent-elements" select="$indent-elements" />
563             </xsl:apply-templates>
564         </div>
565         <xsl:text>&#xA;</xsl:text>
566     </xsl:template>
567
568     <!-- wrapper -->
569     <xsl:template match="verb:wrapper">
570         <xsl:apply-templates mode="xmlverb">
571             <xsl:with-param name="indent-elements" select="$indent-elements" />
572         </xsl:apply-templates>
573     </xsl:template>
574
575     <xsl:template match="verb:wrapper" mode="xmlverb">
576         <xsl:apply-templates mode="xmlverb">
577             <xsl:with-param name="indent-elements" select="$indent-elements" />
578         </xsl:apply-templates>
579     </xsl:template>
580
581     <!-- element nodes -->
582     <xsl:template match="*" mode="xmlverb">
583         <xsl:param name="indent-elements" select="true()" />
584         <xsl:param name="indent" select="''" />
585         <xsl:param name="indent-increment" select="'&#xA0;&#xA0;&#xA0;'" />
586         <xsl:if test="$indent-elements">
587             <br/>
588             <xsl:value-of select="$indent" />
589         </xsl:if>
590         <xsl:text>&lt;</xsl:text>
591         <xsl:variable name="ns-prefix"
592                       select="substring-before(name(),':')" />
593         <xsl:if test="$ns-prefix != ''">
594             <span class="xmlverb-element-nsprefix">
595                 <xsl:value-of select="$ns-prefix"/>
596             </span>
597             <xsl:text>:</xsl:text>
598         </xsl:if>
599         <span class="xmlverb-element-name">
600             <xsl:value-of select="local-name()"/>
601         </span>
602         <xsl:variable name="pns" select="../namespace::*"/>
603         <xsl:if test="$pns[name()=''] and not(namespace::*[name()=''])">
604             <span class="xmlverb-ns-name">
605                 <xsl:text> xmlns</xsl:text>
606             </span>
607             <xsl:text>=&quot;&quot;</xsl:text>
608         </xsl:if>
609         <xsl:for-each select="namespace::*">
610             <xsl:if test="not($pns[name()=name(current()) and
611                            .=current()])">
612                 <xsl:call-template name="xmlverb-ns" />
613             </xsl:if>
614         </xsl:for-each>
615         <xsl:for-each select="@*">
616             <xsl:call-template name="xmlverb-attrs" />
617         </xsl:for-each>
618         <xsl:choose>
619             <xsl:when test="node()">
620                 <xsl:text>&gt;</xsl:text>
621                 <xsl:apply-templates mode="xmlverb">
622                     <xsl:with-param name="indent-elements"
623                                     select="$indent-elements"/>
624                     <xsl:with-param name="indent"
625                                     select="concat($indent, $indent-increment)"/>
626                     <xsl:with-param name="indent-increment"
627                                     select="$indent-increment"/>
628                 </xsl:apply-templates>
629                 <xsl:if test="* and $indent-elements">
630                     <br/>
631                     <xsl:value-of select="$indent" />
632                 </xsl:if>
633                 <xsl:text>&lt;/</xsl:text>
634                 <xsl:if test="$ns-prefix != ''">
635                     <span class="xmlverb-element-nsprefix">
636                         <xsl:value-of select="$ns-prefix"/>
637                     </span>
638                     <xsl:text>:</xsl:text>
639                 </xsl:if>
640                 <span class="xmlverb-element-name">
641                     <xsl:value-of select="local-name()"/>
642                 </span>
643                 <xsl:text>&gt;</xsl:text>
644             </xsl:when>
645             <xsl:otherwise>
646                 <xsl:text> /&gt;</xsl:text>
647             </xsl:otherwise>
648         </xsl:choose>
649         <xsl:if test="not(parent::*)"><br /><xsl:text>&#xA;</xsl:text></xsl:if>
650     </xsl:template>
651
652     <!-- attribute nodes -->
653     <xsl:template name="xmlverb-attrs">
654         <xsl:text> </xsl:text>
655         <span class="xmlverb-attr-name">
656             <xsl:value-of select="name()"/>
657         </span>
658         <xsl:text>=&quot;</xsl:text>
659         <span class="xmlverb-attr-content">
660             <xsl:call-template name="html-replace-entities">
661                 <xsl:with-param name="text" select="normalize-space(.)" />
662                 <xsl:with-param name="attrs" select="true()" />
663             </xsl:call-template>
664         </span>
665         <xsl:text>&quot;</xsl:text>
666     </xsl:template>
667
668     <!-- namespace nodes -->
669     <xsl:template name="xmlverb-ns">
670         <xsl:if test="name()!='xml'">
671             <span class="xmlverb-ns-name">
672                 <xsl:text> xmlns</xsl:text>
673                 <xsl:if test="name()!=''">
674                     <xsl:text>:</xsl:text>
675                 </xsl:if>
676                 <xsl:value-of select="name()"/>
677             </span>
678             <xsl:text>=&quot;</xsl:text>
679             <span class="xmlverb-ns-uri">
680                 <xsl:value-of select="."/>
681             </span>
682             <xsl:text>&quot;</xsl:text>
683         </xsl:if>
684     </xsl:template>
685
686     <!-- text nodes -->
687     <xsl:template match="text()" mode="xmlverb">
688         <span class="xmlverb-text">
689             <xsl:call-template name="preformatted-output">
690                 <xsl:with-param name="text">
691                     <xsl:call-template name="html-replace-entities">
692                         <xsl:with-param name="text" select="." />
693                     </xsl:call-template>
694                 </xsl:with-param>
695             </xsl:call-template>
696         </span>
697     </xsl:template>
698
699     <!-- comments -->
700     <xsl:template match="comment()" mode="xmlverb">
701         <xsl:text>&lt;!--</xsl:text>
702         <span class="xmlverb-comment">
703             <xsl:call-template name="preformatted-output">
704                 <xsl:with-param name="text" select="." />
705             </xsl:call-template>
706         </span>
707         <xsl:text>--&gt;</xsl:text>
708         <xsl:if test="not(parent::*)"><br /><xsl:text>&#xA;</xsl:text></xsl:if>
709     </xsl:template>
710
711     <!-- processing instructions -->
712     <xsl:template match="processing-instruction()" mode="xmlverb">
713         <xsl:text>&lt;?</xsl:text>
714         <span class="xmlverb-pi-name">
715             <xsl:value-of select="name()"/>
716         </span>
717         <xsl:if test=".!=''">
718             <xsl:text> </xsl:text>
719             <span class="xmlverb-pi-content">
720                 <xsl:value-of select="."/>
721             </span>
722         </xsl:if>
723         <xsl:text>?&gt;</xsl:text>
724         <xsl:if test="not(parent::*)"><br /><xsl:text>&#xA;</xsl:text></xsl:if>
725     </xsl:template>
726
727
728     <!-- =========================================================== -->
729     <!--                    Procedures / Functions                   -->
730     <!-- =========================================================== -->
731
732     <!-- generate entities by replacing &, ", < and > in $text -->
733     <xsl:template name="html-replace-entities">
734         <xsl:param name="text" />
735         <xsl:param name="attrs" />
736         <xsl:variable name="tmp">
737             <xsl:call-template name="replace-substring">
738                 <xsl:with-param name="from" select="'&gt;'" />
739                 <xsl:with-param name="to" select="'&amp;gt;'" />
740                 <xsl:with-param name="value">
741                     <xsl:call-template name="replace-substring">
742                         <xsl:with-param name="from" select="'&lt;'" />
743                         <xsl:with-param name="to" select="'&amp;lt;'" />
744                         <xsl:with-param name="value">
745                             <xsl:call-template name="replace-substring">
746                                 <xsl:with-param name="from"
747                                                 select="'&amp;'" />
748                                 <xsl:with-param name="to"
749                                                 select="'&amp;amp;'" />
750                                 <xsl:with-param name="value"
751                                                 select="$text" />
752                             </xsl:call-template>
753                         </xsl:with-param>
754                     </xsl:call-template>
755                 </xsl:with-param>
756             </xsl:call-template>
757         </xsl:variable>
758         <xsl:choose>
759             <!-- $text is an attribute value -->
760             <xsl:when test="$attrs">
761                 <xsl:call-template name="replace-substring">
762                     <xsl:with-param name="from" select="'&#xA;'" />
763                     <xsl:with-param name="to" select="'&amp;#xA;'" />
764                     <xsl:with-param name="value">
765                         <xsl:call-template name="replace-substring">
766                             <xsl:with-param name="from"
767                                             select="'&quot;'" />
768                             <xsl:with-param name="to"
769                                             select="'&amp;quot;'" />
770                             <xsl:with-param name="value" select="$tmp" />
771                         </xsl:call-template>
772                     </xsl:with-param>
773                 </xsl:call-template>
774             </xsl:when>
775             <xsl:otherwise>
776                 <xsl:value-of select="$tmp" />
777             </xsl:otherwise>
778         </xsl:choose>
779     </xsl:template>
780
781     <!-- replace in $value substring $from with $to -->
782     <xsl:template name="replace-substring">
783         <xsl:param name="value" />
784         <xsl:param name="from" />
785         <xsl:param name="to" />
786         <xsl:choose>
787             <xsl:when test="contains($value,$from)">
788                 <xsl:value-of select="substring-before($value,$from)" />
789                 <xsl:value-of select="$to" />
790                 <xsl:call-template name="replace-substring">
791                     <xsl:with-param name="value"
792                                     select="substring-after($value,$from)" />
793                     <xsl:with-param name="from" select="$from" />
794                     <xsl:with-param name="to" select="$to" />
795                 </xsl:call-template>
796             </xsl:when>
797             <xsl:otherwise>
798                 <xsl:value-of select="$value" />
799             </xsl:otherwise>
800         </xsl:choose>
801     </xsl:template>
802
803     <!-- preformatted output: space as &nbsp;, tab as 8 &nbsp;
804                               nl as <br> -->
805     <xsl:template name="preformatted-output">
806         <xsl:param name="text" />
807         <xsl:call-template name="output-nl">
808             <xsl:with-param name="text">
809                 <xsl:call-template name="replace-substring">
810                     <xsl:with-param name="value"
811                                     select="translate($text,' ','&#xA0;')" />
812                     <xsl:with-param name="from" select="'&#9;'" />
813                     <xsl:with-param name="to"
814                                     select="'&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;'" />
815                 </xsl:call-template>
816             </xsl:with-param>
817         </xsl:call-template>
818     </xsl:template>
819
820     <!-- output nl as <br> -->
821     <xsl:template name="output-nl">
822         <xsl:param name="text" />
823         <xsl:choose>
824             <xsl:when test="contains($text,'&#xA;')">
825                 <xsl:value-of select="substring-before($text,'&#xA;')" />
826                 <br />
827                 <xsl:text>&#xA;</xsl:text>
828                 <xsl:call-template name="output-nl">
829                     <xsl:with-param name="text"
830                                     select="substring-after($text,'&#xA;')" />
831                 </xsl:call-template>
832             </xsl:when>
833             <xsl:otherwise>
834                 <xsl:value-of select="$text" />
835             </xsl:otherwise>
836         </xsl:choose>
837     </xsl:template>
838
839 </xsl:stylesheet>