How-to break a for-each loop in XSLT?

2019-01-11 23:19发布

问题:

How-to break a for-each loop in XSLT?

回答1:

XSLT is written in a very functional style, and in this style there is no equivalent of a break statement. What you can do is something like this:

<xsl:for-each select="...nodes...">
    <xsl:if test="...some condition...">
        ...body of loop...
    </xsl:if>
</xsl:for-each>

That way the for-each will still iterate through all the nodes, but the body of the loop will only be executed if the condition is true.



回答2:

Put the condition for stopping the "loop" in the select attribute of the for-each element. For instance, to "break" after four elements:

<xsl:for-each select="nodes[position()&lt;=4]">

To iterate up to but not including a node that satisfied some particular condition:

<xsl:for-each select="preceding-sibling::node[condition]">


回答3:

XSLT isn't a procedural language; don't think of for-each as being a "loop" in the way you have a loop in Java. For-each is a way to apply a template to each of a bunch of items. It doesn't necessarily happen in a particular order, so you can't think of it as "apply this template to each of a bunch of items until such-and-such happens, then stop".

That said, you can use the select attribute to filter the results, so it becomes more like "apply a template to each of a bunch of items, but only if such-and-such is true of them".

If what you really want is "apply a template to each of a bunch of items, where such-and-such is true of them, but only to the first one this is true of", you can combine the select attribute with the position() function.



回答4:

A "break" from the body of an <xsl:for-each> XSLT instruction cannot be specified using a syntactic construct, however it can be simulated.

This code snippet at topxml.com describes the technique in detail:

In case you need a ""break"" from an xsl:for-each loop

Essentially two techniques are discussed:

  1. Performing something inside the body of <xsl:for-each> only if a specific condition is satisfied.

  2. Specifying the processing not using <xsl:for-each> but with recursion

The second method has the benefit of being able to perform the exit immediately, contrasted with the first method having to still perform many "empty cycles" even after the exit-condition has been satisfied.



回答5:

Hello I kwow this is an old post but maybe it can help other developers. I have found a way to break a for each in XSLT it is not litteraly a break but if you see the code you will get it. As you know or not know you can use inline C# code in xslt. In this example i want to loop al the nodes and take the first NTE node with Value RC But if I get a node that differs from the NTE node i want to stop looking at the condition. So I set a global variable in C# code and I ask the value each time I go through a node:

    <xsl:value-of select="userCSharp:SetStopForeach('true')" />
<xsl:for-each select="following-sibling::node()">

        <xsl:if test="local-name()='NTE_NotesAndComments_3' and userCSharp:GetStopForeach()" >

        <xsl:for-each select="NTE_4_CommentType">
            <xsl:if test="(CE_0364_0_IdentifierSt)[text()=&quot;RC&quot;]"> 
        <ns0:RESULTAAT_COMMENTAAR>
                    <xsl:for-each select="../NTE_3_Comment">

                        <xsl:value-of select="./text()" />
                    </xsl:for-each>
                </ns0:RESULTAAT_COMMENTAAR> 
            </xsl:if>
        </xsl:for-each>
        </xsl:if>
        <xsl:if test="local-name()='ORC_CommonOrder'" >
            <xsl:value-of select="userCSharp:SetStopForeach('false')" />
        </xsl:if>
    </xsl:for-each>


    .....

    <msxsl:script language="C#" implements-prefix="userCSharp">
 <![CDATA[ 

    public bool StopForeach=false;
    public bool GetStopForeach() {
        return StopForeach;
    }
    public string SetStopForeach(bool aValue) {
         StopForeach=aValue;
         return "";
    }

      ]]> 
      </msxsl:script>


回答6:

I had a similar situation and here is the code I had written. For logical reasons, I couldn't fit in the other conditions with condition01.

<xsl:for-each select="msxsl:node-set($DATA6)[condition01]"> 
<xsl:choose>
<xsl:when test="not((condtion02 or  condition03) and condition04)">
--body of for loop 
</xsl:when>
</xsl:choose>
</xsl:for-each>


标签: xslt