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

后端 未结 6 1932
死守一世寂寞
死守一世寂寞 2020-12-03 13:52

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

相关标签:
6条回答
  • 2020-12-03 14:22

    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.

    0 讨论(0)
  • 2020-12-03 14:22

    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]">
    
    0 讨论(0)
  • 2020-12-03 14:28

    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>
    
    0 讨论(0)
  • 2020-12-03 14:32

    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. This can be improved if the condition can be specified in the select attribute of <xsl:for-each> -- in this case only the necessary nodes will be processed. See for example: https://stackoverflow.com/a/7532602/36305

    2. Specifying the processing not using <xsl:for-each> but with recursion. There are many examples of recursive processing with XSLT. See the code at: https://fxsl.sf.net/

    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.

    0 讨论(0)
  • 2020-12-03 14:42

    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.

    0 讨论(0)
  • 2020-12-03 14:42

    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>
    
    0 讨论(0)
提交回复
热议问题