assigning the value to a variable through xsl - xslt

I am stuck up in an odd situation I have an variable named PaymentabcflowsVar as shown below
<xsl:with-param name="PaymentabcflowsVar" select="$RBC_CDSERStream_Obj/CTM_PaymentPeriod"/>
and I am fetching the value at some logic as shown below..
<xsl:value-of select="$TTeturnVar/onal/onalAmount/amount" />
now I want to assign this value to the above variable named PaymentabcflowsVar such as
PaymentabcflowsVar = <xsl:value-of select="$TTeturnVar/onal/onalAmount/amount" />
please advise how to achieve this..!!
well now what I have done is that i have assign the value a variable temporarily
<xsl:variable name="holodingtnalamount"><xsl:value-of select="$TTeturnVar/onal/onalAmount/amount" />
now please advise can I assign the variable holodingtnalamount value to PaymentabcflowsVar

A few matters of apparent confusion require clarification:
(1) Here's how to assign the value to a variable:
<xsl:variable name="PaymentabcflowsVar"
select="$TTeturnVar/onal/onalAmount/amount"/>
(2) A variable can only be assigned a value once. Explanation here.
(3) xsl:with-param is for use in passing parameters to named templates.

Related

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.

Declare a empty variable

I wrote :-
<xsl:variable name="cAddress" select=""></xsl:variable>
I don't want to assign any value here, I want to assign later. Is this possible?
No it is not possible. In XSLT, variables are immutable. You cannot assign - or reassign - a value to an existing variable. Technically, you can declare an empty variable as:
<xsl:variable name="myVar"/>
but you won't be able to do anything with it later.
If you want to pass a parameter to a stylesheet or to a template at runtime, use:
<xsl:param name="cAddress"/>
or:
<xsl:param name="cAddress" select="'default value'"/>

In XSLT, why do I need to do comparisons with variables instead of with attribute values (in a test expression)

I am parsing a document, with different behavior depending on whether the id attribute is an element of a collection of values ($item-ids in the code below). My question is, why do I need to assign a variable and then compare with that value, like this:
<xsl:template match="word/item">
<xsl:variable name="id" select="#abg:id"/>
<xsl:if test="$item-ids[.=$id]">
<xsl:message>It matches!</xsl:message>
</xsl:if>
</xsl:template>
It seems to be that I should be able to do it like this, though it doesn't work:
<xsl:template match="word/item">
<xsl:if test="$item-ids[.=#abg:id]">
<xsl:message>It matches!</xsl:message>
</xsl:if>
</xsl:template>
This is something I keep forgetting and having to relearn. Can anybody explain why it works this way? Thanks.
To understand XPath, you need to understand the concept of the context node. An expression like #id is selecting an attribute of the context node. And the context node changes inside square brackets.
You don't have to use a variable in this case. Here you can use:
<xsl:template match="word/item">
<xsl:if test="$item-ids[. = current()/#abg:id]">
<xsl:message>It matches!</xsl:message>
</xsl:if>
</xsl:template>
The reason you can't just use $item-ids[. = #abg:id] is that inside the [], you are in the context of whatever is right before the [] (in this case $item-ids), so #abg:id would be treated as $item-ids/#abg:id, which isn't what you want.
current() refers to the current context outside of the <xsl:if> so current()/#abg:id should reflect you the value you want.
I think it's because the line
<xsl:if test="$item-ids[.=#abg:id]">
compares the value of $item-ids to the string '#abg:id' - you need to compare it to the value of #abg:id which is why you need to select that value into the $id variable for the test to work.
Does that help at all?
Edit: I've misunderstood the issue - the other answers are better than mine.

How to know variable has value or not in XSLT

