none
Exit a loop from custom xslt RRS feed

  • Question

  • My custom xslt is as follows which I am using in my map:

    <?xml version="1.0" encoding="utf-16"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
                    exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://Students.Student.SourceSchema"
                    xmlns:ns0="http://Students.Student.DestinationSchema"
                    xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
      <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />

      <xsl:template match="/">
        <xsl:apply-templates select="/s0:Students" />
      </xsl:template>
      <xsl:template match="/s0:Students">
        <ns0:DestinationDetails>

          <xsl:for-each select="StudentTransactions">
            <xsl:if test="FName='H'">

              <xsl:variable name="var:v104" select="ID"/>

              <xsl:for-each select="/s0:Students/StudentTransactions[FName='D' and ID_Detail=$var:v104]">


                <xsl:variable name="Detail_String" select="string(GL_String/text())"/>


                <xsl:if test="$Detail_String!=''">

                  <Details>
                    <HeaderSegment>

                    </HeaderSegment>
                  </Details>
                  </xsl:if>
              </xsl:for-each>

      
            </xsl:if>

          </xsl:for-each>
         


        

        </ns0:DestinationDetails>
      </xsl:template>

      <msxsl:script language="C#" implements-prefix="userCSharp">
        <![CDATA[
    public string StringConcat(string param0)
    {
       return param0;
    }



    ]]>
      </msxsl:script>
    </xsl:stylesheet>


    I want to break the following loop : 

    <xsl:for-each select="/s0:Students/StudentTransactions[FName='D' and ID_Detail=$var:v104]">

    when  <xsl:if test="$Detail_String!=''"> condition is true.


    Any kind of  help would be appreciated.

                                                                                                         



    Prakash


    • Edited by Shivay_ Saturday, December 6, 2014 2:18 PM
    Saturday, December 6, 2014 2:10 PM

Answers

  • Got your point. The counter is not incrementing because, varialbes are immutable in XSLT, i.e. they can't be changed. I think what you need to do is use the position(). With the resultset of For-each, using position()=1 in <xsl:if test="position() =1 , you would just access the first record of the resultset from for-each

    If my understanding of your problem is correct, then the following XSLT shall work for you.

    <?xml version="1.0" encoding="utf-16"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://CallTemplate_Increment.StudentSchema" xmlns:ns0="http://CallTemplate_Increment.DestinationStudentSchema" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
      <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
      <xsl:template match="/">
        <xsl:apply-templates select="/s0:Students" />
      </xsl:template>
      <xsl:template match="/s0:Students">
        <ns0:DestinationDetails>
          <xsl:for-each select="StudentTransactions">
            <xsl:if test="FName='H'">
              <xsl:variable name="var:v104" select="ID"/>
              <xsl:variable name="count" select="0"/>
              
                     
              <xsl:for-each select="/s0:Students/StudentTransactions[FName='D' and ID_Detail=$var:v104]">
                
                <xsl:variable name="Detail_String" select="string(GL_String/text())"/>
                <!--<xsl:if test="$Detail_String!='' and $count=0">-->
                <xsl:if test="position() =1 and $Detail_String!=''" >
                  <xsl:variable name="var:v1" select="userCSharp:StringConcat(string(FName/text()) , string(LName/text()))" />
                  <Details>
                    <ID>
                      <xsl:value-of select="ID/text()" />
                    </ID>
                    <FullName>
                      <xsl:value-of select="$var:v1" />
                    </FullName>
                    <Cost>
                      <xsl:value-of select="Cost/text()" />
                    </Cost>
                  </Details>
                  <!--<xsl:value-of select="$count + 1"/>-->
                </xsl:if>
              </xsl:for-each>
            </xsl:if>
          </xsl:for-each>
        </ns0:DestinationDetails>
      </xsl:template>
      <msxsl:script language="C#" implements-prefix="userCSharp">
        <![CDATA[
    public string StringConcat(string param0, string param1)
    {
       return param0 + param1;
    }
    
    
    
    ]]>
      </msxsl:script>
    </xsl:stylesheet>


    If this answers your question please mark it accordingly. If this post is helpful, please vote as helpful by clicking the upward arrow mark next to my reply.

    • Marked as answer by Shivay_ Monday, December 8, 2014 11:05 AM
    Saturday, December 6, 2014 5:51 PM

