1<?xml version="1.0" encoding="UTF-8" ?>
2<!--
3  Copyright (C) 2005, 2006 Etienne Giraudy, InStranet Inc
4  Copyright (C) 2005, 2007 Etienne Giraudy
5
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  Lesser General Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19-->
20
21<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
22   <xsl:output
23         method="xml" indent="yes"
24         doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
25         doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
26         encoding="UTF-8"/>
27
28   <xsl:variable name="apos" select="&quot;'&quot;"/>
29   <xsl:key name="lbc-code-key"        match="/BugCollection/BugInstance" use="concat(@category,@abbrev)" />
30   <xsl:key name="lbc-bug-key"         match="/BugCollection/BugInstance" use="concat(@category,@abbrev,@type)" />
31   <xsl:key name="lbp-class-b-t"  match="/BugCollection/BugInstance" use="concat(Class/@classname,@type)" />
32
33<xsl:template match="/" >
34
35<html>
36   <head>
37      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
38      <title>
39         FindBugs (<xsl:value-of select="/BugCollection/@version" />) 
40         Analysis for 
41         <xsl:choose>
42            <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
43            <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
44         </xsl:choose>
45      </title>
46      <style type="text/css">
47         html, body, div, form {
48            margin:0px;
49            padding:0px;
50         }
51         body {
52            padding:3px;
53         }
54         a, a:link , a:active, a:visited, a:hover {
55            text-decoration: none; color: black;
56         }
57         #navlist {
58                 padding: 3px 0;
59                 margin-left: 0;
60                 border-bottom: 1px solid #778;
61                 font: bold 12px Verdana, sans-serif;
62         }
63         #navlist li {
64                 list-style: none;
65                 margin: 0;
66                 display: inline;
67         }
68         #navlist li a {
69                 padding: 3px 0.5em;
70                 margin-left: 3px;
71                 border: 1px solid #778;
72                 border-bottom: none;
73                 background: #DDE;
74                 text-decoration: none;
75         }
76         #navlist li a:link { color: #448; }
77         #navlist li a:visited { color: #667; }
78         #navlist li a:hover {
79                 color: #000;
80                 background: #AAE;
81                 border-color: #227;
82         }
83         #navlist li a.current {
84                 background: white;
85                 border-bottom: 1px solid white;
86         }
87         #filterWrapper {
88            margin-bottom:5px;
89         }
90         #displayWrapper {
91            margin-top:5px;
92         }
93         .message {
94            background:#BBBBBB;
95           border: 1px solid #778;
96         }
97         .displayContainer {
98            border:1px solid #555555;
99            margin-top:3px;
100            padding: 3px;
101            display:none;
102         }
103         #summaryContainer table,
104         #historyContainer table {
105            border:1px solid black;
106         }
107         #summaryContainer th,
108         #historyContainer th {
109            background: #aaaaaa;
110            color: white;
111         }
112         #summaryContainer th, #summaryContainer td,
113         #historyContainer th, #historyContainer td {
114            padding: 2px 4px 2px 4px;
115         }
116         .summary-name {
117            background: #eeeeee;
118            text-align:left;
119         }
120         .summary-size {
121            background: #eeeeee;
122            text-align:center;
123         }
124         .summary-priority-all {
125            background: #dddddd;
126            text-align:center;
127         }
128         .summary-priority-1 {
129            background: red;
130            text-align:center;
131         }
132         .summary-priority-2 {
133            background: orange;
134            text-align:center;
135         }
136         .summary-priority-3 {
137            background: green;
138            text-align:center;
139         }
140         .summary-priority-4 {
141            background: blue;
142            text-align:center;
143         }
144
145         .bugList-level1 {
146            margin-bottom:5px;
147         }
148         .bugList-level1, .bugList-level2, .bugList-level3, .bugList-level4 {
149            background-color: #ffffff;
150            margin-left:15px;
151            padding-left:10px;
152         }
153         .bugList-level1-label, .bugList-level2-label, .bugList-level3-label, .bugList-level4-label {
154            background-color: #bbbbbb;
155            border: 1px solid black;
156            padding: 1px 3px 1px 3px;;
157         }
158         .bugList-level2-label, .bugList-level3-label, .bugList-level4-label {
159            border-width: 0px 1px 1px 1px;
160         }
161         .bugList-level4-label {
162            background-color: #ffffff;
163            border: 0px 0px 1px 0px;
164         }
165         .bugList-level4 {
166            border: 0px 1px 1px 1px;
167         }
168
169         .bugList-level4-inner {
170            border-style: solid;
171            border-color: black;
172            border-width: 0px 1px 1px 1px;
173         }
174         .b-r {
175            font-size: 10pt; font-weight: bold; padding: 0 0 0 60px;
176         }
177         .b-d {
178            font-weight: normal; background: #ccccc0;
179            padding: 0 5px 0 5px; margin: 0px;
180         }
181         .b-1 {
182            background: red; height: 0.5em; width: 1em;
183            margin-right: 0.5em;
184         }
185         .b-2 {
186            background: orange; height: 0.5em; width: 1em;
187            margin-right: 0.5em;
188         }
189         .b-3 {
190            background: green; height: 0.5em; width: 1em;
191            margin-right: 0.5em;
192         }
193         .b-4 {
194            background: blue; height: 0.5em; width: 1em;
195            margin-right: 0.5em;
196         }
197
198      </style>
199      <script type='text/javascript'><xsl:text disable-output-escaping='yes'><![CDATA[
200         var menus            = new Array('summary','info','history','listByCategories','listByPackages');
201         var selectedMenuId   = "summary";
202         var selectedVersion  = -1;
203         var selectedPriority = 4;
204         var lastVersion      = 0;
205         var includeFixedIntroducedBugs;
206
207         var bPackageNamesPopulated = false;
208
209         var filterContainerId              = "filterWrapper";
210         var historyControlContainerId      = "historyControlWrapper";
211         var messageContainerId             = "messageContainer";
212         var summaryContainerId             = "summaryContainer";
213         var infoContainerId                = "infoContainer";
214         var historyContainerId             = "historyContainer";
215         var listByCategoriesContainerId    = "listByCategoriesContainer";
216         var listByPackagesContainerId      = "listByPackagesContainer";
217
218         var idxCatKey = 0; var idxCatDescr = 1; var idxBugCat = 1;
219         var idxCodeKey = 0; var idxCodeDescr = 1; var idxBugCode = 2;
220         var idxPatternKey = 2; var idxPatternDescr = 3; var idxBugPattern = 3;
221         var idxBugKey = 0; var idxBugDescr = 6;
222         var idxBugClass = 6, idxBugPackage = 7;
223
224         // main init function
225         function init() {
226            loadFilter();
227            selectMenu(selectedMenuId);
228            lastVersion = versions.length - 1;
229         }
230
231         // menu callback function
232         function selectMenu(menuId) {
233            document.getElementById(selectedMenuId).className="none";
234            document.getElementById(menuId).className="current";
235            if (menuId!=selectedMenuId) {
236               hideMenu(selectedMenuId);
237               selectedMenuId = menuId;
238            }
239            if (menuId=="summary")           displaySummary();
240            if (menuId=="info")              displayInfo();
241            if (menuId=="history")           displayHistory();
242            if (menuId=="listByCategories")  displayListByCategories();
243            if (menuId=="listByPackages")    displayListByPackages();
244         }
245
246         // display filter
247         function loadFilter() {
248            var versionsBox = document.findbugsForm.versions.options;
249            versionsBox[0] = new Option(" -- All Versions -- ","-1");
250            versionsBox.selectedIndex = 0;
251            if (versions.length>=1) {
252               for (x=0; versions.length>1 && x<versions.length; x++) {
253                  versionsBox[x+1] = new Option(" Bugs at release: "+versions[versions.length-x-1][1], versions[versions.length-x-1][0]);
254               }
255            }
256
257            var prioritiesBox = document.findbugsForm.priorities.options;
258            prioritiesBox[0] = new Option(" -- All priorities -- ", "4");
259            prioritiesBox[1] = new Option(" P1 bugs ", "1");
260            prioritiesBox[2] = new Option(" P1 and P2 bugs ", "2");
261            prioritiesBox[3] = new Option(" P1, P2 and P3 bugs ", "3");
262         }
263
264         // display a message
265         function displayMessage(msg) {
266            var container = document.getElementById(messageContainerId);
267            container.innerHTML = "<div class='message'>"+msg+"</div>";
268         }
269
270         // reset displayed message
271         function resetMessage() {
272            var container = document.getElementById(messageContainerId);
273            container.innerHTML = "";
274         }
275
276         function hideMenu(menuId) {
277            var container = menuId+"Container";
278            document.getElementById(container).style.display="none";
279         }
280
281         // filter callback function
282         function filter() {
283            var versionsBox = document.findbugsForm.versions.options;
284            selectedVersion = versionsBox[versionsBox.selectedIndex].value;
285
286            var prioritiesBox = document.findbugsForm.priorities.options;
287            selectedPriority = prioritiesBox[prioritiesBox.selectedIndex].value;
288
289            selectMenu(selectedMenuId);
290         }
291
292         // includeFixedBugs callback function
293         function includeFixedIntroducedBugsInHistory() {
294            includeFixedIntroducedBugs =
295              document.findbugsHistoryControlForm.includeFixedIntroducedBugs.checked;
296
297            selectMenu(selectedMenuId);
298         }
299
300         // display summary tab
301         function displaySummary() {
302            resetMessage();
303            hide(filterContainerId);
304            hide(historyControlContainerId);
305            var container = document.getElementById(summaryContainerId);
306            container.style.display="block";
307         }
308
309         // display info tab
310         function displayInfo() {
311            resetMessage();
312            hide(filterContainerId);
313            hide(historyControlContainerId);
314            var container = document.getElementById(infoContainerId);
315            container.style.display="block";
316         }
317
318         // display history tab
319         function displayHistory() {
320            displayMessage("Loading history...");
321            hide(filterContainerId);
322            show(historyControlContainerId);
323            var container = document.getElementById(historyContainerId);
324            var content = "";
325            var i=0;
326            var p = [0,0,0,0,0];
327            var f = [0,0,0,0,0];
328
329            content += "<table><tr><th>Release</th><th>Bugs</th><th>Bugs p1</th><th>Bugs p2</th><th>Bugs p3</th><th>Bugs Exp.</th></tr>";
330
331            var aSpan   = "<span title='Bugs introduced in this release that have not been fixed.'>";
332            var fSpan   = "<span title='Bugs fixed in this release.'>";
333            var fiSpan  = "<span title='Bugs introduced in this release that were fixed in later releases.'>";
334            var afiSpan = "<span title='Total number of bugs introduced in this release.'>";
335            var eSpan   = "</span>";
336
337            if(includeFixedIntroducedBugs) {
338                for (i=(versions.length-1); i>0; i--) {
339                    v = countBugsVersion(i, 4);
340                    t = countTotalBugsVersion(i);
341                    o = countFixedButActiveBugsVersion(i);
342                    f = countFixedBugsInVersion(i);
343                    fi = countFixedBugsIntroducedInVersion(i);
344                    content += "<tr>";
345                    content += "<td class='summary-name'>" + versions[i][1] + "</td>";
346                    content += "<td class='summary-priority-all'> " + (t[0] + o[0]) + " (+" + afiSpan + (v[0] + fi[0]) + eSpan +
347                      " [" + aSpan + v[0] + eSpan + " / " + fiSpan + fi[0] + eSpan + "] " + eSpan + " / -" + fSpan + f[0] + eSpan + ") </td>";
348                    content += "<td class='summary-priority-1'> " + (t[1] + o[1]) + " (+" + afiSpan + (v[1] + fi[1]) + eSpan +
349                      " [" + aSpan + v[1] + eSpan + " / " + fiSpan + fi[1] + eSpan + "] " + eSpan + " / -" + fSpan + f[1] + eSpan + ") </td>";
350                    content += "<td class='summary-priority-2'> " + (t[2] + o[2]) + " (+" + afiSpan + (v[2] + fi[2]) + eSpan +
351                      " [" + aSpan + v[2] + eSpan + " / " + fiSpan + fi[2] + eSpan + "] " + eSpan + " / -" + fSpan + f[2] + eSpan + ") </td>";
352                    content += "<td class='summary-priority-3'> " + (t[3] + o[3]) + " (+" + afiSpan + (v[3] + fi[3]) + eSpan +
353                      " [" + aSpan + v[3] + eSpan + " / " + fiSpan + fi[3] + eSpan + "] " + eSpan + " / -" + fSpan + f[3] + eSpan + ") </td>";
354                    content += "<td class='summary-priority-4'> " + (t[4] + o[4]) + " (+" + afiSpan + (v[4] + fi[4]) + eSpan +
355                      " [" + aSpan + v[4] + eSpan + " / " + fiSpan + fi[4] + eSpan + "] " + eSpan + " / -" + fSpan + f[4] + eSpan + ") </td>";
356                    content += "</tr>";
357                }
358            } else {
359                for (i=(versions.length-1); i>0; i--) {
360                    v = countBugsVersion(i, 4);
361                    t = countTotalBugsVersion(i);
362                    o = countFixedButActiveBugsVersion(i);
363                    f = countFixedBugsInVersion(i);
364                    content += "<tr>";
365                    content += "<td class='summary-name'>" + versions[i][1] + "</td>";
366                    content += "<td class='summary-priority-all'> " + (t[0] + o[0]) + " (+" + aSpan + v[0] + eSpan + " / -" + fSpan + f[0] + eSpan + ") </td>";
367                    content += "<td class='summary-priority-1'  > " + (t[1] + o[1]) + " (+" + aSpan + v[1] + eSpan + " / -" + fSpan + f[1] + eSpan + ") </td>";
368                    content += "<td class='summary-priority-2'  > " + (t[2] + o[2]) + " (+" + aSpan + v[2] + eSpan + " / -" + fSpan + f[2] + eSpan + ") </td>";
369                    content += "<td class='summary-priority-3'  > " + (t[3] + o[3]) + " (+" + aSpan + v[3] + eSpan + " / -" + fSpan + f[3] + eSpan + ") </td>";
370                    content += "<td class='summary-priority-4'  > " + (t[4] + o[4]) + " (+" + aSpan + v[4] + eSpan + " / -" + fSpan + f[4] + eSpan + ") </td>";
371                    content += "</tr>";
372                }
373            }
374
375            t = countTotalBugsVersion(0);
376            o = countFixedButActiveBugsVersion(0);
377            content += "<tr>";
378            content += "<td class='summary-name'>" + versions[0][1] + "</td>";
379            content += "<td class='summary-priority-all'> " + (t[0] + o[0]) + " </td>";
380            content += "<td class='summary-priority-1'  > " + (t[1] + o[1]) + " </td>";
381            content += "<td class='summary-priority-2'  > " + (t[2] + o[2]) + " </td>";
382            content += "<td class='summary-priority-3'  > " + (t[3] + o[3]) + " </td>";
383            content += "<td class='summary-priority-4'  > " + (t[4] + o[4]) + " </td>";
384            content += "</tr>";
385
386            content += "</table>";
387            container.innerHTML = content;
388            container.style.display="block";
389            resetMessage();
390         }
391
392         // display list by cat tab
393         function displayListByCategories() {
394            hide(historyControlContainerId);
395            show(filterContainerId);
396            var container = document.getElementById(listByCategoriesContainerId);
397            container.innerHTML = "";
398            container.style.display="block";
399            displayMessage("Loading stats (categories)...");
400            container.innerHTML = displayLevel1("lbc", "Stats by Bug Categories");
401            resetMessage();
402         }
403
404         // display list by package tab
405         function displayListByPackages() {
406            hide(historyControlContainerId);
407            show(filterContainerId);
408            var container = document.getElementById(listByPackagesContainerId);
409            container.style.display="block";
410            if (!bPackageNamesPopulated) {
411               displayMessage("Initializing...");
412               populatePackageNames();
413            }
414            displayMessage("Loading stats (packages)...");
415            container.innerHTML = displayLevel1("lbp", "Stats by Bug Package");
416            resetMessage();
417         }
418
419         // callback function for list item click
420         function toggleList(listType, containerId, id1, id2, id3) {
421            var container = document.getElementById(containerId);
422            if (container.style.display=="block") {
423               container.style.display="none";
424            } else {
425               if (listType=="lbc") {
426                  if (id1.length>0 && id2.length==0 && id3.length==0) {
427                     displayCategoriesCodes(containerId, id1);
428                  } else if (id1.length>0 && id2.length>0 && id3.length==0) {
429                     displayCategoriesCodesPatterns(containerId, id1, id2);
430                  } else if (id1.length>0 && id2.length>0 && id3.length>0) {
431                     displayCategoriesCodesPatternsBugs(containerId, id1, id2, id3);
432                  } else {
433                     // ???
434                  }
435               } else if (listType=="lbp") {
436                  if (id1.length>0 && id2.length==0 && id3.length==0) {
437                     displayPackageCodes(containerId, id1);
438                  } else if (id1.length>0 && id2.length>0 && id3.length==0) {
439                     displayPackageClassPatterns(containerId, id1, id2);
440                  } else if (id1.length>0 && id2.length>0 && id3.length>0) {
441                     displayPackageClassPatternsBugs(containerId, id1, id2, id3);
442                  } else {
443                     // ???
444                  }
445               } else {
446                  // ????
447               }
448            }
449         }
450
451         // list by categories, display bug cat>codes
452         function displayCategoriesCodes(containerId, catId) {
453            displayMessage("Loading stats (codes)...");
454            var container = document.getElementById(containerId);
455            container.style.display="block";
456            if (container.innerHTML=="Loading..." || container.innerHTML=="") {
457               container.innerHTML = displayLevel2("lbc", catId);
458            }
459            resetMessage();
460         }
461
462         // list by categories, display bug package>codes
463         function displayPackageCodes(containerId, packageId) {
464            displayMessage("Loading stats (codes)...");
465            var container = document.getElementById(containerId);
466            container.style.display="block";
467            if (container.innerHTML=="Loading..." || container.innerHTML=="") {
468               container.innerHTML = displayLevel2("lbp", packageId);
469            }
470            resetMessage();
471         }
472
473         // list by categories, display bug cat>codes>patterns
474         function displayCategoriesCodesPatterns(containerId, catId, codeId) {
475            displayMessage("Loading stats (patterns)...");
476            var container = document.getElementById(containerId);
477            container.style.display="block";
478            if (container.innerHTML=="Loading..." || container.innerHTML=="")
479               container.innerHTML = displayLevel3("lbc", catId, codeId);
480            resetMessage();
481         }
482
483         // list by package, display bug package>class>patterns
484         function displayPackageClassPatterns(containerId, packageId, classId) {
485            displayMessage("Loading stats (patterns)...");
486            var container = document.getElementById(containerId);
487            container.style.display="block";
488            if (container.innerHTML=="Loading..." || container.innerHTML=="")
489               container.innerHTML = displayLevel3("lbp", packageId, classId);
490            resetMessage();
491         }
492
493         // list by categories, display bug cat>codes>patterns>bugs
494         function displayCategoriesCodesPatternsBugs(containerId, catId, codeId, patternId) {
495            displayMessage("Loading stats (bugs)...");
496            var container = document.getElementById(containerId);
497            container.style.display="block";
498            if (container.innerHTML=="Loading..." || container.innerHTML=="")
499               container.innerHTML = displayLevel4("lbc", catId, codeId, patternId);
500            resetMessage();
501         }
502
503         // list by package, display bug package>class>patterns>bugs
504         function displayPackageClassPatternsBugs(containerId, packageId, classId, patternId) {
505            displayMessage("Loading stats (bugs)...");
506            var container = document.getElementById(containerId);
507            container.style.display="block";
508            if (container.innerHTML=="Loading..." || container.innerHTML=="")
509               container.innerHTML = displayLevel4("lbp",  packageId, classId, patternId);
510            resetMessage();
511         }
512
513         // generate level 1 list
514         function displayLevel1(list, title) {
515            var content = "";
516            var content2 = "";
517
518            content += "<h3>"+title+"</h3>";
519            content += getPriorityLegend();
520            content2 += "<div class='bugList'>";
521
522            var id = "";
523            var containerId = "";
524            var subContainerId = "";
525            var prefixSub = "";
526            var prefixId = "";
527            var p = [0,0,0,0,0];
528            var numberOfBugs = 0;
529            var label = "";
530            var max = 0;
531            if (list=="lbc") {
532               max = categories.length;
533            } else if (list=="lbp") {
534               max = packageStats.length;
535            }
536
537            for (var x=0; x<max -1; x++) {
538               if (list=="lbp" && packageStats[x][1]=="0") continue;
539
540               if (list=="lbc") {
541                  id = categories[x][idxCatKey];
542                  label = categories[x][idxCatDescr];
543                  containerId = "categories-" + id;
544                  subContainerId = "cat-"+id;
545                  p = countBugsCat(selectedVersion, selectedPriority, id, idxBugCat);
546               }
547               if (list=="lbp") {
548                  id = packageStats[x][0];
549                  label = packageStats[x][0];
550                  containerId = "packages-" + id;
551                  subContainerId = "package-"+id;
552                  p = countBugsPackage(selectedVersion, selectedPriority, id, idxBugPackage);
553               }
554
555               subContainerId = prefixSub+id;
556
557               var total = p[1]+p[2]+p[3]+p[4];
558               if (total > 0) {
559                  content2 += addListItem( 1, containerId, label, total, p, subContainerId,
560                                          "toggleList('" + list + "', '" + subContainerId + "', '"+ id + "', '', '')"
561                                          );
562               }
563               numberOfBugs += total;
564            }
565            content2 += "</div>";
566            content += "<h4>Total number of bugs";
567            if (selectedVersion!=-1) {
568               content += " (introduced in release " + versions[selectedVersion][1] +")";
569            }
570            content += ": "+numberOfBugs+"</h4>";
571            return content+content2;
572         }
573
574         // generate level 2 list
575        function displayLevel2(list, id1) {
576            var content = "";
577            var code = "";
578            var containerId = "";
579            var subContainerId = "";
580            var p = [0,0,0,0,0];
581            var max = 0;
582            var id2 = "";
583            if (list=="lbc") {
584               max = codes.length;
585            } else if (list=="lbp") {
586               max = classStats.length;
587            }
588
589            for (var x=0; x<max -1; x++) {
590               if (list=="lbp" && classStats[x][3]=="0") continue;
591
592               if (list=="lbc") {
593                  id2 = codes[x][idxCodeKey];
594                  label = codes[x][idxCodeDescr];
595                  containerId = "codes-"+id1;
596                  subContainerId = "cat-" + id1 + "-code-" + id2;
597                  p = countBugsCode(selectedVersion, selectedPriority, id1, idxBugCat, id2, idxBugCode);
598               }
599               if (list=="lbp") {
600                  id2 = classStats[x][0];
601                  label = classStats[x][0];
602                  containerId = "packages-"+id1;
603                  subContainerId = "package-" + id1 + "-class-" + id2;
604                  p = countBugsClass(selectedVersion, selectedPriority, id1, idxBugPackage, id2, idxBugClass);
605               }
606
607               var total = p[1]+p[2]+p[3]+p[4];
608               if (total > 0) {
609                  content += addListItem( 2, containerId, label, total, p, subContainerId,
610                                          "toggleList('"+ list + "', '" + subContainerId + "', '"+ id1 + "', '"+ id2 + "', '')"
611                                          );
612               }
613            }
614            return content;
615         }
616
617         // generate level 3 list
618        function displayLevel3(list, id1, id2) {
619            var content = "";
620            var containerId = "";
621            var subContainerId = "";
622            var p = [0,0,0,0,0];
623            var max = 0;
624            var label = "";
625            var id3 = "";
626
627            if (list=="lbc") {
628               max = patterns.length;
629            } else if (list=="lbp") {
630               max = patterns.length;
631            }
632
633            for (var x=0; x<max -1; x++) {
634               //if (list=="lbp" && (patterns[x][0]!=id1 || patterns[x][1]!=id2)) continue;
635               //if (list=="lbp" && classStats[x][3]=="0") continue;
636
637               if (list=="lbc") {
638                  id3 = patterns[x][idxPatternKey];;
639                  label = patterns[x][idxPatternDescr];
640                  containerId = "patterns-"+id1;
641                  subContainerId = "cat-" + id1 + "-code-" + id2 + "-pattern-" + id3;
642                  p = countBugsPattern(selectedVersion, selectedPriority, id1, idxBugCat, id2, idxBugCode, id3, idxBugPattern);
643               }
644               if (list=="lbp") {
645                  id3 = patterns[x][idxPatternKey];;
646                  label = patterns[x][idxPatternDescr];
647                  containerId = "classpatterns-"+id1;
648                  subContainerId = "package-" + id1 + "-class-" + id2 + "-pattern-" + id3;
649                  p = countBugsClassPattern(selectedVersion, selectedPriority, id2, idxBugClass, id3, idxBugPattern);
650               }
651
652               var total = p[1]+p[2]+p[3]+p[4];
653               if (total > 0) {
654                  content += addListItem( 3, containerId, label, total, p, subContainerId,
655                                          "toggleList('" + list + "', '" + subContainerId + "', '"+ id1 + "', '"+ id2 + "', '"+ id3 + "')"
656                                          );
657               }
658            }
659            return content;
660         }
661
662         // generate level 4 list
663        function displayLevel4(list, id1, id2, id3) {
664            var content = "";
665            var bug = "";
666            var bugP = 0;
667            var containerId = "";
668            var subContainerId = "";
669            var bugId = "";
670            var label = "";
671            var p = [0,0,0,0,0];
672            for (var x=0; x<bugs.length -1; x++) {
673               bug = bugs[x];
674               if (list=="lbc") {
675                  if ( bug[1]!=id1 || bug[2]!=id2 || bug[3]!=id3 ) continue;
676                  if ( selectedVersion!=-1
677                     && selectedVersion!=bug[5]) continue;
678                  if ( selectedPriority!=4
679                     && selectedPriority<bug[4]) continue;
680
681                  subContainerId = "cat-" + id1 + "-code-" + id2 + "-pattern-" + id3 + "-bug-" + bug[0];
682               }
683               if (list=="lbp") {
684                  if ( bug[7]!=id1 || bug[6]!=id2 || bug[3]!=id3 ) continue;
685                  if ( selectedVersion!=-1
686                     && selectedVersion!=bug[5]) continue;
687                  if ( selectedPriority!=4
688                     && selectedPriority<bug[4]) continue;
689
690                  subContainerId = "package-" + id1 + "-class-" + id2 + "-pattern-" + id3 + "-bug-" + bug[0];
691               }
692
693               bugId = "b-uid-" + bug[0];
694               label = bug[idxBugDescr];
695               containerId = "bugs-"+bugId;
696               bugP = bug[4];
697               p[bugP]++;
698               var total = p[1]+p[2]+p[3]+p[4];
699               if (total > 0) {
700                  content += addBug(   4, containerId, label, bugP, bug[5], subContainerId,
701                                       "showbug('" + bugId + "', '" + subContainerId + "', '"+id3+"')");
702               }
703            }
704            return content;
705         }
706
707
708         function addListItem(level, id, label, total, p, subId, onclick) {
709            var content = "";
710
711            content += "<div class='bugList-level"+level+"' >";
712            content += "<div class='bugList-level"+level+"-label' id='"+id+"' >";
713            content += "<a href='' onclick=\"" + onclick + ";return false;\" ";
714            content += ">";
715            content += "<strong>"+label+"</strong>";
716            content += " "+total+" bugs";
717            if (selectedPriority>1)
718               content += " <em>("+p[1];
719            if (selectedPriority>=2)
720               content += "/"+p[2];
721            if (selectedPriority>=3)
722               content += "/"+p[3];
723            if (selectedPriority>=4)
724               content += "/"+p[4];
725            if (selectedPriority>1)
726               content += ")</em>";
727            content += "</a>";
728            content += "</div>";
729            content += "<div class='bugList-level"+level+"-inner' id='"+subId+"' style='display:none;'>Loading...</div>";
730            content += "</div>";
731            return content;
732         }
733
734         function addBug( level, id, label, p, version, subId, onclick) {
735            var content = "";
736
737            content += "<div class='bugList-level" + level + "' id='" + id + "'>";
738            content += "<div class='bugList-level" + level + "-label' id='" + id + "'>";
739            content += "<span class='b-" + p + "'>&nbsp;&nbsp;&nbsp;</span>";
740            content += "<a href='' onclick=\"" + onclick + ";return false;\">";
741            if (version==lastVersion) {
742               content += "<span style='color:red;font-weight:bold;'>NEW!</span> ";
743            }
744            content += "<strong>" + label + "</strong>";
745            if (version==0) {
746               content += " <em>since release first historized release</em>";
747            } else {
748               content += " <em>since release " + versions[version][1] + "</em>";
749            }
750            content += "</a>";
751            content += "</div>";
752            content += "<div class='bugList-level" + level + "-inner' id='" + subId + "' style='display:none;'>Loading...</div>";
753            content += "</div>";
754            return content;
755         }
756
757         function countBugsVersion(version, priority) {
758            return countBugs(version, priority, "", -1, "", -1, "", -1, "", -1, "", -1);
759         }
760
761         function countBugsCat(version, priority, cat, idxCat) {
762            return countBugs(version, priority, cat, idxCat, "", -1, "", -1, "", -1, "", -1);
763         }
764
765         function countBugsPackage(version, priority, packageId, idxPackage) {
766            return countBugs(version, priority, "", -1, "", -1, "", -1, packageId, idxPackage, "", -1);
767         }
768
769         function countBugsCode(version, priority, cat, idxCat, code, idxCode) {
770            return countBugs(version, priority, cat, idxCat, code, idxCode, "", -1, "", -1, "", -1);
771         }
772
773         function countBugsPattern(version, priority, cat, idxCat, code, idxCode, packageId, idxPattern) {
774            return countBugs(version, priority, cat, idxCat, code, idxCode, packageId, idxPattern, "", -1, "", -1);
775         }
776
777         function countBugsClass(version, priority, id1, idxBugPackage, id2, idxBugClass) {
778            return countBugs(version, priority, "", -1, "", -1, "", -1, id1, idxBugPackage, id2, idxBugClass);
779         }
780
781         function countBugsClassPattern(version, priority, id2, idxBugClass, id3, idxBugPattern) {
782            return countBugs(version, priority, "", -1, "", -1, id3, idxBugPattern, "", -1, id2, idxBugClass);
783         }
784
785         function countBugs(version, priority, cat, idxCat, code, idxCode, pattern, idxPattern, packageId, idxPackage, classId, idxClass) {
786            var count = [0,0,0,0,0];
787            var last=1000000;
788            for (var x=0; x<bugs.length-1; x++) {
789               var bug = bugs[x];
790
791               var bugCat = bug[idxCat];
792               var bugP = bug[4];
793               var bugCode = bug[idxCode];
794               var bugPattern = bug[idxPattern];
795
796               if (     (version==-1    || version==bug[5])
797                     && (priority==4    || priority>=bug[4])
798                     && (idxCat==-1     || bug[idxCat]==cat)
799                     && (idxCode==-1    || bug[idxCode]==code)
800                     && (idxPattern==-1 || bug[idxPattern]==pattern)
801                     && (idxPackage==-1 || bug[idxPackage]==packageId)
802                     && (idxClass==-1   || bug[idxClass]==classId)
803                     ) {
804                  count[bug[4]]++;
805               }
806            }
807            count[0] = count[1] + count[2] + count[3] + count[4];
808            return count;
809         }
810
811         function countFixedBugsInVersion(version) {
812            var count = [0,0,0,0,0];
813            var last=1000000;
814            for (var x=0; x<fixedBugs.length-1; x++) {
815               var bug = fixedBugs[x];
816
817               var bugP = bug[4];
818
819               if ( version==-1 || version==(bug[6]+1)) {
820                  count[bug[4]]++;
821               }
822            }
823            count[0] = count[1] + count[2] + count[3] + count[4];
824            return count;
825         }
826
827         function countFixedBugsIntroducedInVersion(version) {
828            var count = [0,0,0,0,0];
829            var last=1000000;
830            for (var x=0; x<fixedBugs.length-1; x++) {
831               var bug = fixedBugs[x];
832
833               var bugP = bug[4];
834
835               if ( version==-1 || version==(bug[5])) {
836                  count[bug[4]]++;
837               }
838            }
839            count[0] = count[1] + count[2] + count[3] + count[4];
840            return count;
841         }
842
843         function countFixedButActiveBugsVersion(version) {
844            var count = [0,0,0,0,0];
845            var last=1000000;
846            for (var x=0; x<fixedBugs.length-1; x++) {
847               var bug = fixedBugs[x];
848
849               var bugP = bug[4];
850
851               if ( version==-1 || (version >=bug[5] && version<=bug[6]) ) {
852                  count[bug[4]]++;
853               }
854            }
855            count[0] = count[1] + count[2] + count[3] + count[4];
856            return count;
857         }
858
859         function countTotalBugsVersion(version) {
860            var count = [0,0,0,0,0];
861            var last=1000000;
862            for (var x=0; x<bugs.length-1; x++) {
863               var bug = bugs[x];
864
865               var bugP = bug[4];
866
867               if (version==-1 || version>=bug[5]) {
868                  count[bug[4]]++;
869               }
870            }
871            count[0] = count[1] + count[2] + count[3] + count[4];
872            return count;
873         }
874
875         function getPriorityLegend() {
876            var content = "";
877            content += "<h5><span class='b-1'>&nbsp;&nbsp;&nbsp;</span> P1 ";
878            content += "<span class='b-2'>&nbsp;&nbsp;&nbsp;</span> P2 ";
879            content += "<span class='b-3'>&nbsp;&nbsp;&nbsp;</span> P3 ";
880            content += "<span class='b-4'>&nbsp;&nbsp;&nbsp;</span> Exp ";
881            content += "</h5>";
882            return content;
883         }
884
885         function populatePackageNames() {
886            for (var i=0; i<bugs.length; i++) {
887               var classId = bugs[i][6];
888               var idx = classId.lastIndexOf('.');
889               var packageId = "";
890
891               if (idx>0) {
892                  packageId = classId.substring(0, idx);
893               }
894
895               bugs[i][7] = packageId;
896            }
897         }
898
899         function showbug(bugId, containerId, patternId) {
900            var bugplaceholder   = document.getElementById(containerId);
901            var bug              = document.getElementById(bugId);
902
903            if ( bugplaceholder==null) {
904               alert(buguid+'-ph-'+list+' - '+buguid+' - bugplaceholder==null');
905               return;
906            }
907            if ( bug==null) {
908               alert(buguid+'-ph-'+list+' - '+buguid+' - bug==null');
909               return;
910            }
911
912            var newBug = bug.innerHTML;
913            var pattern = document.getElementById('tip-'+patternId).innerHTML;
914            toggle(containerId);
915            bugplaceholder.innerHTML = newBug + pattern;
916         }
917         function toggle(foo) {
918            if( document.getElementById(foo).style.display == "none") {
919               show(foo);
920            } else {
921               if( document.getElementById(foo).style.display == "block") {
922                  hide(foo);
923               } else {
924                  show(foo);
925               }
926            }
927         }
928         function show(foo) {
929            document.getElementById(foo).style.display="block";
930         }
931         function hide(foo) {
932            document.getElementById(foo).style.display="none";
933         }
934
935         window.onload = function(){
936            init();
937         };
938      ]]></xsl:text></script>
939      <script type='text/javascript'>
940         // versions fields: release id, release label
941         var versions = new Array(
942            <xsl:for-each select="/BugCollection/History/AppVersion">
943               [ "<xsl:value-of select="@sequence" />", "<xsl:value-of select="@release" />" ],
944            </xsl:for-each>
945               [ "<xsl:value-of select="/BugCollection/@sequence" />", "<xsl:value-of select="/BugCollection/@release" />" ]
946            );
947
948         // categories fields: category id, category label
949         var categories = new Array(
950            <xsl:for-each select="/BugCollection/BugCategory">
951               <xsl:sort select="@category" order="ascending" />
952               [ "<xsl:value-of select="@category" />", "<xsl:value-of select="Description" />" ],
953            </xsl:for-each>
954               [ "", "" ]
955            );
956
957         // codes fields: code id, code label
958         var codes = new Array(
959            <xsl:for-each select="/BugCollection/BugCode">
960               <xsl:sort select="@abbrev" order="ascending" />
961               [ "<xsl:value-of select="@abbrev" />", "<xsl:value-of select="Description" />" ],
962            </xsl:for-each>
963               [ "", "" ]
964            );
965
966         // patterns fields: category id, code id, pattern id, pattern label
967         var patterns = new Array(
968            <xsl:for-each select="/BugCollection/BugPattern">
969               <xsl:sort select="@type" order="ascending" />
970               [ "<xsl:value-of select="@category" />", "<xsl:value-of select="@abbrev" />", "<xsl:value-of select="@type" />", "<xsl:value-of select="translate(ShortDescription, '&quot;', $apos)" />" ],
971
972            </xsl:for-each>
973               [ "", "", "", "" ]
974            );
975
976         // class stats fields: class name, package name, isInterface, total bugs, bugs p1, bugs p2, bugs p3, bugs p4
977         var classStats = new Array(
978            <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats/ClassStats">
979               <xsl:sort select="@class" order="ascending" />
980               [ "<xsl:value-of select="@class" />", "<xsl:value-of select="../@package" />", "<xsl:value-of select="@interface" />", "<xsl:value-of select="@bugs" />", "<xsl:value-of select="@priority_1" />", "<xsl:value-of select="@priority_2" />", "<xsl:value-of select="@priority_3" />", "<xsl:value-of select="@priority_4" />" ],
981            </xsl:for-each>
982               [ "", "", "", "", "", "", "", "" ]
983            );
984
985         // package stats fields: package name, total bugs, bugs p1, bugs p2, bugs p3, bugs p4
986         var packageStats = new Array(
987            <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats">
988               <xsl:sort select="@package" order="ascending" />
989               [ "<xsl:value-of select="@package" />", "<xsl:value-of select="@total_bugs" />", "<xsl:value-of select="@priority_1" />", "<xsl:value-of select="@priority_2" />", "<xsl:value-of select="@priority_3" />", "<xsl:value-of select="@priority_4" />" ],
990            </xsl:for-each>
991               [ "", "", "", "", "", "" ]
992            );
993
994
995         // bugs fields: bug id, category id, code id, pattern id, priority, release id, class name, packagename (populated by javascript)
996         var bugs = new Array(
997            <xsl:for-each select="/BugCollection/BugInstance[string-length(@last)=0]">
998
999               [ "<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" />",
1000                 "<xsl:value-of select="@category" />",
1001                 "<xsl:value-of select="@abbrev" />",
1002                 "<xsl:value-of select="@type" />",
1003                 <xsl:value-of select="@priority" />,
1004                 <xsl:choose><xsl:when test='string-length(@first)=0'>0</xsl:when><xsl:otherwise><xsl:value-of select="@first" /></xsl:otherwise></xsl:choose>,
1005                 "<xsl:value-of select="Class/@classname" />",
1006                 ""],
1007            </xsl:for-each>
1008               [ "", "", "", "", 0, 0, "", "" ]
1009            );
1010
1011         // bugs fields: bug id, category id, code id, pattern id, priority, first release id, fixed release id, class name
1012         var fixedBugs = new Array(
1013            <xsl:for-each select="/BugCollection/BugInstance[string-length(@last)>0]">
1014
1015               [ "<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" />",
1016                 "<xsl:value-of select="@category" />",
1017                 "<xsl:value-of select="@abbrev" />",
1018                 "<xsl:value-of select="@type" />",
1019                 <xsl:value-of select="@priority" />,
1020                 <xsl:choose><xsl:when test='string-length(@first)=0'>0</xsl:when><xsl:otherwise><xsl:value-of select="@first" /></xsl:otherwise></xsl:choose>,
1021                 <xsl:choose><xsl:when test='string-length(@last)>0'><xsl:value-of select="@last" /></xsl:when><xsl:otherwise>-42</xsl:otherwise></xsl:choose>,
1022                 "<xsl:value-of select="Class/@classname" />" ],
1023            </xsl:for-each>
1024               [ "", "", "", "", 0, 0, 0, "" ]
1025            );
1026
1027      </script>
1028   </head>
1029   <body>
1030      <h3>
1031         <a href="http://findbugs.sourceforge.net">FindBugs</a> (<xsl:value-of select="/BugCollection/@version" />) 
1032         Analysis for 
1033         <xsl:choose>
1034            <xsl:when test='string-length(/BugCollection/Project/@projectName)>0'><xsl:value-of select="/BugCollection/Project/@projectName" /></xsl:when>
1035            <xsl:otherwise><xsl:value-of select="/BugCollection/Project/@filename" /></xsl:otherwise>
1036         </xsl:choose>
1037      </h3>
1038
1039      <div id='menuWrapper' style=''>
1040         <div id="navcontainer">
1041            <ul id="navlist">
1042               <li><a id='summary'           class="current" href="#" onclick="selectMenu('summary'); return false;"         >Summary</a></li>
1043               <li><a id='history'           class="none"    href="#" onclick="selectMenu('history'); return false;"         >History</a></li>
1044               <li><a id='listByCategories'  class="none"    href="#" onclick="selectMenu('listByCategories'); return false;">Browse By Categories</a></li>
1045               <li><a id='listByPackages'    class="none"    href="#" onclick="selectMenu('listByPackages'); return false;"  >Browse by Packages</a></li>
1046               <li><a id='info'              class="none"    href="#" onclick="selectMenu('info'); return false;"            >Info</a></li>
1047            </ul>
1048         </div>
1049      </div>
1050
1051      <div id='displayWrapper'>
1052
1053      <div style='height:25px;'>
1054         <div id='messageContainer' style='float:right;'>
1055            Computing data...
1056         </div>
1057         <div id='filterWrapper' style='display:none;'>
1058            <form name='findbugsForm'>
1059               <div id='filterContainer' >
1060                  <select name='versions' onchange='filter()'>
1061                     <option value="loading">Loading filter...</option>
1062                  </select>
1063                  <select name='priorities' onchange='filter()'>
1064                     <option value="loading">Loading filter...</option>
1065                  </select>
1066               </div>
1067            </form>
1068         </div>
1069         <div id='historyControlWrapper' style='display:none;'>
1070           <form name="findbugsHistoryControlForm">
1071             <div id='historyControlContainer'>
1072               <input type='checkbox' name='includeFixedIntroducedBugs'
1073                      value='checked' alt='Include fixed introduced bugs.'
1074                      onclick='includeFixedIntroducedBugsInHistory()' />
1075               Include counts of introduced bugs that were fixed in later releases.
1076             </div>
1077           </form>
1078         </div>
1079      </div>
1080         <div id='summaryContainer'          class='displayContainer'>
1081            <h3>Package Summary</h3>
1082            <table>
1083               <tr>
1084                  <th>Package</th>
1085                  <th>Code Size</th>
1086                  <th>Bugs</th>
1087                  <th>Bugs p1</th>
1088                  <th>Bugs p2</th>
1089                  <th>Bugs p3</th>
1090                  <th>Bugs Exp.</th>
1091               </tr>
1092               <tr>
1093                  <td class='summary-name'>
1094                     Overall
1095                     (<xsl:value-of select="/BugCollection/FindBugsSummary/@num_packages" /> packages),
1096                     (<xsl:value-of select="/BugCollection/FindBugsSummary/@total_classes" /> classes)
1097                  </td>
1098                  <td class='summary-size'><xsl:value-of select="/BugCollection/FindBugsSummary/@total_size" /></td>
1099                  <td class='summary-priority-all'><xsl:value-of select="/BugCollection/FindBugsSummary/@total_bugs" /></td>
1100                  <td class='summary-priority-1'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_1" /></td>
1101                  <td class='summary-priority-2'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_2" /></td>
1102                  <td class='summary-priority-3'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_3" /></td>
1103                  <td class='summary-priority-4'><xsl:value-of select="/BugCollection/FindBugsSummary/@priority_4" /></td>
1104               </tr>
1105               <xsl:for-each select="/BugCollection/FindBugsSummary/PackageStats">
1106                  <xsl:sort select="@package" order="ascending" />
1107                  <xsl:if test="@total_bugs!='0'" >
1108                     <tr>
1109                        <td class='summary-name'><xsl:value-of select="@package" /></td>
1110                        <td class='summary-size'><xsl:value-of select="@total_size" /></td>
1111                        <td class='summary-priority-all'><xsl:value-of select="@total_bugs" /></td>
1112                        <td class='summary-priority-1'><xsl:value-of select="@priority_1" /></td>
1113                        <td class='summary-priority-2'><xsl:value-of select="@priority_2" /></td>
1114                        <td class='summary-priority-3'><xsl:value-of select="@priority_3" /></td>
1115                        <td class='summary-priority-4'><xsl:value-of select="@priority_4" /></td>
1116                     </tr>
1117                  </xsl:if>
1118               </xsl:for-each>
1119            </table>
1120         </div>
1121
1122         <div id='infoContainer'             class='displayContainer'>
1123            <div id='analyzed-files'>
1124               <h3>Analyzed Files:</h3>
1125               <ul>
1126                  <xsl:for-each select="/BugCollection/Project/Jar">
1127                     <li><xsl:apply-templates /></li>
1128                  </xsl:for-each>
1129               </ul>
1130            </div>
1131            <div id='used-libraries'>
1132               <h3>Used Libraries:</h3>
1133               <ul>
1134                  <xsl:for-each select="/BugCollection/Project/AuxClasspathEntry">
1135                     <li><xsl:apply-templates /></li>
1136                  </xsl:for-each>
1137                  <xsl:if test="count(/BugCollection/Project/AuxClasspathEntry)=0" >
1138                     <li>None</li>
1139                  </xsl:if>
1140               </ul>
1141            </div>
1142            <div id='analysis-error'>
1143               <h3>Analysis Errors:</h3>
1144               <ul>
1145                  <xsl:variable name="error-count"
1146                                select="count(/BugCollection/Errors/MissingClass)" />
1147                  <xsl:if test="$error-count=0" >
1148                     <li>None</li>
1149                  </xsl:if>
1150                  <xsl:if test="$error-count>0" >
1151                     <li>Missing ref classes for analysis:
1152                        <ul>
1153                           <xsl:for-each select="/BugCollection/Errors/MissingClass">
1154                              <li><xsl:apply-templates /></li>
1155                           </xsl:for-each>
1156                        </ul>
1157                     </li>
1158                  </xsl:if>
1159               </ul>
1160            </div>
1161         </div>
1162         <div id='historyContainer'          class='displayContainer'>Loading...</div>
1163         <div id='listByCategoriesContainer' class='displayContainer'>Loading...</div>
1164         <div id='listByPackagesContainer'   class='displayContainer'>Loading...</div>
1165      </div>
1166
1167      <div id='bug-collection' style='display:none;'>
1168      <!-- advanced tooltips -->
1169      <xsl:for-each select="/BugCollection/BugPattern">
1170         <xsl:variable name="b-t"><xsl:value-of select="@type" /></xsl:variable>
1171         <div>
1172            <xsl:attribute name="id">tip-<xsl:value-of select="$b-t" /></xsl:attribute>
1173            <xsl:attribute name="class">tip</xsl:attribute>
1174            <xsl:value-of select="/BugCollection/BugPattern[@type=$b-t]/Details" disable-output-escaping="yes" />
1175         </div>
1176      </xsl:for-each>
1177
1178      <!-- bug descriptions - hidden -->
1179      <xsl:for-each select="/BugCollection/BugInstance[not(@last)]">
1180            <div style="display:none;" class='bug'>
1181               <xsl:attribute name="id">b-uid-<xsl:value-of select="@instanceHash" />-<xsl:value-of select="@instanceOccurrenceNum" /></xsl:attribute>
1182               <xsl:for-each select="*/Message">
1183                  <div class="b-r"><xsl:apply-templates /></div>
1184               </xsl:for-each>
1185               <div class="b-d">
1186                  <xsl:value-of select="LongMessage" disable-output-escaping="no" />
1187               </div>
1188            </div>
1189      </xsl:for-each>
1190      </div>
1191   </body>
1192</html>
1193</xsl:template>
1194
1195
1196</xsl:transform>
1197
1198