Break from for each loop in xslt

breakfor-loopxslt

I have to break from for-each loop if @PercentOfAmountActive is not equal to 0 or 100.

This is my XML:

<SamplePointSet Id="1" StartDate="2012-01-01T04:00:00Z" CalendarId="1" Cyclic="6" ForAttribute="0" ObjectId="0" ProbabilityFunctionId="0" TableNumber="0" TimePeriodId="4" ParentId="1">
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="100" Sequence="1" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="0" Sequence="2" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="100" Sequence="3" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="0" Sequence="4" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="100" Sequence="5" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="0" Sequence="6" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="100" Sequence="7" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="0" Sequence="8" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="100" Sequence="9" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="0" Sequence="10" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="100" Sequence="11" SamplePointSetId="1" />
    <SamplePoint NumberOfActiveTimePeriods="30" PercentOfAmountActive="0" Sequence="12" SamplePointSetId="1" />
  </SamplePointSet>

Below is xslt code

<xsl:for-each select=".../CM:SamplePointSet/CM:SamplePoint">
  <xsl:variable name="varActiveTimePeriod" select="./@NumberOfActiveTimePeriods * $varMultiple"/>
  <xsl:variable name="varPercentOfAmountActive" select="./@PercentOfAmountActive"/>

  <!-- . . . some Condition To break if (percent of amount active) not 0 or 100 -->

  <xsl:value-of select="CMXsltExtObject:SetRecurenceRule($varActiveTimePeriod, $varPercentOfAmountActive, $varCalendarFrequency)"/>
</xsl:for-each>

Is there any way to do it?

Best Answer

Avoid for-each loops in XSLT. Instead, where possible, apply your nodes to templates, using XPath to target only those nodes that are suitable.

You can achieve the break effect by applying templates only to those nodes...

  • whose @PercentOfAmountActive attribute is equal to 0 or 100
  • none of whose preceding siblings have a @PercentOfAmountActive attribute which is not equal to 0 or 100.

Here's a simplified example, which you can run at this XMLPlayground.

XML

<root>
    <node attr='0'>hello 1</node>
    <node attr='100'>hello 2</node>
    <node attr='0'>hello 3</node>
    <node attr='100'>hello 4</node>
    <node attr='1'>hello 5</node>
    <node attr='0'>hello 6</node>
    <node attr='100'>hello 7</node>
</root>

XSLT

<xsl:template match='/'>
    <ul>
        <xsl:apply-templates select='root/node[(@attr = 0 or @attr = 100) and not(preceding-sibling::*[@attr != 0 and @attr != 100])]' />
    </ul>
</xsl:template>

<xsl:template match='node'>
    <li><xsl:value-of select='.' /></li>
</xsl:template>

Only the first four nodes are output, simulating the 'break' effect once we hit a node that was unsuitable.