A. Shah
A. Shah

Reputation: 37

Looping through an xpath getting the right iteration each time in xslt 2

I have a condition where I need to loop atleast once and so I have the following xsl code. However, this doesnt work as it always gets the last iterations value. How can I tweak this so it gets the right iteration on each loop?

 <xsl:variable name='count0'>
    <xsl:choose>
    <xsl:when test='count($_BoolCheck/BoolCheck[1]/CheckBoolType) = 0'>
      <xsl:value-of select="1"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select='count($_BoolCheck/BoolCheck[1]/CheckBoolType)'/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:for-each select="1 to $count0">
  <xsl:variable name='_LoopVar_2_0' select='$_BoolCheck/BoolCheck[1]/CheckBoolType[position()=$count0]'/>
  <e>
    <xsl:attribute name="n">ValueIsTrue</xsl:attribute>
    <xsl:attribute name="m">f</xsl:attribute>
    <xsl:attribute name="d">f</xsl:attribute>
    <xsl:if test="(ctvf:isTrue($_LoopVar_2_0/CheckBoolType[1]))">
      <xsl:value-of select="&quot;Value True&quot;"/>
    </xsl:if>
  </e>
</xsl:for-each>

The xml file is as follows:

<BoolCheck>
<CheckBoolType>true</CheckBoolType>
<CheckBoolType>false</CheckBoolType>
<CheckBoolType>1</CheckBoolType>
<CheckBoolType>0</CheckBoolType>
<CheckBoolType>True</CheckBoolType>
<CheckBoolType>False</CheckBoolType>
<CheckBoolType>TRUE</CheckBoolType>
<CheckBoolType>FALSE</CheckBoolType>
</BoolCheck>

In this case I need to iterate through each iteration of CheckBoolType and produce a corresponding number of values. However, in the above example if there were no CheckBoolType iterations I would still like the iterations to enter the for-each loop atleast once. i hope that clarifies it a little more.

Upvotes: 0

Views: 1148

Answers (1)

Michael Kay
Michael Kay

Reputation: 163625

First observation: your declaration of $count0 can be replaced by

<xsl:variable name="temp" select="count($_BoolCheck/BoolCheck[1]/CheckBoolType)"/>
<xsl:variable name="count0" select="if ($temp=0) then 1 else $temp"/>

(Sorry if that seems irrelevant, but my first step in debugging code is always to simplify it. It makes the bugs much easier to find).

When you do this you can safely replace the predicate [position()=$count0] by [$count0], because $count0 is now an integer rather than a document node. (Even better, declare it as an integer using as='xs:integer' on the xsl:variable declaration.)

But hang on, $count0 is the number of elements being processed, so CheckBoolType[$count] will always select the last one. That's surely not what you want.

This brings us to another bug in your code. The value of the variable $_LoopVar_2_0 is an element node named CheckBoolType. The expression $_LoopVar_2_0/CheckBoolType[1] is looking for children of this element that are also named CheckBoolType. There are no such children, so the expression selects an empty sequence, so the boolean test is always false.

At this stage I would like to show you some correct code to achieve your desired output. Unfortunately you haven't shown us the desired output. I can't reverse engineer the requirement from (a) your incorrect code, and (b) your prose description of the algorithm you are trying to implement.

Upvotes: 0

Related Questions