tags:

views:

226

answers:

1

I'm a beginner with XSL. I would like to take the StyleCop report and display the file names and their violation count in a descendant order (in XSL 1).

The StyleCop report looks like:

<StyleCopViolations>
  <Violation Section="A" LineNumber="5" Source="A1  RuleNamespace="Microsoft.StyleCop.CSharp.DocumentationRules" Rule="ElementsMustBeDocumented" RuleId="SA1600">The class must have a documentation header.</Violation>
  <Violation Section="B" LineNumber="8" Source="B1" RuleNamspace="Microsoft.StyleCop.CSharp.DocumentationRules" Rule="ElementsMustBeDocumented" RuleId="SA1600">The method must have a documentation header.</Violation>
  <Violation Section="C" LineNumber="20" Source="C1" RuleNamespace="Microsoft.StyleCop.CSharp.DocumentationRules" Rule="ElementsMustBeDocumented" RuleId="SA1600">The method must have a documentation header.</Violation>
  <Violation Section="D" LineNumber="25" Source="D1" RuleNamespace="Microsoft.StyleCop.CSharp.DocumentationRules" Rule="ElementsMustBeDocumented" RuleId="SA1600">The method must have a documentation header.</Violation>
</StyleCopViolations>

The first part of my XSL simply consists in finding what are the different sources which violate any StyleCop rule. Thus, I group the 'Violation' elements according to their 'Source' property. For that, I use the Muenchian method.

<xsl:key name="sameFile" match="//StyleCopViolations/Violation" use="@Source"/>
    <xsl:template match="/">

    <xsl:variable name="report.root" select="//StyleCopViolations" />
    <xsl:variable name="report.rootTransformed" select="msxsl:node-set($report.root)" />

...
<xsl:variable name="files">
   <xsl:apply-templates select="$report.root/Violation[count(. | key('sameFile', @Source)[1]) = 1]" mode="compute">
       <xsl:with-param name="violations" select="$report.rootTransformed"/>
   </xsl:apply-templates>
</xsl:variable>

The template used to compute the violation count is also quite simple: I copy the source attribute and compute the asked value.

<xsl:template match="Violation" mode="compute">   
    <xsl:param name="violations"/>    
    <xsl:variable name="Source" select="@Source" />   
    <xsl:copy>   
       <xsl:copy-of select="@Source" />   
       <xsl:element name="NbErrors">
         <xsl:value-of select="count($violations/Violation[@Source=$Source])"/>
 </xsl:element>
    </xsl:copy>  
</xsl:template>

This part works fine.

Then, in order to display the result in a descending order, I use a standard sort tag:

<xsl:apply-templates select="msxsl:node-set($files)" mode="display">
  <xsl:sort select="NbErrors" data-type="number" order="descending"/>  
</xsl:apply-templates>

The 'display' template is:

<xsl:template match="Violation" mode="display">
  <tr>
   <td>
     <xsl:value-of select="@Source"/>
   </td>
   <td>
     <xsl:value-of select="NbErrors"/>
   </td>    
 </tr>
 </xsl:template>

However, the files are not sorted. What could the problem be?

A: 

I found the solution : using a for-each instead of a apply-template for displaying the elements :)

excepeiont32