All replies

  • XSLT is imperative not functional. 

    In XSLT you can't exit a loop. What you can do is in select statement of the  <xsl:for-each, specify the condition that selected nodes must meet. May be something like

     <xsl:for-each select="/s0:Students/StudentTransactions[(FName='D') and (ID_Detail=$var:v104) and (GL_String/text()=='')]">


    (I may not be correct in the conditions specified in For-each, this is just to show an example) as said exit loop doesn't exist in XSLT, handle it in the filter condition used in For-each.


    If this answers your question please mark it accordingly. If this post is helpful, please vote as helpful by clicking the upward arrow mark next to my reply.


    Saturday, December 6, 2014 2:52 PM
  • This is not possible. There isn't any XSLT instruction for exiting the processing of xsl:for-each and continuing the execution of the transformation. What you can do is specify precisely the conditions that the selected nodes should meet

    <xsl:for-each select="/s0:Students/StudentTransactions[FName='D' and ID_Detail=$var:v104]">

    So the for each loop for studentTransactions can only terminate when condtion is not meet. This is simply by reason that XSLT doing mapping by structure.

    Thanks

    Abhishek



    Saturday, December 6, 2014 3:05 PM
  •                                        

    Dear Ashwin, Your reply is appreciable but it's not match with my requirement. I want to do this with the help of global variable and incrementd by one but its value is not changing.

    <?xml version="1.0" encoding="utf-16"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
                    exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://Students.Student.SourceSchema"
                    xmlns:ns0="http://Students.Student.DestinationSchema"
                    xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
      <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />

      <xsl:template match="/">
        <xsl:apply-templates select="/s0:Students" />
      </xsl:template>
      <xsl:template match="/s0:Students">
        <ns0:DestinationDetails>

          <xsl:for-each select="StudentTransactions">
            <xsl:if test="FName='H'">

              <xsl:variable name="var:v104" select="ID"/>
              <xsl:variable name="count" select="0"/>

              <xsl:for-each select="/s0:Students/StudentTransactions[FName='D' and ID_Detail=$var:v104]">


                <xsl:variable name="Detail_String" select="string(GL_String/text())"/>


                <xsl:if test="$Detail_String!='' and $count=0">



                  <Details>
                    <HeaderSegment>

                    </HeaderSegment>
                  </Details>
                  <xsl:value-of select="$count + 1"/>
                  </xsl:if>
              </xsl:for-each>


            </xsl:if>

          </xsl:for-each>





        </ns0:DestinationDetails>
      </xsl:template>

      <msxsl:script language="C#" implements-prefix="userCSharp">
        <![CDATA[
    public string StringConcat(string param0)
    {
       return param0;
    }



    ]]>
      </msxsl:script>
    </xsl:stylesheet>


    Prakash

    Saturday, December 6, 2014 3:06 PM
  • what are your trying to do? Are trying to exit a loop for increment a counter.

    Provide us the schema and the requirement, we will help you.


    If this answers your question please mark it accordingly. If this post is helpful, please vote as helpful by clicking the upward arrow mark next to my reply.

    Saturday, December 6, 2014 4:06 PM
  • Got your point. The counter is not incrementing because, varialbes are immutable in XSLT, i.e. they can't be changed. I think what you need to do is use the position(). With the resultset of For-each, using position()=1 in <xsl:if test="position() =1 , you would just access the first record of the resultset from for-each

    If my understanding of your problem is correct, then the following XSLT shall work for you.

    <?xml version="1.0" encoding="utf-16"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://CallTemplate_Increment.StudentSchema" xmlns:ns0="http://CallTemplate_Increment.DestinationStudentSchema" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
      <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
      <xsl:template match="/">
        <xsl:apply-templates select="/s0:Students" />
      </xsl:template>
      <xsl:template match="/s0:Students">
        <ns0:DestinationDetails>
          <xsl:for-each select="StudentTransactions">
            <xsl:if test="FName='H'">
              <xsl:variable name="var:v104" select="ID"/>
              <xsl:variable name="count" select="0"/>
              
                     
              <xsl:for-each select="/s0:Students/StudentTransactions[FName='D' and ID_Detail=$var:v104]">
                
                <xsl:variable name="Detail_String" select="string(GL_String/text())"/>
                <!--<xsl:if test="$Detail_String!='' and $count=0">-->
                <xsl:if test="position() =1 and $Detail_String!=''" >
                  <xsl:variable name="var:v1" select="userCSharp:StringConcat(string(FName/text()) , string(LName/text()))" />
                  <Details>
                    <ID>
                      <xsl:value-of select="ID/text()" />
                    </ID>
                    <FullName>
                      <xsl:value-of select="$var:v1" />
                    </FullName>
                    <Cost>
                      <xsl:value-of select="Cost/text()" />
                    </Cost>
                  </Details>
                  <!--<xsl:value-of select="$count + 1"/>-->
                </xsl:if>
              </xsl:for-each>
            </xsl:if>
          </xsl:for-each>
        </ns0:DestinationDetails>
      </xsl:template>
      <msxsl:script language="C#" implements-prefix="userCSharp">
        <![CDATA[
    public string StringConcat(string param0, string param1)
    {
       return param0 + param1;
    }
    
    
    
    ]]>
      </msxsl:script>
    </xsl:stylesheet>


    If this answers your question please mark it accordingly. If this post is helpful, please vote as helpful by clicking the upward arrow mark next to my reply.

    • Marked as answer by Shivay_ Monday, December 8, 2014 11:05 AM
    Saturday, December 6, 2014 5:51 PM