Attachment 'xml.xsl'

Download

   1 <?xml version="1.0"?>
   2 <?xml-stylesheet type="text/xsl" href="xml.xsl"?>
   3 <!--
   4  |
   5  | displaying xml source in various format (html, text)
   6  | frederic.glorieux@ajlsm.com
   7  |
   8  | fast test, apply this to itself
   9  |
  10  | usage :
  11  |   as a root xsl matching all elements
  12  |   as an import xsl to format some xml
  13  |     with <xsl:apply-templates select="node()" mode="xml:html"/>
  14  |     in this case you need to copy css and js somewhere to link with
  15  |
  16  | features :
  17  |   DOM compatible hide/show
  18  |   double click to expand all
  19  |   old browser compatible
  20  |   no extra characters to easy copy/paste code
  21  |   html formatting oriented for logical css
  22  |   commented to easier adaptation
  23  |   all xmlns:*="uri" attributes in root node
  24  |   text reformating ( xml entities )
  25  |
  26  | problems :
  27  |   <![CDATA[ node ]]> can't be shown (processed by xml parser before xsl transformation)
  28  |
  29  | TODOs
  30  |
  31  | - an edit mode
  32  |
  33  +-->
  34 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
  35     <xsl:output indent="no" method="xml" cdata-section-elements="cdata"/>
  36     <xsl:param name="pre" select="false()"/>
  37     <xsl:param name="text-replace" select="true()"/>
  38     <xsl:param name="val-replace" select="true()"/>
  39     <xsl:param name="inlines" select="' emph hilite strong b i a '"/>
  40     <xsl:param name="pres" select="' pre script style logic documentation originalExpression '"/>
  41     <xsl:param name="blocks" select="' p para '"/>
  42     <xsl:param name="hides" select="' hide '"/>
  43     <xsl:param name="cdatas" select="concat(' cdata ', normalize-space(/*/*/@cdata-section-elements), ' ')"/>
  44     <xsl:param name="action"/>
  45     <xsl:param name="back"/>
  46     <xsl:variable name="xml:search-atts" select="document('')/*/xsl:template[@name='search-atts']/search"/>
  47     <!--
  48      |    specific formating for some nodes (local-name only)
  49      |-->
  50     <!-- style -->
  51     <xsl:template name="xml:style">
  52         <xsl:text xml:space="preserve">
  53             /*
  54             body css properties are applied to operators
  55 
  56             nodes have a class :
  57                 processing-instruction, comment,
  58                 text, attribute value
  59                 tag name, attribute name
  60             tag+atts are included in el class
  61              */
  62 
  63             .xml_pi
  64                 {color:#000080; font-weight: bold;}
  65             .xml_rem
  66                 {  margin:0; padding:0; white-space:pre;
  67                  font-size:90%;
  68                 font-family: monospace, sans-serif;
  69                 color:#666666; background:#FFFFF0; font-weight: 100; }
  70             .xml_text, .xml_val, .xml_cdata
  71                 { font-size:100%; font-weight:bold; color:#555555; 
  72                 margin:0; padding:0;
  73                 font-family:monospace, sans-serif; 
  74                 background:#F5F5F5;
  75                 }
  76             .xml_cdata {color:red}
  77             .xml_name
  78                 {color:#CC3333; font-weight:900; font-family: Verdana, sans-serif; }
  79             .xml_att
  80                 {color:#008000;font-weight:100; font-family: Verdana, sans-serif; }
  81             .xml_tag
  82                 { white-space:nowrap;}
  83             .xml_ns
  84                 { color:#000080; font-weight:100;}
  85             .xml_margin
  86                 { display:block; margin-left:20px; padding-left:10px; border-left: 1px dotted;
  87                 margin-top:0px; margin-bottom:0px; margin-right:0px; }
  88 
  89             /* 
  90              *  global formatting 
  91              * 
  92              *  those classes could be used inline or as block
  93              *  so formatting is decide by an xml class container
  94              */
  95             .xml
  96                 { display:block; 
  97                 font-family: "Lucida Console", monospace, sans-serif; font-size: 80%;
  98                 color:Navy; margin-left:2em; }
  99             .xml pre { margin:0 }
 100             .xml a {text-decoration:none; }
 101             .xml a:hover {text-decoration: underline; }
 102             .xml a:active, .xml a:active *  {background:#CC3333;color:#FFFFFF;}
 103             .xml a {text-decoration:none; }
 104             .swap_hide { color:blue; text-decoration:underline; }
 105 
 106         </xsl:text>
 107     </xsl:template>
 108     <!--
 109      |    ROOT
 110      |-->
 111     <!-- low priority on root node in case of include -->
 112     <xsl:template name="xml:root" match="/" priority="-2">
 113         <xsl:param name="current" select="."/>
 114         <xsl:param name="title" select="'XML - source'"/>
 115         <html>
 116             <head>
 117                 <title>
 118                     <xsl:value-of select="$title"/>
 119                 </title>
 120                 <script type="text/javascript">
 121                     <xsl:call-template name="xml:swap.js"/>
 122     var SWAP_CLASS='xml_margin';
 123 
 124 
 125     function save(text, fileName)
 126     {
 127         log="";
 128         if (document.execCommand)
 129         {
 130             if (!document.frames[0]) return log + "no frame to write in";
 131             win=document.frames[0];
 132             win.document.open("text/html", "replace");
 133             win.document.write(text);
 134             win.document.close();
 135             win.focus();
 136             win.document.execCommand('SaveAs', fileName);
 137         }
 138      /*
 139      
 140      function writeToFile(fileName,text) {
 141  
 142 netscape.security.PrivilegeManager.enablePrivilege('UniversalFileAccess');
 143     var fileWriter = new java.io.FileWriter(fileName);
 144     fileWriter.write (text, 0, text.length);
 145     fileWriter.close();
 146 }
 147 
 148 if (document.layers) {
 149     writeToFile('file.txt','Hello World');
 150 }
 151 		*/
 152     }
 153 
 154     function dom(xml)
 155     {
 156         if (window.DOMParser) return (new DOMParser()).parseFromString(xml, "text/xml");
 157         else if (window.ActiveXObject)
 158         {
 159             var doc = new ActiveXObject("Microsoft.XMLDOM");
 160             doc.async = false;
 161             doc.loadXML(xml);
 162             return doc;
 163         }
 164         else
 165         {
 166             alert(NOXML);
 167             return null;
 168         }
 169     }
 170     
 171     function xml_save()
 172     {
 173         if (!document.getElementById) return false;
 174         o=document.getElementById('edit');
 175         if (!o.innerText) return false; 
 176         var edit=o.contentEditable; 
 177         o.contentEditable=false; 
 178         var xml=o.innerText; 
 179         o.contentEditable=edit; 
 180         var doc=dom(xml); 
 181         if (!doc || !doc.documentElement) if (!confirm('The document you want to save is not well-formed. Continue ?')) return false;  
 182         save(xml)
 183     }
 184     
 185     function xml_edit(button, edit)
 186     {
 187         if (!document.getElementById) return false;
 188         if (document.body.isContentEditable==null) return false;
 189         var o=document.getElementById('edit'); 
 190         if(!o) return false; 
 191         if (edit == null) edit=!o.isContentEditable; 
 192         if (edit) { 
 193             if (button) button.className='but_in'; 
 194             o.contentEditable=true;
 195             document.cookie="edit=true";
 196         } 
 197         else { 
 198             if (button) button.className=''; 
 199             o.contentEditable=false; 
 200             document.cookie="edit=false";
 201         }
 202     }
 203 
 204     function xml_submit(form)
 205     {
 206         if (!form) form=document.forms[0];
 207         if (!document.getElementById) return false;
 208         o=document.getElementById('edit'); 
 209         if (!o.innerText) return false; 
 210         var edit=o.contentEditable; 
 211         o.contentEditable=false; 
 212         var xml=o.innerText; 
 213         o.contentEditable=edit; 
 214         var doc=dom(xml); 
 215         if (!doc || !doc.documentElement) if (!confirm('The document you want to upload is not well-formed. Continue ?')) return false;  
 216         if (!form || !form.xml) return false;
 217         form.xml.value=xml;
 218         if(form.url) form.url.value=window.location.href;
 219         return true;
 220     }
 221     
 222     function edit_key(o)
 223     {
 224         if (!event) return;
 225         var key=event.keyCode;
 226         if (!o) o=document.getElementById('edit');
 227         if (!o.isContentEditable) return true;
 228         if (key==9) {
 229             if (event.shiftKey) document.execCommand("Outdent"); 
 230             else document.execCommand("Indent"); 
 231             window.event.cancelBubble = true;
 232             window.event.returnValue = false;
 233             return false;
 234         }
 235         if (key==83) {
 236             if (!event.ctrlKey) return;
 237             xml_save();
 238             window.event.cancelBubble = true;
 239             window.event.returnValue = false;
 240             return false;
 241         }
 242         if (key==85) {
 243             if (!event.ctrlKey) return;
 244             form=document.forms[0];
 245             if (!form) return;
 246             if (xml_submit(form)) form.submit();
 247             window.event.cancelBubble = true;
 248             window.event.returnValue = false;
 249             return false;
 250         }
 251     }
 252     
 253     function xml_load()
 254     {
 255         if (!document.getElementById || !document.execCommand || document.body.isContentEditable==null) return false; 
 256         var o=document.getElementById('bar'); 
 257         if (!o || !o.style) return; 
 258         o.style.display='';
 259         xml_edit(document.forms[0].butEdit, (document.cookie.search("edit=true") != -1));
 260     }
 261 
 262                 </script>
 263                 <style type="text/css">
 264                     <xsl:call-template name="xml:style"/>
 265                     .but_over {}
 266                     .but_in {border:inset 2px; color:red; }
 267                 </style>
 268             </head>
 269             <body onload="xml_load()" ondblclick="swap_all(this)">
 270                 <form id="bar" style="margin:0; display:none;" onsubmit="return xml_submit(this); ">
 271                     <xsl:if test="$action">
 272                         <xsl:attribute name="action">
 273                             <xsl:value-of select="$action"/>
 274                         </xsl:attribute>
 275                         <xsl:attribute name="method">post</xsl:attribute>
 276                     </xsl:if>
 277                     <iframe id="save" style="display:none">nothing</iframe>
 278                     <xsl:if test="$back">
 279                         <input type="hidden" name="back" value="{$back}"/>
 280                         <button accesskey="b" type="button" onclick="window.location.href=this.form.back.value">
 281                             <u>B</u>ack
 282                     </button>
 283                     </xsl:if>
 284                     <button name="butEdit" type="button" accesskey="e" onclick="xml_edit(this)">
 285                         <u>E</u>dit</button>
 286                     <button type="button" accesskey="s" onclick="xml_save()">
 287                         <u>S</u>ave</button>
 288                     <xsl:if test="$action">
 289                         <button type="submit" accesskey="u">
 290                             <u>U</u>pload</button>
 291                     </xsl:if>
 292                     <input type="hidden" name="url"/>
 293                     <textarea name="xml" cols="1" rows="1" style="width:1px; height:1px">nothing</textarea>
 294                 </form>
 295                 <div class="xml" id="edit" onkeydown="edit_key(this)">
 296                     <div class="xml_pi">&lt;?xml version="1.0"?&gt;</div>
 297                     <xsl:apply-templates select="$current" mode="xml:html"/>
 298                 </div>
 299             </body>
 300         </html>
 301     </xsl:template>
 302     <!-- script -->
 303     <xsl:template name="xml:swap.js">
 304         /*<cdata>
 305             <xsl:text disable-output-escaping="yes"><![CDATA[  */
 306 /*    
 307     if (!document.getElementById)
 308     {
 309         html='';
 310         html +='<style type="text/css">';
 311         html +='.'+ SWAP_CLASS + ' {display:block;}';
 312         html +='</style>';
 313         document.write(html);
 314     }
 315 */
 316     var SWAP_CLASS='swap';
 317     var SWAP_SRC_PREFIX='src';
 318     var SWAP_DEBUG=true;
 319     function swap_one(id, src, mode)
 320     {
 321         var log='swap_one ';
 322         if (!document.getElementById) return false; // log + 'no dom ';
 323         tgt=document.getElementById(id);
 324         if (!tgt) return false; // log+' not find ' ;
 325         log+=' #'+tgt.id+' ';
 326         if (!mode)
 327             if (tgt.store=='none') mode='show';
 328             else if (tgt.style.display=='none') mode='show';
 329             else mode='hide';
 330         log+=mode+' ';
 331         if (false) {}
 332         else if (mode=='show') log+=swap_show(tgt, src);
 333         else if (mode=='hide') log+=swap_hide(tgt, src);
 334         return log;
 335     }
 336 
 337     function swap_show(tgt, src, store)
 338     {
 339         var log='swap_show';
 340         if (!tgt) return log+" no tgt";
 341         if (!tgt.style) 
 342         {
 343             if (!document.getElementById) return log + ' no dom';
 344             tgt=document.getElementById(tgt);
 345             log+=' #'+tgt;
 346         }
 347         if (!tgt || !tgt.style) return log + ' not a node';
 348         tgt.style.display='';
 349         if (store==null || store != false) 
 350         {
 351             tgt.store=tgt.style.display;
 352             log+=" store"+tgt.store+" ";
 353         }
 354         // store user action
 355         if (!src) src=SWAP_SRC_PREFIX + tgt.id;
 356         if (!src.className) src=document.getElementById(src);
 357         if (!src) return log+" no src #"+src;
 358         if (src.value=='+') src.value='-';
 359         else if (src.className != null) 
 360         {
 361             style=src.className.replace(/ ?swap_hide ?/gi, '');
 362             // style=style+' swap_show';
 363             src.className=style;
 364         }
 365         else if (src.innerHTML) src.innerHTML.replace('+', '-');
 366         return log;
 367     }
 368 
 369     function swap_hide(tgt, src, restore)
 370     {
 371         var log='swap_hide';
 372         if (!tgt) return log+" no tgt";
 373         if (!tgt.style) 
 374         {
 375             if (!document.getElementById) return log + ' no dom';
 376             tgt=document.getElementById(tgt);
 377             log+=' #'+tgt;
 378         }
 379         if (!tgt || !tgt.style) return log + ' not a node';
 380         // store display
 381         tgt.display=tgt.style.display;
 382         if (!restore) 
 383         {
 384             tgt.style.display='none'; 
 385             tgt.store=tgt.style.display; 
 386         }
 387         else 
 388         {
 389             tgt.style.display=tgt.store;
 390             log+=' restore ';
 391         } 
 392         if (!src) src=SWAP_SRC_PREFIX + tgt.id;
 393         if (!src.className) src=document.getElementById(src);
 394         if (!src) return log+" no src #"+src;
 395         if (src.value=='-') {  src.value='+'; }
 396         else if (src.tagName != null) 
 397         {
 398             
 399             var style=src.className;
 400             // style=style.replace(/ ?swap_show ?/gi, '');
 401             src.className=style+' swap_hide';
 402         }
 403         else if (src.innerHTML) src.innerHTML.replace('+', '-');
 404         return log;
 405     }
 406 
 407     function swap_over(tgt, src)
 408     {
 409         return 'swap_over ' + swap_show(tgt, src, false);
 410     }
 411     
 412     function swap_out(tgt, src)
 413     {
 414         return 'swap_out ' + swap_hide(tgt, src, true);
 415     }
 416     
 417 
 418     function swap_hideAll(tgt, level, swap_class)
 419     {
 420         if (!level) level=0;
 421         if (!swap_class) swap_class=SWAP_CLASS;
 422         if (tgt.className) if (tgt.className.search(swap_class) != -1)
 423             {
 424                 if (level != 0) level--; 
 425                 if (level==0) swap_hide (tgt);
 426             }
 427         if (!tgt.childNodes) return;
 428         var i=0;
 429         while (tgt.childNodes[i]) 
 430             {swap_hideAll(tgt.childNodes[i], level, swap_class); i++; }
 431         return true;
 432     }    
 433     function swap_showAll(tgt, level, swap_class)
 434     {
 435         if (!level) level=0;
 436         if (!swap_class) swap_class=SWAP_CLASS;
 437         if (tgt.className) if (tgt.className.search(swap_class) != -1) 
 438             {
 439                 if (level !=0) level--; 
 440                 if (level == 0) swap_show(tgt);
 441             }
 442         if (!tgt.childNodes) return;
 443         var i=0;
 444         while (tgt.childNodes[i]) 
 445             {swap_showAll(tgt.childNodes[i], level, swap_class); i++; }
 446     }
 447 
 448     function swap_all(id, level, mode, swap_class)    
 449     {
 450         if (!document.getElementById) return false;
 451         var node=document.getElementById(id);
 452         if (!node) node=document.documentElement;
 453         if (mode=='hide') hide=true;
 454         else if (mode=='show') hide=false;
 455         else hide=node.swap;
 456         if (hide) {node.swap=false; return swap_hideAll(node, level, swap_class)}
 457         else {node.swap=true; return swap_showAll(node, level, swap_class)}
 458         return false;
 459     }
 460 /*]]></xsl:text>
 461         </cdata>*/
 462     </xsl:template>
 463     <!-- PI -->
 464     <xsl:template match="processing-instruction()" mode="xml:html">
 465         <span class="xml_pi">
 466             <xsl:apply-templates select="." mode="xml:text"/>
 467         </span>
 468     </xsl:template>
 469     <!-- add xmlns declarations -->
 470     <xsl:template name="xml:ns">
 471         <xsl:variable name="ns" select="../namespace::*"/>
 472         <xsl:for-each select="namespace::*">
 473             <xsl:if test="
 474             name() != 'xml' 
 475             and (
 476                 not(. = $ns) 
 477                 or not($ns[name()=name(current())])
 478             )">
 479                 <xsl:value-of select="' '"/>
 480                 <span class="xml_att">
 481                     <xsl:text>xmlns</xsl:text>
 482                     <xsl:if test="normalize-space(name())!=''">
 483                         <xsl:text>:</xsl:text>
 484                         <span class="xml_ns">
 485                             <xsl:value-of select="name()"/>
 486                         </span>
 487                     </xsl:if>
 488                 </span>
 489                 <xsl:text>="</xsl:text>
 490                 <span class="xml_ns">
 491                     <xsl:value-of select="."/>
 492                 </span>
 493                 <xsl:text>"</xsl:text>
 494             </xsl:if>
 495         </xsl:for-each>
 496     </xsl:template>
 497     <!-- attribute -->
 498     <xsl:template name="xml:att" match="@*" mode="xml:html">
 499         <xsl:param name="inline"/>
 500         <xsl:value-of select="' '"/>
 501         <span class="xml_att">
 502             <xsl:call-template name="xml:name"/>
 503         </span>
 504         <xsl:text>=&quot;</xsl:text>
 505         <xsl:if test=". != ''">
 506             <span class="xml_val">
 507                 <xsl:call-template name="replaces">
 508                     <xsl:with-param name="string" select="."/>
 509                     <xsl:with-param name="searches" select="
 510   document('')/*/xsl:template[@name='xml:ampgtlt']/search
 511 | document('')/*/xsl:template[@name='xml:quot']/search
 512                             "/>
 513                 </xsl:call-template>
 514             </span>
 515         </xsl:if>
 516         <xsl:text>"</xsl:text>
 517     </xsl:template>
 518     <!--  text -->
 519     <xsl:template match="text()[normalize-space(.)='']" mode="xml:html">
 520         <!-- only non empty text nodes are matched -->
 521     </xsl:template>
 522     <!--
 523     <xsl:template match="text()[normalize-space(.)='']" mode="xml:html"/>
 524 -->
 525     <xsl:template match="*/text()" mode="xml:html" priority="1">
 526         <xsl:param name="text" select="."/>
 527         <xsl:param name="pre"/>
 528         <xsl:param name="cdata"/>
 529         <xsl:param name="inline"/>
 530         <xsl:variable name="name">
 531             <xsl:choose>
 532                 <xsl:when test="$pre and ../*">pre</xsl:when>
 533                 <xsl:otherwise>span</xsl:otherwise>
 534             </xsl:choose>
 535         </xsl:variable>
 536         <xsl:element name="{$name}">
 537             <xsl:choose>
 538                 <xsl:when test="$cdata">
 539                     <xsl:attribute name="class">xml_cdata</xsl:attribute>
 540                     <xsl:value-of select="."/>
 541                 </xsl:when>
 542                 <xsl:when test="
 543                     (contains(., '&amp;') 
 544                     or contains(., '&lt;')
 545                     or contains(., '&gt;'))
 546                     and $text-replace
 547                     ">
 548                     <xsl:attribute name="class">xml_text</xsl:attribute>
 549                     <xsl:call-template name="replaces">
 550                         <xsl:with-param name="string" select="$text"/>
 551                         <xsl:with-param name="searches" select="
 552         document('')/*/xsl:template[@name='xml:ampgtlt']/search
 553                         "/>
 554                     </xsl:call-template>
 555                 </xsl:when>
 556                 <xsl:otherwise>
 557                     <xsl:attribute name="class">xml_text</xsl:attribute>
 558                     <xsl:value-of select="."/>
 559                 </xsl:otherwise>
 560             </xsl:choose>
 561         </xsl:element>
 562     </xsl:template>
 563     <!-- comment -->
 564     <xsl:template match="comment()" mode="xml:html">
 565         <xsl:if test=". != ''">
 566             <pre>
 567                 <xsl:choose>
 568                     <xsl:when test="contains(., '&#xa;')">
 569                         <a href="#i" class="pointer" id="src{generate-id()}" onclick="swap_one('{generate-id()}'); return false;">&lt;!--</a>
 570                     </xsl:when>
 571                     <xsl:otherwise>
 572                         <xsl:text>&lt;!--</xsl:text>
 573                     </xsl:otherwise>
 574                 </xsl:choose>
 575                 <span class="xml_rem" id="{generate-id()}">
 576                     <xsl:value-of select="."/>
 577                 </span>
 578                 <xsl:text>--&gt;</xsl:text>
 579             </pre>
 580         </xsl:if>
 581     </xsl:template>
 582     <!-- name -->
 583     <xsl:template name="xml:name">
 584         <xsl:param name="node" select="."/>
 585         <xsl:if test="contains(name($node), ':')">
 586             <span class="xml_ns">
 587                 <xsl:value-of select="concat(normalize-space(substring-before(name($node), ':')), ':')"/>
 588             </span>
 589         </xsl:if>
 590         <xsl:value-of select="local-name($node)"/>
 591     </xsl:template>
 592     <!--
 593      |    ELEMENT
 594      |-->
 595     <xsl:template match="*" name="xml:element" mode="xml:html">
 596         <xsl:param name="element" select="."/>
 597         <xsl:param name="content" select="$element/* | $element/text() | $element/comment()"/>
 598         <xsl:param name="local-name" select="concat(' ', local-name($element), ' ')"/>
 599         <xsl:param name="hide" select="contains($hides, $local-name) or $element/@xml:swap[contains(., 'hide')]"/>
 600         <xsl:param name="inline" select="contains($inlines, $local-name)"/>
 601         <xsl:param name="id" select="generate-id($element)"/>
 602         <xsl:variable name="block" select="contains($blocks, $local-name)"/>
 603         <xsl:variable name="cdata" select="contains($cdatas, $local-name)"/>
 604         <xsl:variable name="pre" select="contains($pres, $local-name) or @xml:space='preserve'"/>
 605         <xsl:variable name="el">
 606             <xsl:choose>
 607                 <xsl:when test="$cdata">pre</xsl:when>
 608                 <xsl:when test="$pre and not($content/*[contains($pres, concat(' ',local-name())) or @xml:space='preserve'])">pre</xsl:when>
 609                 <xsl:when test="$inline">span</xsl:when>
 610                 <xsl:when test="$block">div</xsl:when>
 611                 <xsl:otherwise>div</xsl:otherwise>
 612             </xsl:choose>
 613         </xsl:variable>
 614         <xsl:variable name="tag">
 615             <xsl:choose>
 616                 <xsl:when test="$inline">span</xsl:when>
 617                 <xsl:when test="$cdata">span</xsl:when>
 618                 <xsl:when test="$pre">span</xsl:when>
 619                 <xsl:when test="$block">span</xsl:when>
 620                 <xsl:otherwise>span</xsl:otherwise>
 621             </xsl:choose>
 622         </xsl:variable>
 623         <xsl:variable name="cont">
 624             <xsl:choose>
 625                 <xsl:when test="$inline">span</xsl:when>
 626                 <xsl:when test="$block">span</xsl:when>
 627                 <xsl:when test="$content/descendant-or-self::*[1]">blockquote</xsl:when>
 628                 <xsl:when test="$cdata">span</xsl:when>
 629                 <xsl:when test="$pre">span</xsl:when>
 630                 <xsl:otherwise>span</xsl:otherwise>
 631             </xsl:choose>
 632         </xsl:variable>
 633         <xsl:variable name="swap">
 634             <xsl:choose>
 635                 <xsl:when test="$hide">a</xsl:when>
 636                 <xsl:when test="$cdata and text()">a</xsl:when>
 637                 <xsl:when test="$pre and text()">a</xsl:when>
 638                 <xsl:when test="$inline">span</xsl:when>
 639                 <xsl:when test="$content/descendant-or-self::*[1]">a</xsl:when>
 640                 <xsl:otherwise>span</xsl:otherwise>
 641             </xsl:choose>
 642         </xsl:variable>
 643         <xsl:element name="{$el}">
 644             <!-- element-open -->
 645             <xsl:element name="{$tag}">
 646                 <xsl:attribute name="id">
 647                     <xsl:text>src</xsl:text>
 648                     <xsl:value-of select="$id"/>
 649                 </xsl:attribute>
 650                 <xsl:attribute name="class">xml_tag</xsl:attribute>
 651                 <xsl:element name="{$swap}">
 652                     <xsl:if test="$swap='a'">
 653                         <xsl:attribute name="name">
 654                             <xsl:text>src</xsl:text>
 655                             <xsl:value-of select="$id"/>
 656                         </xsl:attribute>
 657                         <xsl:attribute name="href">#end<xsl:value-of select="$id"/>
 658                         </xsl:attribute>
 659                         <xsl:attribute name="onclick">if (window.swap_one) a=swap_one('<xsl:value-of select="$id"/>'); if (a) return false;</xsl:attribute>
 660                     </xsl:if>
 661                     <xsl:text>&lt;</xsl:text>
 662                     <span class="xml_name">
 663                         <xsl:if test="$hide">
 664                             <xsl:attribute name="class">xml_name swap_hide</xsl:attribute>
 665                         </xsl:if>
 666                         <xsl:call-template name="xml:name">
 667                             <xsl:with-param name="node" select="$element"/>
 668                         </xsl:call-template>
 669                     </span>
 670                     <xsl:call-template name="xml:ns"/>
 671                     <xsl:apply-templates select="$element/@*[name()!='xml:swap']" mode="xml:html">
 672                         <xsl:with-param name="inline" select="$inline"/>
 673                     </xsl:apply-templates>
 674                     <xsl:if test="not($content)">/</xsl:if>
 675                     <xsl:text>&gt;</xsl:text>
 676                     <xsl:if test="$cdata and $content">
 677                         <xsl:text>&lt;![CDATA[</xsl:text>
 678                     </xsl:if>
 679                 </xsl:element>
 680             </xsl:element>
 681             <xsl:if test="$content">
 682                 <!-- element-content -->
 683                 <xsl:element name="{$cont}">
 684                     <xsl:attribute name="id">
 685                         <xsl:value-of select="$id"/>
 686                     </xsl:attribute>
 687                     <xsl:if test="$hide">
 688                         <xsl:attribute name="style">display:none; {};</xsl:attribute>
 689                     </xsl:if>
 690                     <xsl:attribute name="class">
 691                         <xsl:if test="$cont ='blockquote'">xml_margin</xsl:if>
 692                     </xsl:attribute>
 693                     <xsl:choose>
 694                         <xsl:when test="$block or $inline">
 695                             <xsl:apply-templates select="$content" mode="xml:html">
 696                                 <xsl:with-param name="pre" select="$pre"/>
 697                                 <xsl:with-param name="cdata" select="$cdata"/>
 698                                 <xsl:with-param name="inline" select="true()"/>
 699                             </xsl:apply-templates>
 700                         </xsl:when>
 701                         <xsl:otherwise>
 702                             <xsl:apply-templates select="$content" mode="xml:html">
 703                                 <xsl:with-param name="pre" select="$pre"/>
 704                                 <xsl:with-param name="cdata" select="$cdata"/>
 705                             </xsl:apply-templates>
 706                         </xsl:otherwise>
 707                     </xsl:choose>
 708                 </xsl:element>
 709                 <!-- element-close -->
 710                 <xsl:element name="{$tag}">
 711                     <xsl:attribute name="class">xml_tag</xsl:attribute>
 712                     <xsl:if test="$cdata">
 713                         <xsl:text>]]&gt;</xsl:text>
 714                     </xsl:if>
 715                     <xsl:text>&lt;/</xsl:text>
 716                     <a class="xml_name" name="end{generate-id($element)}">
 717                         <xsl:if test="$cont ='blockquote'">
 718                             <xsl:attribute name="href">#src<xsl:value-of select="$id"/>
 719                             </xsl:attribute>
 720                         </xsl:if>
 721                         <xsl:call-template name="xml:name">
 722                             <xsl:with-param name="node" select="$element"/>
 723                         </xsl:call-template>
 724                     </a>
 725                     <xsl:text>&gt;</xsl:text>
 726                 </xsl:element>
 727             </xsl:if>
 728         </xsl:element>
 729     </xsl:template>
 730     <!-- unplugged -->
 731     <!--
 732     <xsl:template match="*[local-name()='include' or local-name()='import']" mode="xml:html">
 733         <xsl:call-template name="xml:element">
 734             <xsl:with-param name="element" select="."/>
 735             <xsl:with-param name="content" select="document(@href, .)"/>
 736             <xsl:with-param name="hide" select="true()"/>
 737         </xsl:call-template>
 738     </xsl:template>
 739     -->
 740     <!--
 741      find/replace on a set of nodes
 742      thanks to jeni@jenitennison.com
 743      http://www.biglist.com/lists/xsl-list/archives/200110/msg01229.html
 744      fixed and adapted by frederic.glorieux@ajlsm.com -->
 745     <xsl:template name="replaces">
 746         <xsl:param name="string"/>
 747         <xsl:param name="searches" select="no-node"/>
 748         <xsl:choose>
 749             <!--
 750             <xsl:when xmlns:java="java" xmlns:xalan="http://xml.apache.org/xalan" test="function-available('xalan:distinct')">
 751                 <xsl:value-of select="java:org.apache.xalan.xsltc.compiler.util.Util.replace($string, 'a', '__')"/>
 752             </xsl:when>
 753         -->
 754             <xsl:when test="false()">
 755                 <!-- -->
 756             </xsl:when>
 757             <xsl:otherwise>
 758                 <xsl:variable name="first" select="$searches[1]"/>
 759                 <xsl:variable name="rest" select="$searches[position() > 1]"/>
 760                 <xsl:choose>
 761                     <xsl:when test="$first and contains($string, $first/find)">
 762                         <!-- replace with rest in before -->
 763                         <xsl:call-template name="replaces">
 764                             <xsl:with-param name="string" select="substring-before($string, $first/find)"/>
 765                             <xsl:with-param name="searches" select="$rest"/>
 766                         </xsl:call-template>
 767                         <!-- copy-of current replace -->
 768                         <xsl:copy-of select="$first/replace/node()"/>
 769                         <!-- replace with all in after -->
 770                         <xsl:call-template name="replaces">
 771                             <xsl:with-param name="string" select="substring-after($string, $first/find)"/>
 772                             <xsl:with-param name="searches" select="$searches"/>
 773                         </xsl:call-template>
 774                     </xsl:when>
 775                     <!-- empty the searches -->
 776                     <xsl:when test="$rest">
 777                         <xsl:call-template name="replaces">
 778                             <xsl:with-param name="string" select="$string"/>
 779                             <xsl:with-param name="searches" select="$rest"/>
 780                         </xsl:call-template>
 781                     </xsl:when>
 782                     <xsl:otherwise>
 783                         <xsl:value-of select="$string"/>
 784                     </xsl:otherwise>
 785                 </xsl:choose>
 786             </xsl:otherwise>
 787         </xsl:choose>
 788     </xsl:template>
 789     <!-- find/replace to search in attributes value -->
 790     <xsl:template name="xml:quot">
 791         <search>
 792             <find>&quot;</find>
 793             <replace>&amp;quot;</replace>
 794         </search>
 795         <!--
 796         <search>
 797             <find>&apos;</find>
 798             <replace>&amp;apos;</replace>
 799         </search>
 800         <search>
 801             <find>&#xA;</find>
 802             <replace>
 803                 <br/>
 804             </replace>
 805         </search>
 806         -->
 807     </xsl:template>
 808     <xsl:template name="xml:br">
 809         <search>
 810             <find>&#xA;</find>
 811             <replace>
 812                 <br/>
 813             </replace>
 814         </search>
 815     </xsl:template>
 816     <!--
 817         <search>
 818             <find>&#xA;</find>
 819             <replace>
 820                 <br/>
 821             </replace>
 822         </search>
 823 -->
 824     <!-- find/replace to search -->
 825     <xsl:template name="xml:ampgtlt">
 826         <!-- entities -->
 827         <search>
 828             <find>&amp;</find>
 829             <replace>&amp;amp;</replace>
 830         </search>
 831         <search>
 832             <find>&gt;</find>
 833             <replace>&amp;gt;</replace>
 834         </search>
 835         <search>
 836             <find>&lt;</find>
 837             <replace>&amp;lt;</replace>
 838         </search>
 839     </xsl:template>
 840     <!--
 841      |    text mode
 842      |-->
 843     <!-- PI -->
 844     <xsl:template match="processing-instruction()" mode="xml:text">
 845         <xsl:text>&lt;?</xsl:text>
 846         <xsl:value-of select="concat(name(.), ' ', .)"/>
 847         <xsl:text>?&gt;</xsl:text>
 848     </xsl:template>
 849     <!-- @* -->
 850     <xsl:template match="@*" mode="xml:text">
 851         <xsl:value-of select="concat(' ', name(), '=&quot;', ., '&quot;')"/>
 852     </xsl:template>
 853     <!-- comment -->
 854     <xsl:template match="comment()" mode="xml:text">
 855         <xsl:call-template name="xml:margin"/>
 856         <xsl:text>&lt;!--</xsl:text>
 857         <xsl:value-of select="."/>
 858         <xsl:text>--&gt;</xsl:text>
 859     </xsl:template>
 860     <!-- * -->
 861     <xsl:template match="*" mode="xml:text">
 862         <xsl:call-template name="xml:margin"/>
 863         <xsl:text>&lt;</xsl:text>
 864         <xsl:value-of select="name()"/>
 865         <xsl:apply-templates select="@*" mode="xml:text"/>
 866         <xsl:call-template name="xml:ns-text"/>
 867         <xsl:if test="not(node() | comment())">
 868             <xsl:text>/</xsl:text>
 869         </xsl:if>
 870         <xsl:text>&gt;</xsl:text>
 871         <xsl:if test="comment() | node ()">
 872             <xsl:apply-templates select="comment() | node () | processing-instruction()" mode="xml:text"/>
 873             <xsl:if test="* | comment()">
 874                 <xsl:call-template name="xml:margin"/>
 875             </xsl:if>
 876             <xsl:text>&lt;/</xsl:text>
 877             <xsl:value-of select="name()"/>
 878             <xsl:text>&gt;</xsl:text>
 879         </xsl:if>
 880     </xsl:template>
 881     <!-- xmlns -->
 882     <xsl:template name="xml:ns-text">
 883         <xsl:variable name="ns" select="../namespace::*"/>
 884         <xsl:for-each select="namespace::*">
 885             <xsl:if test="
 886             name() != 'xml' 
 887             and (
 888                 not(. = $ns) 
 889                 or not($ns[name()=name(current())])
 890             )">
 891                 <xsl:text> xmlns</xsl:text>
 892                 <xsl:if test="normalize-space(name())!=''">
 893                     <xsl:text>:</xsl:text>
 894                     <xsl:value-of select="name()"/>
 895                 </xsl:if>
 896                 <xsl:text>="</xsl:text>
 897                 <xsl:value-of select="."/>
 898                 <xsl:text>"</xsl:text>
 899             </xsl:if>
 900         </xsl:for-each>
 901     </xsl:template>
 902     <!-- "breakable" space margin -->
 903     <xsl:template name="xml:margin">
 904         <xsl:text>&#32;
 905 </xsl:text>
 906         <xsl:for-each select="ancestor::*">
 907             <xsl:text>&#32;&#32;&#32;&#32;</xsl:text>
 908         </xsl:for-each>
 909     </xsl:template>
 910 </xsl:stylesheet>

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.