简体   繁体   中英

XSLT increment variable in for-each loop not working

My input XML:

<Citizens>
  <Category type="Plumbers">
    <Citizen>John</Citizen>
  </Category>
  <Category type="Doctors">
    <Citizen>Ram</Citizen>
    <Citizen>Kumar</Citizen>
  </Category>
  <Category type="Farmers">
    <Citizen>Ganesh</Citizen>
    <Citizen>Suresh</Citizen>
  </Category>
</Citizens>

I had tried the following XSLT to count Citizen irrelevant of Category

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:variable name="citizenTotal" select="0" />
        <xsl:for-each select="Citizens/Category">
            <xsl:variable name="currentCount" select="count(Citizen)" />
            <xsl:variable name="citizenTotal" select="$citizenTotal+$currentCount" />
        </xsl:for-each>
        Total Citizen nodes: <xsl:value-of select="$citizenTotal"></xsl:value-of>
    </xsl:template>
</xsl:stylesheet>

The expected output is 5 , but it gives 0 which is the initiated value outside for-each . I am missing / messing with <xsl:variable/> for its scope. I just tried what I usually do with JSLT where the scope is page by default. Anything like that in XSLT to mention the scope of variable in XSLT ?

In XSL 1.0 you can't increment a global variable. You can achieve this stuff by

    <xsl:for-each select="Citizens/Category">
        <xsl:if test="position()=last()">
             Total Citizen nodes: <xsl:value-of select="position()"/>
       </xsl:if>
    </xsl:for-each>

However in XSLT 2.0 you can have global variable by having Saxon in name space

<xsl:stylesheet version="2.0" 
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
            xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon"
            exclude-result-prefixes="saxon">

Creating variable

<xsl:variable name="count" saxon:assignable="yes" select="0"/>

Increment

<saxon:assign name="count"><xsl:value-of select="$count+1"/></saxon:assign>

The problem is that variables are immutable in xslt. After setting it is not possible to change it.

So you assign citizenTotal = 0. Although you make another "assignment" of variable with the same name in for-each you are - in fact - declaring a new variable in scope of that cycle of loop. When you exit for-each you are out of the scope of it - you got just the variable you declared before that loop and it is set to zero.

If you need total number of all citizens you could do it without cycle with xpath count(//Citizens/Category/Citizen)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM