Adding of two variables in xslt within choose statement - xslt

<xsl:choose>
<xsl:when test="$cty='LOHNSTD'">
<xsl:variable name="sum" select="$sum + $amt"/>
</xsl:when>
<xsl:when test="$cty='REGPAY'">
<xsl:variable name="sum1">
<xsl:value-of select="$sum1 + $amt"/>
</xsl:variable>
</xsl:when>
</xsl:choose>
In the above code it gives me warning message saying variables sum and sum1 are not declared. amt and cty are parameters being passed to this template. Can any one help me in doing the summation based on different category codes?

As already mentioned, you have two problems with your stylesheet fragment: ussing an undeclare variable reference (xsl:variable name="sum" select="$sum + $amt"), and loosing the variable scope outside the xsl:when.
If you want to declare a variable with value deppending on some conditions, then the answer from Ledhund is the right choise: use xsl:choose inside variable's content template.
Also, if the terms of sum are node sets, you could use this expression:
sum($A|$B[$cty='LOHNSTD']|$C[$cty='REGPAY'])
Or
$A + $B[$cty='LOHNSTD'] + $C[$cty='REGPAY']
If you are trying to chance the value of an already declared variable, then you should refactor your transformation because that's not posible in any declarative paradigm as XSLT.

If you can live without having two sum-variables I'd do it like this
<xsl:variable name="sum">
<xsl:choose>
<xsl:when test="$cty='LOHNSTD'">
<xsl:value-of select="$something + $amt"/>
</xsl:when>
<xsl:when test="$cty='REGPAY'">
<xsl:value-of select="$something_else + $amt"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
However if the main thing is to increase the value of variables depending on some condition, you can't. Variables are fixed.

First, you cannot declare a variable inside a choose construct and use it elsewhere. A variable with no following sibling instructions is useless.
In your example you have two problems, the one mentioned above, and that you're trying to use the variables $sum and $sum1 before they're declared (just as the error message suggests). Essensially, you're trying to calculate a sum using the variable you are declaring.
I'm not sure what you're trying to accomplish, but if you give us some more information regarding the problem I'm sure we can help you with a better solution to it.

Related

XSLT Check if case occured in for-each and use the information

I don't have an approach for this, since I'm not able to change values of variables in XSLT.
Hopefully you could provide a proper approach for the following problem:
This is an example xml-node, to which I'll quote to explain the problem:
<information>
<uselessNode1></uselessNode1>
<uselessNode2></uselessNode2>
<importantNode></importantNode>
</information>
What I essentially need here is to go through all the child nodes of the information node.
The importantNode is optional and the thing what I've to detect is whether this node is there or not.
If the importantNode is there it'll processed within the for-each loop and everything is fine.
In case of not having the importandNode, I've to show it's absence outside of the for-each loop.
So, if having following for-each loop in a template for the information node:
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="not( name() = 'importantNode')">
USELESS
</xsl:when>
<xsl:otherwise>
IMPORTANT
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
The output is "USELESS USELESS IMPORTANT". And if the important node is not there the output is
"USELESS USELESS". What I actually need to have instead of "USELESS USELESS" is a prompt, which shows that the important node is not there, e.g. "USELESS USELESS IMPORTANT_MISSING".
I tried to set a variable in the for-each loop if going in the -case and trying to
check this outside of the for-each loop throws an error, that the variable $importantFound is not declared or out of it's scope. I though declaring it before the for-each loop would help. Since I can't declare the variable before the for-each loop and change it's value in the otherwise case inside of the loop, I don't know how to solve this dilemma.
I hope the explanation of my problem was clear enough to understand.
Thank You all in advance.
In case of not having the importandNode, I've to show it's absence outside of the for-each loop.
So why can't you do exactly that - for example:
<xsl:template match="information">
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="not(self::importantNode)">USELESS </xsl:when>
<xsl:otherwise>IMPORTANT </xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:if test="not(importantNode)">IMPORTANT_MISSING</xsl:if>
</xsl:template>

XPATH: How to use a variable in call-template

I am writing an XSLT to transform an XML: I am not experienced in Xpath, and my XML is too big to post.
But here is my problem:
This code: works fine:
<cac:testmathieu>
<xsl:variable name="lineAmount2" select="body:LineAmount * -1" />
<xsl:value-of select="../body:TaxTrans[body:TaxBaseAmount=$lineAmount2]/body:TaxAmount"/>
</cac:testmathieu>
Then, why is the code below not working, when it's used right below the above code:
<xsl:call-template name ="TaxTotalLine">
<xsl:with-param name="TaxAmount" select="../body:TaxTrans[body:TaxBaseAmount=body:LineAmount*-1]/body:TaxAmount"></xsl:with-param>
</xsl:call-template>
The second piece of code is just a merge of of the code in the first example, or am I mistaken?
I think you want
<xsl:call-template name ="TaxTotalLine">
<xsl:with-param name="TaxAmount" select="../body:TaxTrans[body:TaxBaseAmount = current()/body:LineAmount*-1]/body:TaxAmount"></xsl:with-param>
</xsl:call-template>
to compare the LineAmount of the currently processed node (e.g. any outer template or for-each) to the TaxBaseAmout of the TaxTrans element you have applied the predicate in square brackets to.
thanks for the response.
It was acutally a combination of the "current()" and the brackets.
Much appreciated !
Kind regards
Mathieu

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=""Value True""/>
</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.
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.

How to access global variable value in multiple template tags

I have created a global variable and its been used in two templates I am able to access i first template, not able to get the value in second template . Below are my workings
<xsl:variable name="currentValue"></xsl:variable> //global variable declaration
<xsl:template match="/">
<xsl:variable name="unique-accounts" select="/*/*/*/accountId/text()generate-id()=generate-id(key('account-by-id', .)[1])]"/>
<xsl:for-each select="$unique-accounts">
<xsl:variable name="currentValue" select="current()"/>
<xsl:value-of select="$currentValue"/> //here value is printing
<xsl:apply-templates select="//secondTemplate"/>
</xsl:for-each>
</xsl:template> //close od first template
<xsl:template match="secondTemplate">
<xsl:value-of select="$currentValue"/> //here value is not printing
</xsl:template>
If I follow the logic of your code correctly (which is not at all certain), you have declared a global variable as:
<xsl:variable name="currentValue"></xsl:variable>
i.e. as empty. You are then calling this global variable inside your second template:
<xsl:template match="secondTemplate">
<xsl:value-of select="$currentValue"/>
</xsl:template>
and getting an empty result - which is exactly what you should expect.
Within your first template, the declaration:
<xsl:variable name="currentValue" select="current()"/>
overrides the global variable declaration for the scope of the template (more precisely, for the following siblings of the declaration and their descendants - but since the declaration is the first thing you do in the template, it comes down to the same thing).
In more technical terms, the binding established within the template shadows the binding established by the top-level xsl:variable element:
http://www.w3.org/TR/xslt/#dt-shadows
Variables in XSLT are named values, they are not memory locations in which you can place different values at different times. That's a fundamental difference between declarative and procedural programming.
If you would like to explain the problem you are trying to solve (that is, the input and output of the transformation) then I'm sure we can explain how to write it in XSLT. Reverse-engineering the requirement from a completely wrong approach to the solution isn't possible.

how to get variable data out side of when condition

i declare a variable name as Result1 this variable i have used in when conditions
so that variable i want to used out side of when condition. facing issues as variable name as OUT of scope , to resolve this issue can we declare a global variable as gblresult.
how we can pass result1 content to gblresult, but i dont know how to implement. kindly suggest me some thing
Is this perhaps what you want?
<xsl:variable name="result">
<xsl:choose>
<xsl:when test="...">...</xsl:when>
<xsl:when test="...">...</xsl:when>
...
</xsl:choose>
</xsl:variable>
<!-- use variable result here-->