implementing lookup in XSLT

2019-09-06 00:05发布

问题:

Running xml and xslt below and getting the output at bottom. Column with black background Activity Correct Name added manually to provide desired output of Activity Name column which produces wrong values at this moment. I would like to implement following logic.

Pseudo;

  • Select records where Level==Start
    • Set ActivityName = Description
    • Capture ActivityId and ActivityName into memory for future lookup
  • Set each record's ActivityName based on Captured records where ActivityId is a match

you may also find completed logic with C# at .NET Fiddle

XML

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl" ?>
<root>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
   <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Information">0</SubType>
        <Correlation ActivityID="a54221e2-ad37-434a-8f0d-101f7abc2221" />
    </System>
    <ApplicationData>Test21</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
   <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Information">0</SubType>
        <Correlation ActivityID="d30741c2-da73-434a-8f0d-101f7ceb2228" />
    </System>
    <ApplicationData>Test24</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Start">0</SubType>
        <Correlation ActivityID="00000000-0000-0000-0000-000000000000" />
    </System>
    <ApplicationData>Alpha</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Information">0</SubType>
        <Correlation ActivityID="00000000-0000-0000-0000-000000000000" />
    </System>
    <ApplicationData>Test31</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Verbose">0</SubType>
        <Correlation ActivityID="3b081a36-43d5-4ecc-b381-628c33316205" />
    </System>
    <ApplicationData>Test51</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Start">0</SubType>
        <Correlation ActivityID="aa5a5b9c-4b24-43af-9f49-32656385e17d" />
    </System>
    <ApplicationData>Bravo</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
   <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Start">0</SubType>
        <Correlation ActivityID="d30741c2-da73-434a-8f0d-101f7ceb2228" />
    </System>
    <ApplicationData>Charlie</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
    <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Error">0</SubType>
        <Correlation ActivityID="aa5a5b9c-4b24-43af-9f49-32656385e17d" />
    </System>
    <ApplicationData>Test71</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
   <System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
        <SubType Name="Transfer">0</SubType>
        <Correlation ActivityID="00000000-0000-0000-0000-000000000000" />
    </System>
    <ApplicationData>Test41</ApplicationData>
</E2ETraceEvent>    
</root>

XSLT

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:te="http://schemas.microsoft.com/2004/06/E2ETraceEvent"
                xmlns:s="http://schemas.microsoft.com/2004/06/windows/eventlog/system"
                xmlns:sd="http://schemas.microsoft.com/2004/08/System.Diagnostics"
                xmlns:tr="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord"
                exclude-result-prefixes="te s sd tr">
    <xsl:output method="html" indent="no"/>

    <xsl:template match="/">
        <html>
            <head>                  
            </head>
            <body>
                <div>
                    <div>
                    <table>
                        <thead>
                            <tr>                                
                                <th>Description</th>
                                <th>Level</th>
                                <th>Activity Name</th>
                                <th>Activity ID</th>
                            </tr>
                        </thead>
                        <tbody>                     
                            <xsl:for-each select="//te:E2ETraceEvent">

                            <xsl:variable name="level">
                                <xsl:value-of select=".//s:SubType/@Name"/>
                            </xsl:variable>

                            <xsl:variable name="description">
                                <xsl:value-of select=".//te:ApplicationData/text()"/>
                            </xsl:variable>

                            <tr>
                                <!-- APPLICATION DATA -->
                                <td>
                                    <xsl:value-of select="$description"/>
                                </td>

                                <!-- LEVEL -->
                                <td>
                                    <xsl:value-of select="$level"/>                                     
                                </td>

                                <!-- ACTIVITY NAME -->
                                <td>
                                    <xsl:value-of select="((. | preceding-sibling::te:E2ETraceEvent)[s:System/s:SubType/@Name='Start'])[last()]/te:ApplicationData"/>
                                </td>

                                <!-- ACTIVITY ID -->
                                <td>
                                    <xsl:value-of select=".//s:Correlation/@ActivityID"/>                                       
                                </td>
                            </tr>
                        </xsl:for-each>
                        </tbody>
                    </table>
                    </div>
                </div>
            </body>
        </html>
    </xsl:template> 
</xsl:stylesheet>

OUTPUT

回答1:

Your pseudocode is a bit cryptic (like there no records where Level==Start). Besides, XSLT doesn't work that way. In XSLT, a lookup is accomplished using a key.

Try adding this to the top level of your stylesheet:

<xsl:key name="start" match="te:E2ETraceEvent[s:System/s:SubType/@Name='Start']" use="s:System/s:Correlation/@ActivityID" />

and then add this column to your table:

<td>
    <xsl:value-of select="key('start', s:System/s:Correlation/@ActivityID)/te:ApplicationData"/>    
</td>


标签: xml xslt