[xsl] use generate-id and keys to make a transform more efficient

Subject: [xsl] use generate-id and keys to make a transform more efficient
From: "Mangrove Jack" <mangrovejack@xxxxxx>
Date: Wed, 07 Mar 2012 00:57:50 -0500
Hi,

I have the following that I'm currently working on and am sure that it can be improved upon. B I've got Michael Kay's book and have been through Dave Pawson's site many times, but can't figure our how to apply their advice to my specific tranform.

Anyway, I'm limited to pure XSLT (no extension functions), v1.0 only. B No option to change the input xml nor upgrade to XSLT v2.0 either unfortunately.

Here are the contents of my files:

input.xml:
<entries>
 B <entry>
 B  B <qqqq>
 B  B  B <id>1111</id>
 B  B </qqqq>
 B </entry>
 B <entry>
 B  B <startLoop>
 B  B  B <loopId>1</loopId>
 B  B </startLoop>
 B </entry>
 B <entry>
 B  B <qqqq>
 B  B  B <id>2222</id>
 B  B </qqqq>
 B </entry>
 B <entry>
 B  B <endLoop>
 B  B  B <loopId>1</loopId>
 B  B </endLoop>
 B </entry>
 B <entry>
 B  B <qqqq>
 B  B  B <id>3333</id>
 B  B </qqqq>
 B </entry>
 B <entry>
 B  B <startLoop>
 B  B  B <loopId>2</loopId>
 B  B </startLoop>
 B </entry>
 B <entry>
 B  B <endLoop>
 B  B  B <loopId>2</loopId>
 B  B </endLoop>
 B </entry>
 B <entry>
 B  B <qqqq>
 B  B  B <id>4444</id>
 B  B </qqqq>
 B </entry>
</entries>


output.xml:
<AAA>
 B <SEQUENCE>
 B  B <outputEntry>
 B  B  B <entry>
 B  B  B  B <qqqq>
 B  B  B  B  B <id>1111</id>
 B  B  B  B </qqqq>
 B  B  B </entry>
 B  B </outputEntry>
 B  B <outputEntry>
 B  B  B <entry>
 B  B  B  B <startLoop>
 B  B  B  B  B <loopId>1</loopId>
 B  B  B  B </startLoop>
 B  B  B </entry>
 B  B </outputEntry>
 B  B <outputEntry>
 B  B  B <entry>
 B  B  B  B <qqqq>
 B  B  B  B  B <id>3333</id>
 B  B  B  B </qqqq>
 B  B  B </entry>
 B  B </outputEntry>
 B  B <outputEntry>
 B  B  B <entry>
 B  B  B  B <startLoop>
 B  B  B  B  B <loopId>2</loopId>
 B  B  B  B </startLoop>
 B  B  B </entry>
 B  B </outputEntry>
 B  B <outputEntry>
 B  B  B <entry>
 B  B  B  B <qqqq>
 B  B  B  B  B <id>4444</id>
 B  B  B  B </qqqq>
 B  B  B </entry>
 B  B </outputEntry>
 B </SEQUENCE>

 B <LOOPS>
 B  B <LOOP>
 B  B  B <STARTLOOP>
 B  B  B  B <entry>
 B  B  B  B  B <startLoop>
 B  B  B  B  B  B <loopId>1</loopId>
 B  B  B  B  B </startLoop>
 B  B  B  B </entry>
 B  B  B </STARTLOOP>
 B  B  B <MIDDLE>
 B  B  B  B <entry>
 B  B  B  B  B <qqqq>
 B  B  B  B  B  B <id>2222</id>
 B  B  B  B  B </qqqq>
 B  B  B  B </entry>
 B  B  B </MIDDLE>
 B  B  B <ENDLOOP>
 B  B  B  B <entry>
 B  B  B  B  B <endLoop>
 B  B  B  B  B  B <loopId>1</loopId>
 B  B  B  B  B </endLoop>
 B  B  B  B </entry>
 B  B  B </ENDLOOP>
 B  B </LOOP>

 B  B <LOOP>
 B  B  B <STARTLOOP>
 B  B  B  B <entry>
 B  B  B  B  B <startLoop>
 B  B  B  B  B  B <loopId>2</loopId>
 B  B  B  B  B </startLoop>
 B  B  B  B </entry>
 B  B  B </STARTLOOP>
 B  B  B <ENDLOOP>
 B  B  B  B <entry>
 B  B  B  B  B <endLoop>
 B  B  B  B  B  B <loopId>2</loopId>
 B  B  B  B  B </endLoop>
 B  B  B  B </entry>
 B  B  B </ENDLOOP>
 B  B </LOOP>
 B </LOOPS>
