Setting a value in a variable on if conditions using XSL - xslt

I have a basic condition that checks if a variable is empty and if it is set the variable to a specific value like so.
<xsl:variable name="PIC" select="avatar"/>
<xsl:choose>
<xsl:when test="avatar !=''">
<xsl:variable name="PIC" select="avatar"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="PIC" select="'placeholder.jpg'"/>
</xsl:otherwise>
</xsl:choose>
Basically var PIC is set to whatever avatar returns. Then a test is carried to check if if it's not empty and assigned to var PIC and if it is empty a value placeholder.jpg is added to var PIC instead.
Now for some reason I keep getting the following warning
A variable with no following sibling instructions has no effect
Any ideas on what I am doing wrong here?

Variables are immutable in XSLT, and cannot be changed once set. The variable declarations in the xsl:choose are simply new declarations that at local in scope to the current block. (They are said to "shadow" the initial variable).
What you need to do is this...
<xsl:variable name="PIC">
<xsl:choose>
<xsl:when test="avatar !=''">
<xsl:value-of select="avatar"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'placeholder.jpg'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>

Use a single xsl:variable as <xsl:variable name="PIC" select="if (avatar != '') then avatar else 'placeholder.jpg'"/>.

Related

Xslt get value of created xml element

<xsl:when test="conditon = 'value1'">
<typeId>4</typeId>
</xsl:when>
<xsl:when test="conditon = 'value2'">
<typeId>4</typeId>
</xsl:when>
<xsl:when test="conditon = 'value3'">
<typeId>4</typeId>
</xsl:when>
....
....
I have something like above.
Now I want to check condition on created xml tag (typeId).
i.e, below condition in xslt file,
<xsl:if test="$typeId = 4">
<price>100</price>
</xsl:if>
So, how can I use above condition on created tag (above typeId is created tag on which I want to make condition)
Or any other way to achieve as above?
$typeId refers to a variable named typeId, and not to any element you have created.
What you can do, is define a variable called typeId that is set to just the value you want, and use that variable to create the element, and to check in your condition.
<xsl:variable name="typeId">
<xsl:choose>
<xsl:when test="conditon = 'value1'">1</xsl:when>
<xsl:when test="conditon = 'value2'">2</xsl:when>
<xsl:when test="conditon = 'value4'">4</xsl:when>
<xsl:choose>
</xsl:variable>
<typeId>
<xsl:value-of select="$typeId" />
</typeId>
<xsl:if test="$typeId = 4">
<price>100</price>
</xsl:if>
Do note that this code would have to be in the same block of code, as the typeId variable will be local in scope to that block.

Accessing a variable outside the for loop in xsl

I am setting a variable as shown below..
<xsl:variable name="FoundFloating"> <xsl:value-of select="'no'" />
</xsl:variable>
Now I am doing some processing as shown below ..
<xsl:if test="$abcid=$def_id">
<xsl:for-each "$abcd">
<xsl:variable name="abcRate"> <xsl:value-of select="./def_Period/"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$abcdf !=$abcRate">
<xsl:variable name="$FoundFloating"> <xsl:value-of select="yes" />
</xsl:variable>
</xsl:when>
</xsl:choose>
</xsl:for-each>
Now after this xsl for I am evaluating as shown below.. But my query is that whether foundfloating variable is accessible as the for loop is already ended..
<xsl:choose>
<xsl:when test="$FoundFloating='yes'"> <xsl:value-of select="'AAA'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'BBBA'" />
</xsl:otherwise>
</xsl:choose>
Now after this xsl for I am evaluating as shown below.. But my query is that whether foundfloating variable is accessible as the for loop is already ended..
Please advise on this as I have updated the post
The first thing to note is that variables are immutable in XSLT. This means once declared, they cannot be changed. What is actually happening in your XSLT sample is you are declaring a whole new variable, with the same name.
The FoundFloating variable you are declaring within the for loop will not be accessible outside the for loop, as it will only be local in scope. In fact, it will only be accessible inside the xsl:when statement it is defined in. It is a different variable to the global one you defined, and only exists in the loop.
You don't really need the loop here. You can combine the condition in the xsl:for-each and the condition in the xsl:when into a single variable declaration.
<xsl:if test="$abcid=$def_id">
<xsl:variable name="FoundFloating">
<xsl:if test="$abcd[def_Period != $abcdf]">yes</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="$FoundFloating='yes'">
(This replaces the xsl:for-each statement entirely)
In fact, this can be simplified even more, by simply setting FoundFloating to the node itself (if there is one), rather than "yes"
<xsl:if test="$abcid=$def_id">
<xsl:variable name="FoundFloating" select="$abcd[def_Period != $abcdf]" />
<xsl:choose>
<xsl:when test="$FoundFloating">
This works because the essence of the test is whether a certain node exists matching the condition. Rather than setting a variable to "Yes" or "No" if it exists or not, the variable is set to the node itself. Then, if it does the exist the statement <xsl:when test="$FoundFloating"> returns true, but false if it doesn't.
So, you don't need the xsl:for-each loop, and you only need to declare the FoundFloating variable once.

