index in loop XSL

2019-03-18 10:19发布

问题:

I have two nested loop in XSL like this, at this moment I use position() but it's not what I need.

<xsl:for-each select="abc">
  <xsl:for-each select="def">
   I wanna my variable in here increasing fluently 1,2,3,4,5.....n
not like 1,2,3,1,2,3
  </xsl:for-each>
</xsl:for-each>

Can you give me some idea for this stub. Thank you very much!

回答1:

With XSL, the problem is you cannot change a variable (it's more like a constant that you're setting). So incrementing a counter variable does not work.

A clumsy workaround to get a sequential count (1,2,3,4,...) would be to call position() to get the "abc" tag iteration, and another call to position() to get the nested "def" tag iteration. You would then need to multiply the "abc" iteration with the number of "def" tags it contains. That's why this is a "clumsy" workaround.

Assuming you have two nested "def" tags, the XSL would look as follows:

<xsl:for-each select="abc">
    <xsl:variable name="level1Count" select="position() - 1"/>
    <xsl:for-each select="def">
        <xsl:variable name="level2Count" select="$level1Count * 2 + position()"/>
        <xsl:value-of select="$level2Count" />
    </xsl:for-each>
</xsl:for-each>


回答2:

Just change the way to select the items to loop over:

<xsl:for-each select="abc/def">
    <xsl:value-of select="position()"/>
</xsl:for-each>

Should you specifically need to keep the nested loops, consider adding yet another loop like this:

<xsl:variable name="items" select="//abc/def"/>
<xsl:for-each select="abc">
    <xsl:for-each select="def">
        <xsl:variable name="id" select="generate-id()"/>
        <xsl:for-each select="$items">
            <xsl:if test="generate-id()=$id">
                 <xsl:value-of select="position()"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</xsl:for-each>


回答3:

<xsl:for-each select="abc">
    <xsl:variable name="i" select="position()"/>
    <xsl:for-each select="def">
        <xsl:value-of select="$i" />
    </xsl:for-each>
</xsl:for-each>


回答4:

This is an extension of pythonquick's answer that handles different numbers of sub-elements:

<xsl:for-each select="abc">  
    <xsl:variable name="level1Position" select="position()"/>
    <xsl:variable name="priorCount" select="count(../abc[position() &lt; $level1Position]/def)"/>  
    <xsl:for-each select="def">
        <xsl:variable name="level2Count" select="$priorCount + position()"/>
        <xsl:value-of select="$level2Count" />
    </xsl:for-each>
</xsl:for-each>

Input:

<root>
    <abc>
        <def>A</def>
        <def>B</def>
        <def>C</def>
    </abc>
    <abc>
        <def>D</def>
        <def>E</def>
    </abc>
    <abc>
        <def>F</def>
    </abc>
    <abc>
        <def>G</def>
        <def>H</def>
        <def>I</def>
    </abc>
</root>


标签: xslt loops