<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns='http://www.microsoft.com/axe/assessment/manifest' version="1.0">
    <xsl:output method="xml" indent="yes"/> 
    
    <!-- A few Constants / Globals-->
    <xsl:variable name="NUM_ITEMS_DISPLAY" select="50" />
    <xsl:variable name="EtwBSize" select="/TraceData/Memory/Category-Detail/Active/Category[@Name='NonPagedPool']/BigPool[@Tag='EtwB']/@KB" />
    <xsl:variable name="DriverLockedSystemPagesSize" select="/TraceData/Memory/Summary/Active/Category[@Name='DriverLockedSystemPage']/@MB" />
            
    <!-- Begin Selecting and Outputing the data -->
    <xsl:template match="/TraceData">
        <Iteration>
        
            <!-- First write out all of the Overview MetricValues -->
            <MetricValues>
                <xsl:call-template name="WriteMetricValues_PoolAction">
                    <xsl:with-param name="Node" select="PoolAction" />
                </xsl:call-template>

                <xsl:call-template name="WriteMetricValues_Memory">
                    <xsl:with-param name="Node" select="Memory" />
                </xsl:call-template>
            </MetricValues>
            
            <!-- Then write out the TestCases -->
            <TestCases>
                <xsl:call-template name="WriteTestCases_PoolAction">
                    <xsl:with-param name="Node" select="PoolAction" />
                </xsl:call-template>
                
                <xsl:call-template name="WriteTestCases_Memory">
                    <xsl:with-param name="Node" select="Memory" />
                </xsl:call-template>    
            </TestCases>
            
        </Iteration>
    </xsl:template>

    
    <xsl:template name="WriteMetricValues_PoolAction">
        <xsl:param name="Node" />
        
        <xsl:for-each select="$Node">                          <!-- Just Scoping. Not actual iteration -->
            <xsl:variable name="SessionPools" select="PoolImages[@Type='paged pool']/PoolImageInSession[@SessionId != 'NonSession']" />
            
            <xsl:variable name="NonPagedPoolTotal" select="PoolTotals/PoolTotal[normalize-space(@Type)=normalize-space('Non-paged pool    (Total)')]/@OutstandingAllocKB" />
            <xsl:variable name="PagedPoolTotal"      select="PoolTotals/PoolTotal[normalize-space(@Type)=normalize-space('Paged pool        (Total)')]/@OutstandingAllocKB" />

            <!-- Remove the effect of the ETW Buffers when computing the NonPaged Pool -->
            <xsl:call-template name="WriteMetric" >
                <xsl:with-param name="PrgName" select="'OverviewTotals_NonPagedPool'" />
                <xsl:with-param name="Value" select="format-number((($NonPagedPoolTotal - $EtwBSize) div 1024) + $DriverLockedSystemPagesSize , '0.0')" />
            </xsl:call-template>

            <xsl:call-template name="WriteMetric" >
                <xsl:with-param name="PrgName" select="'OverviewTotals_PagedPool'" />
                <xsl:with-param name="Value" select="format-number($PagedPoolTotal div 1024, '0.0')" />
            </xsl:call-template>
            
            <!-- Write out a metric that marks the size of the Etw Buffers -->
            <xsl:call-template name="WriteMetric" >
                <xsl:with-param name="PrgName" select="'OverviewTotals_EtwB'" />
                <xsl:with-param name="Value" select="format-number($EtwBSize div 1024, '0.0')" />
            </xsl:call-template>


        </xsl:for-each>
    </xsl:template>
    
    <xsl:template name="WriteTestCases_PoolAction">
        <xsl:param name="Node" />
        <xsl:for-each select="$Node">


            <!-- Write out the Session Pool detail values -->
            <xsl:variable name="SessionPools" select="PoolImages[@Type='paged pool']/PoolImageInSession[@SessionId != 'NonSession']" />
            
            <xsl:for-each select="$SessionPools" >
                <xsl:sort select="@SessionId" data-type="number" />                               <!-- We are also relying on elements already being sorted by size within the file -->
                <xsl:if test="position() &lt;= $NUM_ITEMS_DISPLAY">
                        <xsl:variable name="SectionName" select="'SessionPool'" />
                        <xsl:variable name="Description" select="concat('Session', @SessionId)" />
                        <xsl:variable name="PrgNameSuffix1" select="'SessionId'" />
                        <xsl:variable name="PrgNameSuffix2" select="'OutstandingAllocKB'" />
                        <xsl:call-template name="WriteTestCase_2Metrics">
                            <xsl:with-param name="Key" select="concat($SectionName, '_Key_', $Description)" />
                            <xsl:with-param name="Name" select="$Description" />
                            <xsl:with-param name="Parent" select="concat($SectionName, '_TestCases' )" />
                            <xsl:with-param name="PrgName1" select="concat($SectionName, '_', $PrgNameSuffix1)" />
                            <xsl:with-param name="Value1" select="$Description" />
                            <xsl:with-param name="PrgName2" select="concat($SectionName, '_', $PrgNameSuffix2)" />
                            <xsl:with-param name="Value2" select="@OutstandingAllocKB" />
                        </xsl:call-template>
                </xsl:if>
            </xsl:for-each>
                    
            
            <!-- Write out the Paged Pool detail values -->
            <xsl:variable name="PagedPool" select="PoolImages[@Type='paged pool']/PoolImageInSession" />
            
            <xsl:for-each select="$PagedPool" >                    <!-- Used for Scoping. There should only be one node here -->
                <xsl:variable name="SessionId" select="@SessionId" />
                
                <xsl:for-each select="PoolImage">
                    <xsl:if test="position() &lt;= $NUM_ITEMS_DISPLAY">
                            <xsl:variable name="SectionName" select="'PagedPool'" />
                            <xsl:variable name="Description" select="concat('Session', $SessionId)" />

                            <TestCase>
                                <Parents><Parent><xsl:value-of select="concat($SectionName, '_TestCases' )" /></Parent></Parents>
                                <Key><xsl:value-of select="concat($SectionName, '_Key_', $Description , '_', @Image)" /></Key>
                                <Name><xsl:value-of select="@Image" /></Name>


                                <MetricValues>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'PagedPool_SessionId'" />
                                        <xsl:with-param name="Value" select="$Description" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'PagedPool_OutstandingAllocKB'" />
                                        <xsl:with-param name="Value" select="@OutstandingAllocKB" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'PagedPool_OutstandingAllocNumber'" />
                                        <xsl:with-param name="Value" select="@OutstandingAllocNumber" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'PagedPool_AllocKB'" />
                                        <xsl:with-param name="Value" select="@AllocKB" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'PagedPool_AllocNumber'" />
                                        <xsl:with-param name="Value" select="@AllocNumber" />
                                    </xsl:call-template>
                         </MetricValues>
                         </TestCase>
                    
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>

            
            <!-- Write out the Non-Paged Pool detail values -->
            <xsl:variable name="NonPagedPool" select="PoolImages[(@Type='NX non-paged pool') or (@Type='EX non-paged pool')]/PoolImageInSession" />
            
            <xsl:for-each select="$NonPagedPool" >              <!-- This has all of the PoolImageInSession elements. Those under 'NX non-paged pool' and those under 'EX non-paged pool'. -->
                <xsl:variable name="NxType" select="../@Type" />

                <!-- Select only those pool images with our current execution type we're looking at -->
                <!-- <xsl:for-each select="PoolImage[../../@Type=$NxType]"> hmmm... -->
                <xsl:for-each select="PoolImage">
                
                    <xsl:if test="position() &lt;= ($NUM_ITEMS_DISPLAY * 2)">
                        <xsl:variable name="Description" select="@Image"/>
                        <xsl:variable name="SiblingNodes" select="$NonPagedPool/PoolImage[@Image=$Description and ../../@Type=$NxType]"/>

                        <!-- Have the first entry do the aggregation for all of its same named siblings -->

                        <xsl:if test="generate-id($Description)=generate-id($SiblingNodes[1]/@Image)">                   <!-- The output is in sorder order, so taking the first will provide us the largest -->

                            <xsl:variable name="SectionName" select="'NonPagedPool'" />
                            <xsl:variable name="NxDesc">
                                <xsl:choose>
                                    <xsl:when test="$NxType='NX non-paged pool'">NX</xsl:when>
                                    <xsl:when test="$NxType='EX non-paged pool'">EX</xsl:when>
                                    <xsl:otherwise>UNK</xsl:otherwise>
                                </xsl:choose>
                            </xsl:variable>

                            <TestCase>
                                <Parents><Parent><xsl:value-of select="concat($SectionName, '_TestCases' )" /></Parent></Parents>
                                <Key><xsl:value-of select="concat($SectionName, '_Key_', $NxDesc , '_', @Image)" /></Key>
                                <Name><xsl:value-of select="@Image" /></Name>

                                <MetricValues>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'NonPagedPool_Type'" />
                                        <xsl:with-param name="Value" select="$NxDesc" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'NonPagedPool_OutstandingAllocKB'" />
                                        <xsl:with-param name="Value" select="sum($SiblingNodes/@OutstandingAllocKB)" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'NonPagedPool_OutstandingAllocNumber'" />
                                        <xsl:with-param name="Value" select="sum($SiblingNodes/@OutstandingAllocNumber)" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'NonPagedPool_AllocKB'" />
                                        <xsl:with-param name="Value" select="sum($SiblingNodes/@AllocKB)" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'NonPagedPool_AllocNumber'" />
                                        <xsl:with-param name="Value" select="sum($SiblingNodes/@AllocNumber)" />
                                    </xsl:call-template>
                                    <xsl:call-template name="WriteMetric">
                                        <xsl:with-param name="PrgName" select="'NonPagedPool_AggregationCount'" />
                                        <xsl:with-param name="Value" select="count($SiblingNodes)" />
                                    </xsl:call-template>
                                </MetricValues>
                            </TestCase>
                        </xsl:if>
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
            
            <!-- Add a sub-section for DriverLockedSystemPages to our NonPaged Pool -->
            <xsl:variable name="SortedNodes">
                <xsl:for-each select="/TraceData/Memory/Category-Detail/Active/Category[@Name='DriverLockedSystemPage']/Driver">
                    <xsl:sort select="@KB" data-type="number" order="descending"/>
                    <xsl:sort select="@Description" data-type="text" order="ascending"/>
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:variable>

            <xsl:for-each select="msxsl:node-set($SortedNodes)/*">
                <xsl:if test="position() &lt;= $NUM_ITEMS_DISPLAY">
                    <xsl:variable name="SectionName" select="'NonPagedPool'" />
                    <xsl:variable name="NxDesc" select="'DriverLockedSystemPages'"/>
                    <xsl:variable name="FullDescription" select="@Description"/>
                    <xsl:variable name="TruncatedDescription" select="substring(@Description, '3')"/>     <!-- Truncate the leading 'c:' -->
                    <xsl:variable name="VisibleDescription">
                        <xsl:choose>
                            <xsl:when test="string(@Description) = '&quot;Unknown&quot;'">
                              <xsl:value-of select="$FullDescription"/>
                            </xsl:when>
                            <xsl:otherwise>
                              <xsl:call-template name="GetFilePart">                                      <!-- This will convert our drive letter truncated '\Windows\System32\driver.sys' to just 'driver.sys' for display -->
                                <xsl:with-param name="FilePath" select="$TruncatedDescription"/>
                              </xsl:call-template>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:variable> 
                    <xsl:variable name="SiblingNodes" select="msxsl:node-set($SortedNodes)/*[substring(@Description, '3')=$TruncatedDescription]"/>

                    <!-- When running through the list, there can be multiple entries for a single "process" or "driver" or "map file" or whatever we're enumerating this time.
                         So each time we find a specific process, we want to find all of the other processes in the list that match this type of process. These are termed the "SiblingNodes".
                         We are going to sum all of the siblings together to write out a single entry. So our logic says if this is the first sibling node, then enter the following "if" block 
                         and write it out. If this is any sibling node other than the first, then know that we have already written it out (when we wrote out the first), and as a result, do 
                         nothing here. 
                    -->

                    <xsl:if test="generate-id($FullDescription)=generate-id($SiblingNodes[1]/@Description)">
                        <TestCase>
                            <Parents><Parent><xsl:value-of select="concat($SectionName, '_TestCases' )" /></Parent></Parents>
                            <Key><xsl:value-of select="concat($SectionName, '_Key_', $NxDesc , '_', $VisibleDescription)" /></Key>
                            <Name><xsl:value-of select="$VisibleDescription" /></Name>

                            <MetricValues>
                                <xsl:call-template name="WriteMetric">
                                    <xsl:with-param name="PrgName" select="'NonPagedPool_Type'" />
                                    <xsl:with-param name="Value" select="$NxDesc" />
                                </xsl:call-template>
                                <xsl:call-template name="WriteMetric">
                                    <xsl:with-param name="PrgName" select="'NonPagedPool_OutstandingAllocKB'" />
                                    <xsl:with-param name="Value" select="sum($SiblingNodes/@KB)" />
                                </xsl:call-template>
                                <xsl:call-template name="WriteMetric">
                                    <xsl:with-param name="PrgName" select="'NonPagedPool_OutstandingAllocNumber'" />
                                    <xsl:with-param name="Value" select="'0'" />
                                </xsl:call-template>
                                <xsl:call-template name="WriteMetric">
                                    <xsl:with-param name="PrgName" select="'NonPagedPool_AllocKB'" />
                                    <xsl:with-param name="Value" select="sum($SiblingNodes/@KB)" />
                                </xsl:call-template>
                                <xsl:call-template name="WriteMetric">
                                    <xsl:with-param name="PrgName" select="'NonPagedPool_AllocNumber'" />
                                    <xsl:with-param name="Value" select="'0'" />
                                </xsl:call-template>
                                <xsl:call-template name="WriteMetric">
                                    <xsl:with-param name="PrgName" select="'NonPagedPool_AggregationCount'" />
                                    <xsl:with-param name="Value" select="count($SiblingNodes)" />
                                </xsl:call-template>
                            </MetricValues>
                         </TestCase>
                    </xsl:if>
                </xsl:if>
            </xsl:for-each>

        </xsl:for-each>
    </xsl:template>
    
    <xsl:template name="GetFilePart">
        <xsl:param name="FilePath" />
        <xsl:choose>
            <xsl:when test="contains(string($FilePath), '\')" >
                <xsl:call-template name="GetFilePart">
                    <xsl:with-param name="FilePath" select="substring-after($FilePath, '\')" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise><xsl:value-of select="$FilePath" /></xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template name="WriteMetricValues_Memory">
        <xsl:param name="Node" />
        <xsl:for-each select="$Node">

                <!-- Output the overview metrics. This is contained in the 'Summary' node of the input file -->
                <xsl:apply-templates select="Summary" />
                
                <!-- Now wite out the process overview detail. The only one not contained in the 'Summary' section -->
                <xsl:call-template name="WriteOverview_Process">
                    <xsl:with-param name="Node" select="Process-Detail" />
                </xsl:call-template>

        </xsl:for-each>
    </xsl:template>

    
    <xsl:template name="WriteTestCases_Memory">
        <xsl:param name="Node" />
        <xsl:for-each select="$Node">

            <xsl:apply-templates select="Category-Detail"/>

            <xsl:apply-templates select="Process-Detail"/>
                
        </xsl:for-each>
    </xsl:template>

    
    <!-- Provide Summary Data -->
    <xsl:template match="Summary">
        
        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_TotalPages'" />
            <xsl:with-param name="Value" select="Total/@MB" />
        </xsl:call-template>
        
        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_AvailablePages'" />
            <xsl:with-param name="Value" select="format-number(Available/@MB + ($EtwBSize div 1024), '0.0')" /> 
        </xsl:call-template>

        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_ActivePages'" />
            <xsl:with-param name="Value" select="format-number(Active/@MB + Mod-ModNoWrite-Transition/@MB - ($EtwBSize div 1024), '0.0')" />
        </xsl:call-template>
        
        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_StandbyPages'" />
            <xsl:with-param name="Value" select="Standby/@MB" />
        </xsl:call-template>
        
        <!-- Driver Paged -->
        <xsl:variable name="DriverPagedTotal_Modified">
            <xsl:choose>
                <xsl:when test="Mod-ModNoWrite-Transition/Category[@Name='Driver-Paged']/@MB">
                    <xsl:value-of select="Mod-ModNoWrite-Transition/Category[@Name='Driver-Paged']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

                <xsl:variable name="DriverPagedTotal_Active">
            <xsl:choose>
                <xsl:when test="Active/Category[@Name='Driver-Paged']/@MB">
                    <xsl:value-of select="Active/Category[@Name='Driver-Paged']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_DriverPaged'" />
            <xsl:with-param name="Value" select="$DriverPagedTotal_Active + $DriverPagedTotal_Modified" />
        </xsl:call-template>

        <!-- Driver NonPaged -->
        <xsl:variable name="DriverNonPagedTotal_Modified">
            <xsl:choose>
                <xsl:when test="Mod-ModNoWrite-Transition/Category[@Name='Driver-NonPaged']/@MB">
                    <xsl:value-of select="Mod-ModNoWrite-Transition/Category[@Name='Driver-NonPaged']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:variable name="DriverNonPagedTotal_Active">
            <xsl:choose>
                <xsl:when test="Active/Category[@Name='Driver-NonPaged']/@MB">
                    <xsl:value-of select="Active/Category[@Name='Driver-NonPaged']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_DriverNonPaged'" />
            <xsl:with-param name="Value" select="$DriverNonPagedTotal_Active  + $DriverNonPagedTotal_Modified" /> 
        </xsl:call-template>
        

        <xsl:variable name="BinariesTotal_Modified">
            <xsl:choose>
                <xsl:when test="Mod-ModNoWrite-Transition/Category[@Name='Image']/@MB">
                    <xsl:value-of select="Mod-ModNoWrite-Transition/Category[@Name='Image']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:variable name="BinariesTotal_Active">
            <xsl:choose>
                <xsl:when test="Active/Category[@Name='Image']/@MB">
                    <xsl:value-of select="Active/Category[@Name='Image']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_Binaries'" />
            <xsl:with-param name="Value" select="$BinariesTotal_Active + $BinariesTotal_Modified" /> 
        </xsl:call-template>
        
        <xsl:variable name="MapFiles_ActivePages">
            <xsl:choose>
                <xsl:when test="Active/Category[@Name='MapFile']/@MB">
                    <xsl:value-of select="Active/Category[@Name='MapFile']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:variable name="MapFiles_ModPages">
            <xsl:choose>
                <xsl:when test="Mod-ModNoWrite-Transition/Category[@Name='MapFile']/@MB">
                    <xsl:value-of select="Mod-ModNoWrite-Transition/Category[@Name='MapFile']/@MB"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <xsl:call-template name="WriteMetric" >
            <xsl:with-param name="PrgName" select="'OverviewTotals_MapFiles'" />
            <xsl:with-param name="Value" select="$MapFiles_ActivePages + $MapFiles_ModPages" /> 
        </xsl:call-template>
        
        <xsl:apply-templates />
    </xsl:template>
    
    <xsl:template match="Category-Detail">
    
            <xsl:call-template name="WriteExpandedSection">
                <xsl:with-param name="SectionName" select="'DriverNonPaged'" />
                <xsl:with-param name="SubsectionName" select="'Active'" />
                <xsl:with-param name="PrgNameSuffix1" select="'DriverPath'" />
                <xsl:with-param name="PrgNameSuffix2" select="'Pages'" />
                <xsl:with-param name="Nodes" select="Active/Category[@Name='Driver-NonPaged']/Driver" />
            </xsl:call-template>
            
            <xsl:call-template name="WriteExpandedSection">
                <xsl:with-param name="SectionName" select="'DriverPaged'" />
                <xsl:with-param name="SubsectionName" select="'Active'" />
                <xsl:with-param name="PrgNameSuffix1" select="'DriverPath'" />
                <xsl:with-param name="PrgNameSuffix2" select="'Pages'" />
                <xsl:with-param name="Nodes" select="Active/Category[@Name='Driver-Paged']/Driver" />
            </xsl:call-template>

            <xsl:call-template name="WriteExpandedSectionWithAllMemTypes">
                <xsl:with-param name="SectionName" select="'Binaries'" />
                <xsl:with-param name="PrgNameSuffix1" select="'BinaryPath'" />
                <xsl:with-param name="PrgNameSuffix2" select="'Pages'" />
                <xsl:with-param name="ActiveNodes" select="Active/Category[@Name='Image']/Image" />
                <xsl:with-param name="ModifiedNodes" select="Mod-ModNoWrite-Transition/Category[@Name='Image']/Image" />
                <xsl:with-param name="StandbyNodes" select="Standby/Category[@Name='Image']/Image" />
            </xsl:call-template>

            <xsl:call-template name="WriteExpandedSectionWithAllMemTypes">
                <xsl:with-param name="SectionName" select="'Files'" />
                <xsl:with-param name="PrgNameSuffix1" select="'FilePath'" />
                <xsl:with-param name="PrgNameSuffix2" select="'Pages'" />
                <xsl:with-param name="ActiveNodes" select="Active/Category[@Name='MapFile']/MapFile" />
                <xsl:with-param name="ModifiedNodes" select="Mod-ModNoWrite-Transition/Category[@Name='MapFile']/MapFile" />
                <xsl:with-param name="StandbyNodes" select="Standby/Category[@Name='MapFile']/MapFile" />
            </xsl:call-template>
        
    </xsl:template>

    
    <xsl:template name="WriteOverview_Process">
        <xsl:param name="Node" />
        
        <xsl:for-each select="$Node">
            <!-- Compute the Overview Process  metric --> 
            <xsl:variable name="ActivePages" select="format-number(Active/@KB div 1024, '0.0')" /> 
            <xsl:variable name="ModPages">
                <xsl:choose>
                    <xsl:when test="Mod-ModNoWrite-Transition/@KB">
                        <xsl:value-of select="format-number(Mod-ModNoWrite-Transition/@KB div 1024, '0.0')"/>
                    </xsl:when>
                    <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
            </xsl:variable>

            <xsl:call-template name="WriteMetric" >
                <xsl:with-param name="PrgName" select="'OverviewTotals_ProcessPages'" />
                <xsl:with-param name="Value" select="$ActivePages + $ModPages" /> 
            </xsl:call-template>
        </xsl:for-each>
        
    </xsl:template>
    
    
                
    <xsl:template match="Process-Detail">
    
        <!-- Then compute the individual data for the details page --> 
        <xsl:variable name="ActiveAndModifiedNodes">
            <xsl:copy-of select="Active/Process" />
            <xsl:copy-of select="Mod-ModNoWrite-Transition/Process" />
        </xsl:variable>
        
        <xsl:call-template name="WriteProcessGroupSection">
            <xsl:with-param name="GroupName" select="'Active'" />
            <xsl:with-param name="Nodes" select="msxsl:node-set($ActiveAndModifiedNodes)/*" />
        </xsl:call-template>
        
        <xsl:call-template name="WriteProcessGroupSection">
            <xsl:with-param name="GroupName" select="'Standby'" />
            <xsl:with-param name="Nodes" select="Standby/Process" />
        </xsl:call-template>
        
    </xsl:template>

    <!-- =================== Helper Templates ================== -->
    
    
    <!-- # WriteMetric # - Named Template to write out a metric -->
    <!-- Two choices of what do to when the source metric is not available. The two main options are:
        1. Don't write the metric out at all
        2. Write out a dummy value of 0
        
        This code uses the former.
    -->
                
    <xsl:template name="WriteMetric">
        <xsl:param name="PrgName" />
        <xsl:param name="Value" />
        
        <!-- Only write out a metric if it has a value. This does mean there is no way to write out a blank metric -->
        <xsl:if test="$Value != ''">
            <MetricValue>
                <ProgrammaticName>
                    <xsl:value-of select="$PrgName" />
                </ProgrammaticName>
                <Value>
                    <xsl:value-of select="$Value" /> 
                </Value>
            </MetricValue>
        </xsl:if>
    </xsl:template>
    
    
    <!--# WriteTestCase # - Named Template to write out a Test Case -->
    <xsl:template name="WriteTestCase_2Metrics">
        <xsl:param name="Key" /> 
        <xsl:param name="Name" /> 
        <xsl:param name="Parent" /> 
        <xsl:param name="PrgName1" /> 
        <xsl:param name="Value1" />
        <xsl:param name="PrgName2" /> 
        <xsl:param name="Value2" />
        
        <TestCase>
            <Parents><Parent><xsl:value-of select="$Parent" /></Parent></Parents>
            <Key><xsl:value-of select="$Key" /></Key>
            <Name><xsl:value-of select="$Name" /></Name>
            

            <MetricValues>
                <xsl:call-template name="WriteMetric">
                    <xsl:with-param name="PrgName" select="$PrgName1" />
                    <xsl:with-param name="Value" select="$Value1" />
                </xsl:call-template>
                <xsl:call-template name="WriteMetric">
                    <xsl:with-param name="PrgName" select="$PrgName2" />
                    <xsl:with-param name="Value" select="$Value2" />
                </xsl:call-template>
            </MetricValues>

        </TestCase>
    </xsl:template>
    
    <xsl:template name="WriteTestCase_4Metrics">
        <xsl:param name="Key" /> 
        <xsl:param name="Name" /> 
        <xsl:param name="Parent" /> 
        <xsl:param name="PrgName1" /> 
        <xsl:param name="Value1" />
        <xsl:param name="PrgName2" /> 
        <xsl:param name="Value2" />
        <xsl:param name="PrgName3" /> 
        <xsl:param name="Value3" />
        <xsl:param name="PrgName4" /> 
        <xsl:param name="Value4" />

        <TestCase>
            <Parents><Parent><xsl:value-of select="$Parent" /></Parent></Parents>
            <Key><xsl:value-of select="$Key" /></Key>
            <Name><xsl:value-of select="$Name" /></Name>
            

            <MetricValues>
                <xsl:call-template name="WriteMetric">
                    <xsl:with-param name="PrgName" select="$PrgName1" />
                    <xsl:with-param name="Value" select="$Value1" />
                </xsl:call-template>
                <xsl:call-template name="WriteMetric">
                    <xsl:with-param name="PrgName" select="$PrgName2" />
                    <xsl:with-param name="Value" select="$Value2" />
                </xsl:call-template>
                <xsl:call-template name="WriteMetric">
                    <xsl:with-param name="PrgName" select="$PrgName3" />
                    <xsl:with-param name="Value" select="$Value3" />
                </xsl:call-template>
                <xsl:call-template name="WriteMetric">
                    <xsl:with-param name="PrgName" select="$PrgName4" />
                    <xsl:with-param name="Value" select="$Value4" />
                </xsl:call-template>
            </MetricValues>
            
        </TestCase>
    </xsl:template>
    <!--# WriteExpandedSection # - Named Template to write out a Test Case 
          Note: At the moment we set the Key to always be the description field.  We may want to change this later. 
                Also we always write out an agg count, so no need to take in a third PrgNameSuffix 
    -->
    <xsl:template name="WriteExpandedSection">
        <xsl:param name="SectionName" /> 
        <xsl:param name="SubsectionName" />  
        <xsl:param name="PrgNameSuffix1" /> 
        <xsl:param name="PrgNameSuffix2" /> 
        <xsl:param name="Nodes" /> 

        <xsl:variable name="SortedNodes">
            <xsl:for-each select="$Nodes">
                <xsl:sort select="@KB" data-type="number" order="descending"/>
                <xsl:sort select="@Description" data-type="text" order="ascending"/>
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:variable>

        <xsl:for-each select="msxsl:node-set($SortedNodes)/*">
            <xsl:if test="position() &lt;= $NUM_ITEMS_DISPLAY">
                <xsl:variable name="DescriptionWithDriveLetter" select="@Description"/>               
                <xsl:variable name="Description" select="substring(@Description, '3')"/>               <!-- Truncate the leading 'c:' -->
                <xsl:variable name="SiblingNodes" select="msxsl:node-set($SortedNodes)/*[substring(@Description, '3')=$Description]"/>

                <!-- When running through the list, there can be multiple entries for a single "process" or "driver" or "map file" or whatever we're enumerating this time.
                     So each time we find a specific process, we want to find all of the other processes in the list that match this type of process. These are termed the "SiblingNodes".
                     We are going to sum all of the siblings together to write out a single entry. So our logic says if this is the first sibling node, then enter the following "if" block 
                     and write it out. If this is any sibling node other than the first, then know that we have already written it out (when we wrote out the first), and as a result, do 
                     nothing here. 
                -->

                <xsl:if test="generate-id($DescriptionWithDriveLetter)=generate-id($SiblingNodes[1]/@Description)">
                    <xsl:call-template name="WriteTestCase_4Metrics">
                        <xsl:with-param name="Key" select="concat($SectionName, '_Key_',  $SubsectionName, '_', $Description)" />
                        <xsl:with-param name="Name" select="$Description" />
                        <xsl:with-param name="Parent" select="concat($SectionName, '_TestCases' )" />
                        <xsl:with-param name="PrgName1" select="concat($SectionName, '_', $PrgNameSuffix1)" />
                        <xsl:with-param name="Value1" select="$Description" />
                        <xsl:with-param name="PrgName2" select="concat($SectionName, '_', $PrgNameSuffix2)" />
                        <xsl:with-param name="Value2" select="sum($SiblingNodes/@KB)" />
                        <xsl:with-param name="PrgName3" select="concat($SectionName, '_', 'MemoryType')" />
                        <xsl:with-param name="Value3" select="$SubsectionName" />
                        <xsl:with-param name="PrgName4" select="concat($SectionName, '_', 'AggregationCount')" />  <!-- No PrgNameSuffix3 -->
                        <xsl:with-param name="Value4" select="count($SiblingNodes)" />
                    </xsl:call-template>
                </xsl:if>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <!-- Each map file will have two entries. One which is a sum of its total active and its total modified usage.
         The other is its standby usage. -->
    <xsl:template name="WriteExpandedSectionWithAllMemTypes">
        <xsl:param name="SectionName" /> 
        <xsl:param name="PrgNameSuffix1" /> 
        <xsl:param name="PrgNameSuffix2" /> 
        <xsl:param name="ActiveNodes" /> 
        <xsl:param name="ModifiedNodes" /> 
        <xsl:param name="StandbyNodes" /> 
            
        <!-- Combine all of the Active Nodes and the Modified nodes into a single result set -->
        <xsl:variable name="ActiveAndModifiedNodes">
            <xsl:copy-of select="$ActiveNodes" /> 
            <xsl:copy-of select="$ModifiedNodes" />
        </xsl:variable>
        
        <xsl:call-template name="WriteExpandedSection">
            <xsl:with-param name="SectionName" select="$SectionName" />
            <xsl:with-param name="SubsectionName" select="'Active'" />
            <xsl:with-param name="PrgNameSuffix1" select="$PrgNameSuffix1" />
            <xsl:with-param name="PrgNameSuffix2" select="$PrgNameSuffix2" />
            <xsl:with-param name="Nodes" select="msxsl:node-set($ActiveAndModifiedNodes)/*" />
        </xsl:call-template>
        
        <xsl:call-template name="WriteExpandedSection">
            <xsl:with-param name="SectionName" select="$SectionName" />
            <xsl:with-param name="SubsectionName" select="'Standby'" />
            <xsl:with-param name="PrgNameSuffix1" select="$PrgNameSuffix1" />
            <xsl:with-param name="PrgNameSuffix2" select="$PrgNameSuffix2" />
            <xsl:with-param name="Nodes" select="$StandbyNodes" />
        </xsl:call-template>
            

    </xsl:template>

    <xsl:template name="WriteProcessGroupSection">
        <xsl:param name="GroupName" /> 
        <xsl:param name="Nodes" /> 

        <xsl:variable name="SortedNodes">
            <xsl:for-each select="$Nodes">
                <xsl:sort select="@KB" data-type="number" order="descending"/>
                <xsl:sort select="@Description" data-type="text" order="ascending"/>
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:variable>

        <xsl:for-each select="msxsl:node-set($SortedNodes)/*">
            <xsl:if test="position() &lt;= $NUM_ITEMS_DISPLAY">
                <xsl:variable name="DescriptionWithPid" select="@Description"/>
                <xsl:variable name="Description" select="substring-before( @Description, ' (' )"/>
                <xsl:variable name="SiblingNodes" select="msxsl:node-set($SortedNodes)/*[substring-before( @Description, ' (' )=$Description]"/>

                 <!-- When running through the list, there can be multiple entries for a single "process" or "driver" or "map file" or whatever we're enumerating this time.
                     So each time we find a specific process, we want to find all of the other processes in the list that match this type of process. These are termed the "SiblingNodes".
                     We are going to sum all of the siblings together to write out a single entry. So our logic says if this is the first sibling node, then enter the following "if" block 
                     and write it out. If this is any sibling node other than the first, then know that we have already written it out (when we wrote out the first), and as a result, do 
                     nothing here. 
                 -->

                <!-- Determine if this node is the first sibling -->
                <xsl:if test="generate-id($DescriptionWithPid)=generate-id($SiblingNodes[1]/@Description)">
                  <TestCase>
                    <Parents><Parent><xsl:value-of select="'Process_TestCases'" /></Parent></Parents>
                    <Key><xsl:value-of select="concat('Process_Key_',$GroupName,'_', $Description)" /></Key>
                    <Name><xsl:value-of select="$Description" /></Name>

                    <MetricValues>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_PageType'" />
                            <xsl:with-param name="Value" select="$GroupName" />
                        </xsl:call-template>
                        
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_AggregationCount'" />
                            <xsl:with-param name="Value" select="count($SiblingNodes)" />
                        </xsl:call-template>
                        
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_ProcessTotal'" />
                            <xsl:with-param name="Value" select="sum($SiblingNodes/@KB)" />
                        </xsl:call-template>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_UserStack'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='UserStack']/@KB)" />
                        </xsl:call-template>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_CopyOnWriteImage'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='CopyOnWriteImage']/@KB)" />
                        </xsl:call-template>
                        <!-- Virtual Alloc is the sum of both Virtual Alloc and Virtual Alloc Pre-Trace -->
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_VirtualAllocCombined'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='VirtualAlloc']/@KB) + sum($SiblingNodes/Category[@Name='VirtualAlloc_PreTrace']/@KB)" />
                        </xsl:call-template>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_Win32Heap'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='Win32Heap']/@KB)" />
                        </xsl:call-template>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_StraggleIOPage'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='StraggleIOPage']/@KB)" />
                        </xsl:call-template>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_PFMappedSection'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='PFMappedSection']/@KB)" />
                        </xsl:call-template>
                        <xsl:call-template name="WriteMetric">
                            <xsl:with-param name="PrgName" select="'Process_KernelStack'" />   
                            <xsl:with-param name="Value" select="sum($SiblingNodes/Category[@Name='KernelStack']/@KB)" />
                        </xsl:call-template>

                    </MetricValues>

                  </TestCase>
                </xsl:if>
                
            </xsl:if>
        </xsl:for-each>

    </xsl:template>

    
</xsl:stylesheet>
