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?