Search code examples
xmlvisual-studioxsltcode-metrics

XSLT Transform for XML Generated by metric.exe


I'm trying to transform the following XML generated by metric.exe for assemblies in my solution. and i am not an expert in XSLT and struggling to arrive at the format indicated at the bottom of the question. please help.

The XML

<?xml version="1.0" encoding="utf-8"?>
<CodeMetricsReport Version="12.0">
  <Targets>
    <Target Name="E:\some-imaginary-path\some-imaginary-dll">
      <Modules>
        <Module Name="some-imaginary-dll" AssemblyVersion="1.0.0.0" FileVersion="1.0.0.0">
          <Metrics>
            <Metric Name="MaintainabilityIndex" Value="84" />
            <Metric Name="CyclomaticComplexity" Value="95" />
            <Metric Name="ClassCoupling" Value="109" />
            <Metric Name="DepthOfInheritance" Value="4" />
            <Metric Name="LinesOfCode" Value="214" />
          </Metrics>
          <Namespaces>
            <Namespace Name="LMS.SomeNamespace">
              <Metrics>
                <Metric Name="MaintainabilityIndex" Value="89" />
                <Metric Name="CyclomaticComplexity" Value="19" />
                <Metric Name="ClassCoupling" Value="18" />
                <Metric Name="DepthOfInheritance" Value="1" />
                <Metric Name="LinesOfCode" Value="29" />
              </Metrics>
              <Types>
                <Type Name="SomeType1">
                  <Metrics>
                    <Metric Name="MaintainabilityIndex" Value="100" />
                    <Metric Name="CyclomaticComplexity" Value="1" />
                    <Metric Name="ClassCoupling" Value="1" />
                    <Metric Name="DepthOfInheritance" Value="0" />
                    <Metric Name="LinesOfCode" Value="0" />
                  </Metrics>
                  <Members>
                    <Member Name="SomeMemberFor1">
                      <Metrics>
                        <Metric Name="MaintainabilityIndex" Value="100" />
                        <Metric Name="CyclomaticComplexity" Value="1" />
                        <Metric Name="ClassCoupling" Value="1" />
                        <Metric Name="LinesOfCode" Value="0" />
                      </Metrics>
                    </Member>
                  </Members>
                </Type>
                <Type Name="SomeType2">
                  <Metrics>
                    <Metric Name="MaintainabilityIndex" Value="76" />
                    <Metric Name="CyclomaticComplexity" Value="3" />
                    <Metric Name="ClassCoupling" Value="6" />
                    <Metric Name="DepthOfInheritance" Value="1" />
                    <Metric Name="LinesOfCode" Value="7" />
                  </Metrics>
                  <Members>
                    <Member Name="SomeMemberFor2" File="e:\some-file.cs" Line="27">
                      <Metrics>
                        <Metric Name="MaintainabilityIndex" Value="67" />
                        <Metric Name="CyclomaticComplexity" Value="2" />
                        <Metric Name="ClassCoupling" Value="5" />
                        <Metric Name="LinesOfCode" Value="6" />
                      </Metrics>
                    </Member>
              </Namespace>
          </Namespaces>
        </Module>
             </Namespace>
          </Namespaces>
        </Module>
      </Modules>
    </Target>
  </Targets>
</CodeMetricsReport>

The XSLT

so far this produces nothing when transformed using a powershell script (certain variations have worked partially so the powershell script is not at fault here)

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
  exclude-result-prefixes="msxsl"