</AAA>



XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; exclude-result-prefixes="xsl">
 B <xsl:output method="xml" omit-xml-declaration="yes"/>

 B <xsl:template match="/entries">
 B  B <AAA> B  
 B  B  B <!-- first, output sequence without loop contents -->
 B  B  B <SEQUENCE>
 B  B  B  B <xsl:for-each select="entry">
 B  B  B  B  B <xsl:choose>
 B  B  B  B  B  B <xsl:when test="not(preceding-sibling::entry[startLoop]) or preceding-sibling::entry[endLoop] and not(./endLoop)">
 B  B  B  B  B  B  B <outputEntry>
 B  B  B  B  B  B  B  B <xsl:copy-of select="."/>
 B  B  B  B  B  B  B </outputEntry>
 B  B  B  B  B  B </xsl:when>
 B  B  B  B  B </xsl:choose>
 B  B  B  B </xsl:for-each>
 B  B  B </SEQUENCE>
 B  B  B 
 B  B  B <!-- second, output each loop sequence contents -->
 B  B  B <LOOPS>
 B  B  B  B <xsl:for-each select="entry">
 B  B  B  B  B <xsl:if test="./startLoop">
 B  B  B  B  B  B <LOOP>
 B  B  B  B  B  B  B <xsl:variable name="start" select="count(preceding-sibling::*) + 1"/>
 B  B  B  B  B  B  B <xsl:variable name="end" select="$start + count(following-sibling::entry[endLoop])"/>
 B  B  B  B  B  B  B <STARTLOOP>
 B  B  B  B  B  B  B  B <xsl:copy-of select="."/>
 B  B  B  B  B  B  B </STARTLOOP>
 B  B  B  B  B  B  B <xsl:for-each select="/entries/entry[position() &gt; $start and position() &lt;= $end]">
 B  B  B  B  B  B  B  B <xsl:choose>
 B  B  B  B  B  B  B  B  B <xsl:when test="./endLoop">
 B  B  B  B  B  B  B  B  B  B <ENDLOOP>
 B  B  B  B  B  B  B  B  B  B  B <xsl:copy-of select="."/>
 B  B  B  B  B  B  B  B  B  B </ENDLOOP>
 B  B  B  B  B  B  B  B  B </xsl:when>
 B  B  B  B  B  B  B  B  B <xsl:otherwise>
 B  B  B  B  B  B  B  B  B  B <MIDDLE>
 B  B  B  B  B  B  B  B  B  B  B <xsl:copy-of select="."/>
 B  B  B  B  B  B  B  B  B  B </MIDDLE>
 B  B  B  B  B  B  B  B  B </xsl:otherwise>
 B  B  B  B  B  B  B  B </xsl:choose>
 B  B  B  B  B  B  B </xsl:for-each>
 B  B  B  B  B  B </LOOP>
 B  B  B  B  B </xsl:if>
 B  B  B  B </xsl:for-each>
 B  B  B </LOOPS>
 B  B </AAA>
 B </xsl:template>

</xsl:stylesheet>



Thanks for any advice,
Michael.

Current Thread