I am creating XSLT file.
I have one variable which take value from XML file.But it may happen that there is no reference in xml for the value and at that time XSL variable will return False/None(don't know).I want keep condition like,If there is no value for the variable use the default one.
How to do that ?
With the few details given in the question, the simplest test you can do is:
<xsl:if test="$var">
...
</xsl:if>
Or you might use xsl:choose if you want to provide output for the else-case:
<xsl:choose>
<xsl:when test="not($var)"> <!-- parameter has not been supplied -->
</xsl:when>
<xsl:otherwise> <!--parameter has been supplied --> </xsl:otherwise>
</xsl:choose>
The second example will also handle the case correctly that the variable or parameter has not been supplied with an actual value, i.e. it equals the empty string. This works because not('') returns true.
You haven't explained what you mean by "has no value". Here is a generic solution:
not($v) and not(string($v))
This expression evaluates to true() iff $v "has no value".
Both conditions need to be met, because a string $v defined as '0' has a value, but not($v) is true().
In XSLT 1.0 using a default can be achieved in different ways if the "value" is a node-set or if the value is a scalar (such as a string, a number or a boolean).
#Alejandro provided one way to get a default value if a variable that is supposed to contain a node-set is empty.
If the variable is supposed to contain a scalar, then the following expression returns its value (if it has a value) or (otherwise) the desired default:
concat($v, substring($default, 1 div (not($v) and not(string($v)))))
You can use string-length to check, if a variable called $reference for example contains anything.
<xsl:choose>
<xsl:when test="string-length($reference) > 0">
<xsl:value-of select="$reference" />
</xsl:when>
<xsl:otherwise>
<xsl:text>some default value</xsl:text>
</xsl:otherwise>
</xsl:choose>
If necessary use normalize-space, too.
First, all variables has values, because XSLT belongs to declarative paradigm: there is no asignation instruction, but when you declare the variable you are also declaring the expression for its value relationship.
If this value it's a node set data type (that looks from your question), then you should test for an empty node set in case nothing was selected. The efective boolean value for an empty node set is false. So, as #0xA3 has answered: test="$node-set".
You wrote:
If there is no value for the variable
use the default one. How to do that ?
Well, that depends on what kind of data type you are looking for.
Suppose the node set data type: if you want $node-set-1 value or $node-set-2 if $node-set-1 is empty, then use:
$node-set-1|$node-set-2[not($node-set-1)]
I tried a lot of solution from SO, my last solution was taken from #dimitre-novatchev, but that one also not working every time. Recently I found one more solution from random google search, thought to share with the community.
In order to check empty variable value, we can declare an empty variable and compare its value against test condition. Here is code snippet:
<xsl:variable name="empty_string"/>
<xsl:if test="testVariableValue != $empty_string">
...
</xsl:if>
Here testVariableValue hold the value of new variable to be tested for empty
scenario.
Hope it would help to test empty variable state.

xsl:call-template: return a number rather than text to be assigned to a variable

I'm having a (minor) problem here. I'm calling a named template and am assigning the outcome to a variable. So for so good, but I need the type of the processed template's return value to be integer rather than text.
I wonder if there's a way to achieve that without having to go with a temporary variable?
Here's some sample code:
<xsl:variable name="tmp">
<xsl:call-template name="mytemplate">
<xsl:with-param name="x" select="123"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="myvar" select="number($tmp)"/>
<xsl:template name="mytemplate">
<xsl:param name="x"/>
<xsl:value-of select="$x"/>
</xsl:template>
Don't mind the code as it is an oversimplification of what my template does. Notice also that I've tried to return <xsl:value-of select="number($x)"/> but to no avail.
Any help is heavily appreciated.
TIA
First, $tmp data type is Result Tree Fragment. So, besides copying, in all allowed operations with $tmp, only counts its string value.
XPath have many rules for implicit casting. In general, whenever an operator or function takes a number data type as argument, the expression will be cast to number with number() function.
Bottom line: in mostly every case you don't need that explicit casting.
As #Alejandro points out, you don't need explicit casting to number.
If you intend to use this not as a number, but to use the number-representation as an intermediate type, then you do need the cast, because the RTF that is in the $tmp variable may not be directly convertible to that type as wanted.
Example:
You need:
boolean(number($tmp))
to convert an RTF or any tree to a boolean tat can have two different values.
boolean(someNode)
is always true() -- by definition.