>
  <xsl:output method="html" indent="yes"/>
   <xsl:template match="/">
  <html>
  <body>
  <h2>x</h2>
  <table border="1">
    <tr bgcolor="#9acd32">
      <th>Name Space Name</th>
      <th>Type Name</th>
      <th>Member Name</th>
      <th>MaintainabilityIndex</th>
      <th>CyclomaticComplexity</th>
      <th>ClassCoupling</th>
      <th>DepthOfInheritance</th>
      <th>LinesOfCode</th>

    </tr>
    <xsl:for-each select="CodeMetricsReport/Targets/Target/Modules/Namespaces/Namespace/Metrics">
    <tr>
      <td><xsl:value-of select="./Metric[@Name = '????']/@Value" /></td>
      <td><xsl:value-of select="./Metric[@Name = '????']/@Value" /></td>
      <td><xsl:value-of select="./Metric[@Name = '????']/@Value" /></td>
      <td><xsl:value-of select="./Metric[@Name = 'MaintainabilityIndex']/@Value" /></td>
      <td><xsl:value-of select="./Metric[@Name = 'CyclomaticComplexity']/@Value"/></td>
      <td><xsl:value-of select="./Metric[@Name = 'ClassCoupling']/@Value"/></td>
      <td><xsl:value-of select="./Metric[@Name = 'DepthOfInheritance']/@Value"/></td>
      <td><xsl:value-of select="./Metric[@Name = 'LinesOfCode']/@Value"/></td>
      </tr>
    </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

the HTML that i am expecting achive

<table border="1">
  <tr bgcolor="#9acd32">
    <th>Name Space Name</th>
    <th>Type Name</th>
    <th>Member Name</th>
    <th>MaintainabilityIndex</th>
    <th>CyclomaticComplexity</th>
    <th>ClassCoupling</th>
    <th>DepthOfInheritance</th>
    <th>LinesOfCode</th>

  </tr>
  <tr>
    <td>Name of namespace</td>
    <td>Type name</td>
    <td>Member name</td>
    <td>1</td>
    <td>2</td>
    <td>3</td>
    <td>4</td>
    <td>5</td>
  </tr>

</table>

Thanks in advance for any help rendered.


