RE: [xsl] Alternative for breaking out of for-each loop in XSLT

Subject: RE: [xsl] Alternative for breaking out of for-each loop in XSLT
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 15 Sep 2006 11:38:01 +0100
To improve the performance of a look-up like this, use keys.

xsl:for-each isn't a loop, it is a mapping function. The concept of breaking
out of a mapping function doesn't make sense. You're making the mistake of
imagining that it processes each element in order, one at a time, starting
at the beginning.

Your logic can be vastly simplified. REplace

>     <xsl:for-each select="document('REC_STATUS.xml')//error/header">
>         <xsl:variable name="varFlag">
>             <xsl:for-each select="parameter">
>                 <xsl:if test="@name='code' and @value=$statCode">
>                     <xsl:text>true</xsl:text>
>                 </xsl:if>
>             </xsl:for-each>
>         </xsl:variable>
>         <xsl:if test="$varFlag='true'">
>             <xsl:for-each select="parameter">
>                 <xsl:if test="@name='value'">
>                     <xsl:value-of select="@value"/>
>                 </xsl:if>
>             </xsl:for-each>
>         </xsl:if>
>     </xsl:for-each>

by:
 
<xsl:value-of select="document('REC_STATUS.xml')
             //error/header[parameter[@name='code' and @value=$statCode]]
             /parameter[@name='value']/@value">

(and then replace it by a call on key())

Michael Kay
http://www.saxonica.com/


 

> -----Original Message-----
> From: Ambika.Das@xxxxxxxxxxxxxxxxxx 
> [mailto:Ambika.Das@xxxxxxxxxxxxxxxxxx] 
> Sent: 15 September 2006 11:23
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Alternative for breaking out of for-each loop in XSLT
> 
> Hi,
> 
> I want to read the error description corresponding to error 
> codes which will be included in the output of the 
> transformation. The structure of the XML file 
> (REC_STATUS.xml) containing error codes is as follows.
> 
> <?xml version="1.0" encoding="UTF-8" ?>
> 
> <error>
> 
> <header name="ERR_STATUS">
> <parameter name="value" value="Permission Denied "/> 
> <parameter name="code" value="1"/> <parameter name="shortStr" 
> value="BN"/> </header>
> 
> </error>
> 
> There is one XSL file which reads the error code as follows.
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> version="1.0">
> 
> <xsl:template name="StatusDesc">
>     <xsl:param name="statCode"/>
>     <xsl:value-of select="$statCode"/>
>     <xsl:for-each select="document('REC_STATUS.xml')//error/header">
>         <xsl:variable name="varFlag">
>             <xsl:for-each select="parameter">
>                 <xsl:if test="@name='code' and @value=$statCode">
>                     <xsl:text>true</xsl:text>
>                 </xsl:if>
>             </xsl:for-each>
>         </xsl:variable>
>         <xsl:if test="$varFlag='true'">
>             <xsl:for-each select="parameter">
>                 <xsl:if test="@name='value'">
>                     <xsl:value-of select="@value"/>
>                 </xsl:if>
>             </xsl:for-each>
>         </xsl:if>
>     </xsl:for-each>
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> The problem is that, each time I need to get an error 
> description from the XML file, the whole XML file needs to be 
> parsed. For example, if the XML file contains 100 error 
> codes, it requires 100 iterations. Even if the error code is 
> found, I can't stop the iteration because XSLT doesn't 
> support breaking out of for each loop. This can lead to 
> performance issues in production.
> 
> Let me know if the above information is sufficient.
> 
> How can I break out of the for-each loop once the error code is found?
> 
> Thanks & Regards,
> Ambika Prasad Das

Current Thread