main
  1<?xml version="1.0" encoding="utf-8"?>
  2<xsl:stylesheet version="1.0"
  3                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  5                xmlns:g="http://www.gallio.org/"
  6                xmlns="http://www.w3.org/1999/xhtml">
  7  <!-- Common utility functions -->
  8  
  9  <!-- Formats a statistics line like 5 run, 3 passed, 2 failed (1 error), 0 inconclusive, 2 skipped -->
 10  <xsl:template name="format-statistics">
 11    <xsl:param name="statistics" />
 12       
 13		<xsl:value-of select="$statistics/@runCount"/>    
 14    <xsl:text> run, </xsl:text>
 15    
 16    <xsl:value-of select="$statistics/@passedCount"/>
 17    <xsl:text> passed</xsl:text>
 18    <xsl:call-template name="format-statistics-category-counts">
 19      <xsl:with-param name="statistics" select="$statistics" />
 20      <xsl:with-param name="status">passed</xsl:with-param>
 21    </xsl:call-template>
 22    <xsl:text>, </xsl:text>
 23    
 24    <xsl:value-of select="$statistics/@failedCount"/>
 25    <xsl:text> failed</xsl:text>
 26    <xsl:call-template name="format-statistics-category-counts">
 27      <xsl:with-param name="statistics" select="$statistics" />
 28      <xsl:with-param name="status">failed</xsl:with-param>
 29    </xsl:call-template>
 30    <xsl:text>, </xsl:text>
 31
 32    <xsl:value-of select="$statistics/@inconclusiveCount"/>
 33    <xsl:text> inconclusive</xsl:text>
 34    <xsl:call-template name="format-statistics-category-counts">
 35      <xsl:with-param name="statistics" select="$statistics" />
 36      <xsl:with-param name="status">inconclusive</xsl:with-param>
 37    </xsl:call-template>
 38    <xsl:text>, </xsl:text>
 39    
 40    <xsl:value-of select="$statistics/@skippedCount"/>
 41    <xsl:text> skipped</xsl:text>
 42    <xsl:call-template name="format-statistics-category-counts">
 43      <xsl:with-param name="statistics" select="$statistics" />
 44      <xsl:with-param name="status">skipped</xsl:with-param>
 45    </xsl:call-template>
 46  </xsl:template>
 47  
 48  <xsl:template name="format-statistics-category-counts">
 49    <xsl:param name="statistics" />
 50    <xsl:param name="status" />
 51    
 52    <xsl:variable name="outcomeSummaries" select="$statistics/g:outcomeSummaries/g:outcomeSummary[g:outcome/@status=$status and g:outcome/@category]" />
 53    
 54    <xsl:if test="$outcomeSummaries">
 55      <xsl:text> (</xsl:text>
 56        <xsl:for-each select="$outcomeSummaries">
 57          <xsl:sort data-type="text" order="ascending" select="g:outcome/@category"/>
 58          
 59          <xsl:if test="position() != 1"><xsl:text>, </xsl:text></xsl:if>
 60          <xsl:value-of select="@count"/>
 61          <xsl:text> </xsl:text>
 62          <xsl:value-of select="g:outcome/@category"/>
 63        </xsl:for-each>
 64      <xsl:text>)</xsl:text>
 65    </xsl:if>
 66  </xsl:template>
 67  
 68  <!-- Formats a CodeLocation -->
 69  <xsl:template name="format-code-location">
 70    <xsl:param name="codeLocation" />
 71    
 72    <xsl:choose>
 73      <xsl:when test="$codeLocation/@path">
 74        <xsl:value-of select="$codeLocation/@path"/>
 75        <xsl:if test="$codeLocation/@line">
 76          <xsl:text>(</xsl:text>
 77          <xsl:value-of select="$codeLocation/@line"/>
 78          <xsl:if test="$codeLocation/@column">
 79            <xsl:text>,</xsl:text>
 80            <xsl:value-of select="$codeLocation/@column"/>
 81          </xsl:if>
 82          <xsl:text>)</xsl:text>
 83        </xsl:if>
 84      </xsl:when>
 85      <xsl:otherwise>
 86        <xsl:text>(unknown)</xsl:text>
 87      </xsl:otherwise>
 88    </xsl:choose>
 89  </xsl:template>
 90
 91  <!-- Formats a CodeReference -->
 92  <xsl:template name="format-code-reference">
 93    <xsl:param name="codeReference" />
 94    
 95    <xsl:if test="$codeReference/@parameter">
 96      <xsl:text>Parameter </xsl:text>
 97      <xsl:value-of select="$codeReference/@parameter"/>
 98      <xsl:text> of </xsl:text>
 99    </xsl:if>
