<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.
Related
in a version="2.0" stylesheet:
the following code produces the correct output
<xsl:variable name="obj">
<xsl:choose>
<xsl:when test="t:ReferencedObjectType='Asset'">
<xsl:value-of select="/t:Flow/t:FHeader/t:Producer/t:Repository" />
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:value-of select="$obj"/>
but this one does not
<xsl:variable name="obj">
<xsl:choose>
<xsl:when test="t:ReferencedObjectType='Asset'">
<xsl:value-of select="/t:Flow/t:FHeader/t:Producer" />
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:value-of select="$obj/t:Repository"/>
How can I get the second code to run as expected ?
If needed, is there a solution in v3 ?
this code does not run either
<xsl:variable name="obj">
<xsl:choose>
<xsl:when test="t:ReferencedObjectType='Asset'">
<xsl:copy-of select="/t:Flow/t:FHeader/t:Producer" />
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:value-of select="$obj/t:Repository"/>
relevant xml input
<Flow>
<FHeader>
<Producer>
<Repository>tests.com</Repository>
</Producer>
</FHeader>
</Flow>
You can simply select <xsl:variable name="obj" select="/t:Flow/t:FHeader/t:Producer/t:Repository[current()/t:ReferencedObjectType='Asset']"/>. Or, as Tim already commented, use xsl:copy-of, also taking into account that you then later on need e.g. $obj/t:Producer/t:Repository to select the right level.
Or learn about the as attribute and use e.g. <xsl:variable name="obj" as="element()*">...<xsl:copy-of select="/t:Flow/t:FHeader/t:Producer"/> ...</xsl:variable>, then you later on can use e.g. $obj/t:Repository.
There is also xsl:sequence to select input nodes instead of copying them, in particular with xsl:variable if you use the as attribute. This might consume less memory.
Furthermore XPath 2 and later have if (condition-expression) then expression else expression conditional expressions at the expression level so you might not need XSLT with xsl:choose/xsl:when but could use the <xsl:variable name="obj" select="if (t:ReferencedObjectType='Asset']) then /t:Flow/t:FHeader/t:Producer else if (...) then ... else ()"/>, that way you would select e.g. an input t:Producer element anyway and if you use the variable you can directly select the t:Repository child.
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'"/>.
I have following xml element in the source and would like to map to an element in the target.
Whenever there is no node in the source, I want to default it to a string "None"
--------------------------Source XML----------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<Instructions InstructionType="Gen">Some Message</Instructions>
<Instructions InstructionType="Test">Some Other Message</Instructions>
---------------------------Transformation XSL--------------------------------------
<xsl:if test='/ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions/#InstructionType = "Gen"'>
<xsl:choose>
<xsl:when test='/ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions[#InstructionType = "Gen"] != ""'>
<ns0:siGen>
<xsl:value-of select='substring(/ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions[#InstructionType = "Gen"],1.0,199.0)'/>
</ns0:siGen>
</xsl:when>
<xsl:when test="not(/ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions[#InstructionType = 'Gen'])">
<ns0:siGen>
<xsl:text disable-output-escaping="no">None</xsl:text>
</ns0:siGen>
</xsl:when>
<xsl:otherwise>
<ns0:siGen>
<xsl:text disable-output-escaping="no">None</xsl:text>
</ns0:siGen>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
---------------------------------------------Issue-------------------------------------------------------------
When the source xml doesn't have the the node at all as shown below (commented), I cannot default the value "None" to the target element "ns0:siGen"
<!--Instructions InstructionType="Gen">Some Message</Instructions-->
<Instructions InstructionType="Test">Some Other Message</Instructions>
I dont understand why the below condition is not working:
<xsl:when test="not(/ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions[#InstructionType = 'Gen'])">
Please advise.
Thanks
Yogi
The very first line in your XSLT sample says this...
<xsl:if
test='/ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions/#InstructionType = "Gen"'>
i.e. You are testing if there is an Instructions element which has an InstructionType equal to "Gen". So, obviously if you comment this Instructions element, the statement will be false, and so your xsl:choose inside the statement will not be executed.
To simplify things, consider putting the instructions element in a variable
<xsl:variable name="gen"
select="ns1:OrderResponse/ns1:OrderResponseBody/ns1:OrderResponseProperties/ns1:Instructions[#InstructionType = 'Gen']" />
Then you can have a simple xsl:choose to test this
<ns0:siGen>
<xsl:choose>
<xsl:when test="$gen != ''"><xsl:value-of select="$gen" /></xsl:when>
<xsl:otherwise>None</xsl:otherwise>
</xsl:choose>
<ns0:siGen>
I want to assign multiple variables depending on one condition environment. I know how to do that for only one variable:
<xsl:variable name="foo">
<xsl:choose>
<xsl:when test="$someCondition">
<xsl:value-of select="3"/>
<xsl:when>
<xsl:otherwise>
<xsl:value-of select="4711"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
But what if I want to assign two variables depending on the same condition $someCondition?
I don't want to write the same xsl:choose statement again, because it is somewhat lengthy and computation intensive in the real example.
The environment in question is libxslt (xslt 1.0) with exslt extensions.
EDIT: What i want is a behaviour similar to
if (condition) {
foo = 1;
bar = "Fred";
}
else if (...) {
foo = 12;
bar = "ASDD";
}
(... more else ifs...)
else {
foo = ...;
bar = "...";
}
What you could is have your main variable return a list of elements; one for each variable you want to set
<xsl:variable name="all">
<xsl:choose>
<xsl:when test="a = 1">
<a>
<xsl:value-of select="1"/>
</a>
<b>
<xsl:value-of select="2"/>
</b>
</xsl:when>
<xsl:otherwise>
<a>
<xsl:value-of select="3"/>
</a>
<b>
<xsl:value-of select="4"/>
</b>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Then, using the exslt function, you can convert this to a 'node set' which can then be used to set your individual variables
<xsl:variable name="a" select="exsl:node-set($all)/a"/>
<xsl:variable name="b" select="exsl:node-set($all)/b"/>
Don't forget you'll need to declare the namepsace for the exslt functions in the XSLT for this to work.
But what if I want to assign two variables depending on the same
condition $someCondition?
I don't want to write the same xsl:choose statement again, because it
is somewhat lengthy and computation intensive in the real example.
Assuming the values of the variables are not nodes, this code doesn't use any extension function to define them:
<xsl:variable name=vAllVars>
<xsl:choose>
<xsl:when test="$someCondition">
<xsl:value-of select="1|Fred"/>
<xsl:when>
<xsl:when test="$someCondition2">
<xsl:value-of select="12|ASDD"/>
<xsl:when>
<xsl:otherwise>
<xsl:value-of select="4711|PQR" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="foo" select="substring-before($vAllVars, '|')"/>
<xsl:variable name="bar" select="substring-after($vAllVars, '|')"/>
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