aim_thebest
aim_thebest

Reputation: 95

Working on Variable in XSL loop to hold dynamic value

Working on the xsl and i am looking for variable inside a loop to reset on new record.

Fetching records from oracle table

<xsl:variable name="curr_temp_emp_no" select="'##'"/>
<xsl:for-each select="/data/test/loof/super_incompleted">
<xsl:variable name="curr_temp_emp_no2" select="emp_no"/>
<xsl:choose>
<xsl:when test="$curr_temp_emp_no2 != $curr_temp_emp_no">
<xsl:value-of select="emp_no"/><fo:inline> - </fo:inline><xsl:value-of select="variable_desc"/></xsl:when>

<xsl:otherwise>
<xsl:value-of select="variable_desc"/>
</xsl:otherwise>
</xsl:choose>   
<xsl:variable name="curr_temp_emp_no" select="emp_no"/>
</xsl:for-each>

I am trying to compare variable "curr_temp_emp_no" if new value only it prints "emp_no - variable_desc" otherwise(if same emp_no) then print only "variable_desc".

I understood from google that Variables in XSLT are immutable, once we assign them a value, we can't change them.

Refence: Can you simulate a boolean flag in XSLT?

Can anyone please help me over here in writting this logic.

Upvotes: 0

Views: 740

Answers (3)

aim_thebest
aim_thebest

Reputation: 95

Thanks for your reply. I have used the "preceding-sibling::" which solved my problem. Now the code is something like this.

<xsl:for-each select="/data/test/loof/super_incompleted">
<xsl:variable name="curr_temp_emp_no2" select="emp_no"/>
<xsl:choose>
<xsl:when test="$curr_temp_emp_no2 != preceding-sibling::super_incompleted[1]/emp_no">
<xsl:value-of select="emp_no"/><fo:inline> - </fo:inline><xsl:value-of select="variable_desc"/></xsl:when>

<xsl:otherwise>
<xsl:value-of select="variable_desc"/>
</xsl:otherwise>
</xsl:choose>   
<xsl:variable name="curr_temp_emp_no" select="emp_no"/>
</xsl:for-each>

Earlier the table was like this. 1- ABC,1- DFE,1- GFH 2- DFG,2- FGH,2- SDS,2- RTY

Now table looks like this. 1- ABC,DFE,GFH 2- DFG,FGH,SDS

Upvotes: 0

Michael Kay
Michael Kay

Reputation: 163322

You're asking us to reverse engineer your requirements from non-working code, which is always a challenge, but you seem to be carrying over ideas from procedural programming languages which gives us some clues as to what you imagine you want this code to do.

Basically it looks like a "group-adjacent" problem. In XSLT 2.0 you would do

<xsl:for-each-group select="/data/test/loof/super_incompleted" 
                    group-adjacent="emp_no">
  ...
</xsl:for-each-group>

If you're stuck with XSLT 1.0 then the usual approach is to process the sequence of nodes with a recursive named template rather than a for-each instruction: you pass the list of nodes as a parameter to the template, together with the current employee id, and then in the template you process the first node in the list, and call yourself recursively to process the remainder of the list.

@ChristianMosz has expanded this suggestion into working code.

Upvotes: 1

Christian Mosz
Christian Mosz

Reputation: 543

It looks like you want to compare the last two values. I could achieve this by:

<xsl:template match="/">
    <xsl:call-template name="helperTemplate">
        <xsl:with-param name="nodes" select="/data/test/loof/super_incompleted"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="helperTemplate">
    <xsl:param name="nodes"/>
    <xsl:param name="oldVal" select="''"/>

    <xsl:if test="$nodes">
        <xsl:variable name="curr_temp_emp_no" select="$nodes[1]/emp_no"/>
        <xsl:choose>
            <xsl:when test="$curr_temp_emp_no != $oldVal">
                <xsl:value-of select="$curr_temp_emp_no"/>
                <fo:inline> - </fo:inline>
                <xsl:value-of select="$nodes[1]/variable_desc"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$nodes[1]/variable_desc"/>
            </xsl:otherwise>
        </xsl:choose>

        <xsl:call-template name="helperTemplate">
            <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
            <xsl:with-param name="oldVal" select="$nodes[1]/emp_no"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

If you want to have the comparison on all values(if there was no previous element with that content), you can sort them first and use the same code.

Upvotes: 1

Related Questions