XSL variable assignment

I have another simple xsl variable question. I'm trying to evaluate an expression and toggle an 'AM' or 'PM' suffix. The variable never evaluates to anything. I've even changed my test to with no luck.
<xsl:variable name="DisplayAMPM">
<xsl:choose>
<xsl:when test="number(substring($LastBootUpTime, 9,2))>11">
<xsl:value-of select="PM"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="AM"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:copy-of select="DisplayAMPM"/>
If you use value-of, put the "AM" and "PM" in quotes so that the processor sees it as a string.
Also, if you reference the variable, like you're trying to do in the copy-of, don't forget the $.
<xsl:variable name="DisplayAMPM">
<xsl:choose>
<xsl:when test="number(substring($LastBootUpTime, 9,2))>11">
<xsl:value-of select="'PM'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'AM'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:copy-of select="$DisplayAMPM"/>
You have a runaway > character in your test attribute which should of course be >.
Secondly, you don't copy your variable ($DisplayAMPM), instead you copy the (nonexistent?) DisplayAMPM element child node set.

How do we change the value of a variable based on another variable?

I have two variables named editable and display.
If the value of editable is true, I want to set the value of display to 'block'.
If the value of editable is false, I want to set the value of display to 'none'.
This is what I have currently:
<xsl:param name="editable" select="true()"/>
<xsl:choose>
<xsl:when test="$editable">
<xsl:variable name="display" select="'block'"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="display" select="'none'"/>
</xsl:otherwise>
</xsl:choose>
The code above doesn't set the value of display to none.
How do we change the value of a variable based on another variable?
I did not test this, but for me it looks like a problem of scope which might be solved this way:
<xsl:param name="editable" select="true()"/>
<xsl:variable name="display">
<xsl:choose>
<xsl:when test="$editable">
<xsl:value-of select="'block'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'none'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>

XSl:Variable - Condition to check whether value exist

Using XSLT 1.0, how do I check whether the value in the variable exists or not?
I am assigning the value to the variable initially from my XML data and then need to check whether it exits or not:
<xsl:variable name="DOC_TYPE">
<xsl:value-of select="name(./RootTag/*[1])"/>
</xsl:variable>
<xsl:if test="string($DOC_TYPE) = ''">
<xsl:variable name="DOC_TYPE">
<xsl:value-of select="name(./*[1])"/>
</xsl:variable>
</xsl:if>
The above is not working as expected. What I need is if <RootTag> exists in my data then the variable should contain the child node below the <RootTag>. If <RootTag> does not exist then the DOC_TYPE should be the first Tag in my XML data.
Thanks for your response.
You can't re-assign variables in XSLT. Variables a immutable, you can't change their value. Ever.
This means you must decide within the variable declaration what value it is going to have:
<xsl:variable name="DOC_TYPE">
<xsl:choose>
<xsl:when test="RootTag">
<xsl:value-of select="name(RootTag/*[1])" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="name(*[1])" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
A few other notes:
this: './RootTag' is redundant. Every XPath you don't start with a slash is relative by default, so saying 'RootTag' is enough
this: <xsl:value-of select="name(*[1])"/> already results in a string (names are strings by definition), so there is no need to do <xsl:if test="string($DOC_TYPE) = ''"> , a simple <xsl:if test="$DOC_TYPE = ''"> suffices
to check if a node exists simply select it via XPath in a test="..." expression - any non-empty node-set evaluates to true
XSLT has strict scoping rules. Variables are valid within their parent elements only. Your second variable (the one within the <xsl:if>) would go out of scope immediately(meaning right at the </xsl:if>).
Try this
<xsl:variable name="DOC_TYPE">
<xsl:choose>
<xsl:when test="/RootTag"><xsl:value-of select="name(/RootTag/*[1])"></xsl:value-of></xsl:when>
<xsl:otherwise><xsl:value-of select="name(/*[1])"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
It only exists if you have assigned it. There's no reason to test it for existence.
See also here