I have an input XML like the following:
Code:
<resultset>
<heading>
<column>server</column>
<column>name</column>
<column>val</column>
<column>at</column>
</heading>
<rows>
<row>
<server>wmi1</server>
<name>cpu</name>
<val>1</val>
<at>0000</at>
</row>
<row>
<server>wmi1</server>
<name>Current-service-threads</name>
<val>1</val>
<at>0000</at>
</row>
<row>
<server>wmi1</server>
<name>Current-system-threads</name>
<val>148</val>
<at>0000</at>
</row>
<row>
<server>wmi1</server>
<name>cpu</name>
<val>2</val>
<at>0005</at>
</row>
<row>
<server>wmi1</server>
<name>Current-service-threads</name>
<val>4</val>
<at>0005</at>
</row>
<row>
<server>wmi1</server>
<name>Current-system-threads</name>
<val>142</val>
<at>0005</at>
</row>
.....
</rows>
</resultset>
The actual input is large --the "at" element runs from 0000 to 2355 in increments of 5, and the server element's value changes from wmi1 to wm10 in increments of 1. So you can imagine how big the input file is.
I need to get an output like so:
Code:
<resultset>
<heading>
<column>at</column>
<column>wmi1-cpu</column>
<column>wmi1-Current-service-threads</column>
...
<heading>
<rows>
<row>
<at>0000</at>
<wmi1-cpu>1</server-name>
<wmi1-Current-service-threads>1</wmi1-Current-service-threads>
<wmi1-Current-system-threads>148</wmi1-Current-system-threads>
</row>
<row>
<at>0005</at>
<wmi1-cpu>2</server-name>
<wmi1-Current-service-threads>4</wmi1-Current-service-threads>
<wmi1-Current-system-threads>142</wmi1-Current-system-threads>
</row>
.....
</rows>
</resultset>
I created the following XSLT program, and that works.
Code:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" />
<xsl:key name="key_server" match="row" use="server"/>
<xsl:variable name="all_server">
<xsl:copy-of select="/resultset/rows/row[count(.|key('key_server', server)[1])=1]/server"/>
</xsl:variable>
<xsl:key name="key_name" match="row" use="name"/>
<xsl:variable name="all_name">
<xsl:copy-of select="/resultset/rows/row[count(.|key('key_name', name)[1])=1]/name"/>
</xsl:variable>
<xsl:key name="key_at" match="row" use="at"/>
<xsl:variable name="all_at">
<xsl:copy-of select="/resultset/rows/row[count(.|key('key_at', at)[1])=1]/at"/>
</xsl:variable>
<xsl:variable name="docu"><xsl:copy-of select="/"/></xsl:variable>
<xsl:template match="/">
<resultset>
<heading>
<column>at</column>
<xsl:for-each select="$all_server/*">
<xsl:sort select="."/>
<xsl:variable name="server"><xsl:value-of select="."/></xsl:variable>
<xsl:for-each select="$all_name/*">
<xsl:sort select="."/>
<xsl:variable name="name"><xsl:value-of select="."/></xsl:variable>
<column><xsl:value-of select="$server"/>-<xsl:value-of select="$name"/></column>
</xsl:for-each>
</xsl:for-each>
</heading>
<rows>
<xsl:for-each select="$all_at/*">
<xsl:sort select="." data-type="number"/>
<xsl:variable name="at"><xsl:value-of select="."/></xsl:variable>
<row>
<xsl:message><xsl:value-of select="$at"/></xsl:message>
<at><xsl:value-of select="$at"/></at>
<xsl:for-each select="$all_server/*">
<xsl:sort select="."/>
<xsl:variable name="server"><xsl:value-of select="."/></xsl:variable>
<xsl:for-each select="$all_name/*">
<xsl:sort select="."/>
<xsl:variable name="name"><xsl:value-of select="."/></xsl:variable>
<xsl:element name="{$server-$name}">
<xsl:value-of select="$docu/resultset/rows/row[server=$server and name=$name and at=$at]/val"/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</row>
</xsl:for-each>
</rows>
</resultset>
</xsl:template>
</xsl:stylesheet>
But, the trouble is, it literally takes about an hour to do the job in a decent machine. I have written so many other XSLTs for almost close to a decade now.
But there are some cases where I am not writing something efficiently where the CPU goes sky high and it takes over an hour!. What is the key point here that I am missing.
I figure I must be doing something in XSLT in a less efficient way than what XSLT is capable of delivering.