Solution

  • Your given input document was not well-formed. I've had to make a guess as to what it is supposed to be. If your input document is ....

    <CodeMetricsReport Version="12.0">
        <Targets>
            <Target Name="E:\some-imaginary-path\some-imaginary-dll">
                <Modules>
                    <Module Name="some-imaginary-dll" AssemblyVersion="1.0.0.0" FileVersion="1.0.0.0">
                        <Metrics>
                            <Metric Name="MaintainabilityIndex" Value="84"/>
                            <Metric Name="CyclomaticComplexity" Value="95"/>
                            <Metric Name="ClassCoupling" Value="109"/>
                            <Metric Name="DepthOfInheritance" Value="4"/>
                            <Metric Name="LinesOfCode" Value="214"/>
                        </Metrics>
                        <Namespaces>
                            <Namespace Name="LMS.SomeNamespace">
                                <Metrics>
                                    <Metric Name="MaintainabilityIndex" Value="89"/>
                                    <Metric Name="CyclomaticComplexity" Value="19"/>
                                    <Metric Name="ClassCoupling" Value="18"/>
                                    <Metric Name="DepthOfInheritance" Value="1"/>
                                    <Metric Name="LinesOfCode" Value="29"/>
                                </Metrics>
                                <Types>
                                    <Type Name="SomeType1">
                                        <Metrics>
                                            <Metric Name="MaintainabilityIndex" Value="100"/>
                                            <Metric Name="CyclomaticComplexity" Value="1"/>
                                            <Metric Name="ClassCoupling" Value="1"/>
                                            <Metric Name="DepthOfInheritance" Value="0"/>
                                            <Metric Name="LinesOfCode" Value="0"/>
                                        </Metrics>
                                        <Members>
                                            <Member Name="SomeMemberFor1">
                                                <Metrics>
                                                    <Metric Name="MaintainabilityIndex" Value="100"/>
                                                    <Metric Name="CyclomaticComplexity" Value="1"/>
                                                    <Metric Name="ClassCoupling" Value="1"/>
                                                    <Metric Name="LinesOfCode" Value="0"/>
                                                </Metrics>
                                            </Member>
                                        </Members>
                                    </Type>
                                    <Type Name="SomeType2">
                                        <Metrics>
                                            <Metric Name="MaintainabilityIndex" Value="76"/>
                                            <Metric Name="CyclomaticComplexity" Value="3"/>
                                            <Metric Name="ClassCoupling" Value="6"/>
                                            <Metric Name="DepthOfInheritance" Value="1"/>
                                            <Metric Name="LinesOfCode" Value="7"/>
                                        </Metrics>
                                        <Members>
                                            <Member Name="SomeMemberFor2" File="e:\some-file.cs" Line="27">
                                                <Metrics>
                                                    <Metric Name="MaintainabilityIndex" Value="67"/>
                                                    <Metric Name="CyclomaticComplexity" Value="2"/>
                                                    <Metric Name="ClassCoupling" Value="5"/>
                                                    <Metric Name="LinesOfCode" Value="6"/>
                                                </Metrics>
                                            </Member>
                                        </Members>
                                    </Type>
                                </Types>
                            </Namespace>
                        </Namespaces>
                    </Module>
                </Modules>
            </Target>
        </Targets>
    </CodeMetricsReport>
    

    ... then this XSLT 1 stylesheet ...

    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0">
    
    <xsl:output method="html" version="5" doctype-system="" encoding="utf-8" />
    <xsl:strip-space elements="*" />  
    
    <xsl:template match="/">
      <html>
        <head>
          <title>metric.exe Output</title>
        </head>
        <body>
          <h1>metric.exe Ouput</h1>
          <table border="1">
            <thead>
              <tr bgcolor="#9acd32">
                <th>Name Space Name</th>
                <th>Type Name</th>
                <th>Member Name</th>
                <th>MaintainabilityIndex</th>
                <th>CyclomaticComplexity</th>
                <th>ClassCoupling</th>
                <th>DepthOfInheritance</th>
                <th>LinesOfCode</th>
              </tr>
            </thead>
            <tbody>
              <xsl:apply-templates select="CodeMetricsReport/Targets/Target/Modules/Module/Namespaces/Namespace/Types/Type/Members/Member" />
            </tbody>
           </table>
        </body>
      </html>
    </xsl:template>
    
    <xsl:template match="Member">
      <tr>
        <td><xsl:value-of select="../../../../@Name" /></td>
        <td><xsl:value-of select="../../@Name" /></td>
        <td><xsl:value-of select="@Name" /></td>
        <td><xsl:value-of select="Metrics/Metric[@Name='MaintainabilityIndex']/@Value" />&#160;</td>
        <td><xsl:value-of select="Metrics/Metric[@Name='CyclomaticComplexity']/@Value" />&#160;</td>
        <td><xsl:value-of select="Metrics/Metric[@Name='ClassCoupling']/@Value" />&#160;</td>
        <td><xsl:value-of select="../../Metrics/Metric[@Name='DepthOfInheritance']/@Value" />&#160;</td>
        <td><xsl:value-of select="Metrics/Metric[@Name='LinesOfCode']/@Value" />&#160;</td>
      </tr>  
    </xsl:template>
    
    </xsl:stylesheet>
    

    ... will transform the input document into this output document ...

    <!DOCTYPE html SYSTEM "">
    <html>
      <head>
        <META http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>metric.exe Output</title>
      </head>
      <body>
        <h1>metric.exe Ouput</h1>
        <table border="1">
          <thead>
            <tr bgcolor="#9acd32">
              <th>Name Space Name</th>
              <th>Type Name</th>
              <th>Member Name</th>
              <th>MaintainabilityIndex</th>
              <th>CyclomaticComplexity</th>
              <th>ClassCoupling</th>
              <th>DepthOfInheritance</th>
              <th>LinesOfCode</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>LMS.SomeNamespace</td>
              <td>SomeType1</td>
              <td>SomeMemberFor1</td>
              <td>100 </td>
              <td>1 </td>
              <td>1 </td>
              <td>0 </td>
              <td>0 </td>
            </tr>
            <tr>
              <td>LMS.SomeNamespace</td>
              <td>SomeType2</td>
              <td>SomeMemberFor2</td>
              <td>67 </td>
              <td>2 </td>
              <td>5 </td>
              <td>1 </td>
              <td>6 </td>
            </tr>
          </tbody>
        </table>
      </body>
    </html>