100    
101    <xsl:choose>
102      <xsl:when test="$codeReference/@type">
103        <xsl:value-of select="$codeReference/@type"/>
104        <xsl:if test="$codeReference/@member">
105          <xsl:text>.</xsl:text>
106          <xsl:value-of select="$codeReference/@member"/>
107        </xsl:if>
108      </xsl:when>
109      <xsl:when test="$codeReference/@namespace">
110        <xsl:value-of select="$codeReference/@namespace"/>
111      </xsl:when>
112    </xsl:choose>
113    
114    <xsl:if test="$codeReference/@assembly">
115      <xsl:if test="$codeReference/@namespace">
116        <xsl:text>, </xsl:text>
117      </xsl:if>
118      <xsl:value-of select="$codeReference/@assembly"/>
119    </xsl:if>
120  </xsl:template>
121  
122  <!-- Creates an aggregate statistics summary from a test instance run and its descendants -->
123  <xsl:template name="aggregate-statistics">
124    <xsl:param name="testStepRun" />
125    
126    <xsl:variable name="testCaseResults" select="$testStepRun/descendant-or-self::g:testStepRun[g:testStep/@isTestCase='true']/g:result" />
127    <xsl:variable name="testCaseOutcomes" select="$testCaseResults/g:outcome" />
128    
129    <xsl:variable name="skippedOutcomes" select="$testCaseOutcomes[@status = 'skipped']" />
130    <xsl:variable name="passedOutcomes" select="$testCaseOutcomes[@status = 'passed']" />
131    <xsl:variable name="inconclusiveOutcomes" select="$testCaseOutcomes[@status = 'inconclusive']" />
132    <xsl:variable name="failedOutcomes" select="$testCaseOutcomes[@status = 'failed']" />
133    
134    <xsl:variable name="skippedCount" select="count($skippedOutcomes)"/>
135    <xsl:variable name="passedCount" select="count($passedOutcomes)"/>
136    <xsl:variable name="inconclusiveCount" select="count($inconclusiveOutcomes)"/>
137    <xsl:variable name="failedCount" select="count($failedOutcomes)"/>
138
139    <g:statistics>
140      <xsl:attribute name="duration"><xsl:value-of select="$testStepRun/g:result/@duration"/></xsl:attribute>
141      <xsl:attribute name="assertCount"><xsl:value-of select="sum($testCaseResults/@assertCount)"/></xsl:attribute>
142      
143      <xsl:attribute name="skippedCount"><xsl:value-of select="$skippedCount"/></xsl:attribute>
144      <xsl:attribute name="passedCount"><xsl:value-of select="$passedCount"/></xsl:attribute>
145      <xsl:attribute name="inconclusiveCount"><xsl:value-of select="$inconclusiveCount"/></xsl:attribute>
146      <xsl:attribute name="failedCount"><xsl:value-of select="$failedCount"/></xsl:attribute>
147      
148      <xsl:attribute name="runCount"><xsl:value-of select="$passedCount + $inconclusiveCount + $failedCount"/></xsl:attribute>
149      
150      <g:outcomeSummaries>
151        <xsl:call-template name="aggregate-statistics-outcome-summaries">
152          <xsl:with-param name="status">skipped</xsl:with-param>
153          <xsl:with-param name="outcomes" select="$skippedOutcomes" />
154        </xsl:call-template>
155        <xsl:call-template name="aggregate-statistics-outcome-summaries">
156          <xsl:with-param name="status">passed</xsl:with-param>
157          <xsl:with-param name="outcomes" select="$passedOutcomes" />
158        </xsl:call-template>
159        <xsl:call-template name="aggregate-statistics-outcome-summaries">
160          <xsl:with-param name="status">inconclusive</xsl:with-param>
161          <xsl:with-param name="outcomes" select="$inconclusiveOutcomes" />
162        </xsl:call-template>
163        <xsl:call-template name="aggregate-statistics-outcome-summaries">
164          <xsl:with-param name="status">failed</xsl:with-param>
165          <xsl:with-param name="outcomes" select="$failedOutcomes" />
166        </xsl:call-template>
167      </g:outcomeSummaries>
168    </g:statistics>
169  </xsl:template>
170  
171  <xsl:key name="outcome-category" match="g:outcome" use="@category" />
172  <xsl:template name="aggregate-statistics-outcome-summaries">
173    <xsl:param name="status" />
174    <xsl:param name="outcomes" />
175    
176    <xsl:for-each select="$outcomes[generate-id() = generate-id(key('outcome-category', @category)[1])]">
177      <xsl:variable name="category" select="@category" />
178      <g:outcomeSummary count="{count($outcomes[@category = $category])}">
179        <g:outcome status="{$status}" category="{$category}" />
180      </g:outcomeSummary>
181    </xsl:for-each>
182  </xsl:template>
183  
184  <!-- Indents text using the specified prefix -->
185  <xsl:template name="indent">
186    <xsl:param name="text" />
187    <xsl:param name="firstLinePrefix" select="'  '" />
188    <xsl:param name="otherLinePrefix" select="'  '" />
189
190    <xsl:if test="$text!=''">
191      <xsl:call-template name="indent-recursive">
192        <xsl:with-param name="text" select="translate($text, '&#9;&#xA;&#xD;', ' &#xA;')" />
193        <xsl:with-param name="firstLinePrefix" select="$firstLinePrefix" />
194        <xsl:with-param name="otherLinePrefix" select="$otherLinePrefix" />
195      </xsl:call-template>
196    </xsl:if>
197  </xsl:template>
198
199  <xsl:template name="indent-recursive">
200    <xsl:param name="text" />
201    <xsl:param name="firstLinePrefix" />
202    <xsl:param name="otherLinePrefix" />
203
204    <xsl:variable name="line" select="substring-before($text, '&#xA;')" />
205    <xsl:choose>
206      <xsl:when test="$line!=''">
207        <xsl:value-of select="$firstLinePrefix"/>
208        <xsl:value-of select="$line"/>
209        <xsl:text>&#xA;</xsl:text>
210        <xsl:call-template name="indent-recursive">
211          <xsl:with-param name="text" select="substring-after($text, '&#xA;')" />
212          <xsl:with-param name="firstLinePrefix" select="$otherLinePrefix" />
213        <xsl:with-param name="otherLinePrefix" select="$otherLinePrefix" />
214        </xsl:call-template>
215      </xsl:when>
216      <xsl:otherwise>
217        <xsl:value-of select="$firstLinePrefix"/>
218        <xsl:value-of select="$text"/>
219        <xsl:text>&#xA;</xsl:text>
220      </xsl:otherwise>
221    </xsl:choose>
222  </xsl:template>
223
224  <!-- Prints text with <br/> at line breaks.
225       Also introduces <wbr/> word break characters every so often if no natural breakpoints appear.
226       Some of the soft breaks are useful, but the forced break at 20 chars is intended to work around
227       limitations in browsers that do not support the word-wrap:break-all CSS3 property.
228  -->
229  <xsl:template name="print-text-with-breaks">
230    <xsl:param name="text" />
231    <xsl:param name="count" select="0" />
232    
233    <xsl:if test="$text">
234      <xsl:variable name="char" select="substring($text, 1, 1)"/>
235      
236      <xsl:choose>
237        <!-- natural word breaks -->
238        <xsl:when test="$char = ' '">
239          <xsl:value-of select="$char"/>
240          <xsl:call-template name="print-text-with-breaks">
241            <xsl:with-param name="text" select="substring($text, 2)" />
242            <xsl:with-param name="count" select="0" />
243          </xsl:call-template>
244        </xsl:when>
245
246        <!-- line breaks -->
247        <xsl:when test="$char = '&#10;'">
248          <br/>
249          <xsl:call-template name="print-text-with-breaks">
250            <xsl:with-param name="text" select="substring($text, 2)" />
251            <xsl:with-param name="count" select="0" />
252          </xsl:call-template>
253        </xsl:when>
254        
255        <!-- characters to break before -->
256        <xsl:when test="$char = '.' or $char = '/' or $char = '\' or $char = ':' or $char = '(' or $char = '&lt;' or $char = '[' or $char = '{' or $char = '_'">
257          <wbr/>
258          <xsl:value-of select="$char"/>
259          <xsl:call-template name="print-text-with-breaks">
260            <xsl:with-param name="text" select="substring($text, 2)" />
261            <xsl:with-param name="count" select="1" />
262          </xsl:call-template>
263        </xsl:when>
264        
265        <!-- characters to break after -->
266        <xsl:when test="$char = ')' or $char = '>' or $char = ']' or $char = '}'">
267          <xsl:value-of select="$char"/>
268          <wbr/>
269          <xsl:call-template name="print-text-with-breaks">
270            <xsl:with-param name="text" select="substring($text, 2)" />
271            <xsl:with-param name="count" select="0" />
272          </xsl:call-template>
273        </xsl:when>
274        
275        <!-- other characters -->
276        <xsl:when test="$count = 19">
277          <xsl:value-of select="$char"/>
278          <wbr/>
279          <xsl:call-template name="print-text-with-breaks">
280            <xsl:with-param name="text" select="substring($text, 2)" />
281            <xsl:with-param name="count" select="0" />
282          </xsl:call-template>
283        </xsl:when>
284        
285        <xsl:otherwise>
286          <xsl:value-of select="$char"/>
287          <xsl:call-template name="print-text-with-breaks">
288            <xsl:with-param name="text" select="substring($text, 2)" />
289            <xsl:with-param name="count" select="$count + 1" />
290          </xsl:call-template>
291        </xsl:otherwise>
292      </xsl:choose>
293    </xsl:if>
294  </xsl:template>
295  
296  <!-- Pretty print date time values -->
297  <xsl:template name="format-datetime">
298    <xsl:param name="datetime" />
299    <xsl:value-of select="substring($datetime, 12, 8)" />, <xsl:value-of select="substring($datetime, 1, 10)" />
300  </xsl:template>
301  
302  <!-- Namespace stripping adapted from http://www.xml.com/pub/a/2004/05/05/tr.html -->
303  <xsl:template name="strip-namespace">
304    <xsl:param name="nodes" />
305    <xsl:apply-templates select="msxsl:node-set($nodes)" mode="strip-namespace" />
306  </xsl:template>
307  
308  <xsl:template match="*" mode="strip-namespace">
309    <xsl:element name="{local-name()}" namespace="">
310      <xsl:apply-templates select="@*|node()" mode="strip-namespace"/>
311    </xsl:element>
312  </xsl:template>
313
314  <xsl:template match="@*" mode="strip-namespace">
315    <xsl:attribute name="{local-name()}" namespace="">
316      <xsl:value-of select="."/>
317    </xsl:attribute>
318  </xsl:template>
319
320  <xsl:template match="processing-instruction()|comment()" mode="strip-namespace">
321    <xsl:copy>
322      <xsl:apply-templates select="node()" mode="strip-namespace"/>
323    </xsl:copy>
324  </xsl:template>  
325  
326  <!-- Converting paths to URIs -->
327  <xsl:template name="path-to-uri">
328    <xsl:param name="path" />    
329    <xsl:if test="$path != ''">
330      <xsl:choose>
331        <xsl:when test="starts-with($path, '\')">/</xsl:when>
332        <xsl:when test="starts-with($path, ' ')">%20</xsl:when>
333        <xsl:when test="starts-with($path, '%')">%25</xsl:when>
334        <xsl:otherwise><xsl:value-of select="substring($path, 1, 1)"/></xsl:otherwise>
335      </xsl:choose>
336      <xsl:call-template name="path-to-uri">
337        <xsl:with-param name="path" select="substring($path, 2)" />
338      </xsl:call-template>
339    </xsl:if>
340  </xsl:template>
341</xsl:stylesheet>