XSLT Template - text output file Using in - xslt

Below The sample XSLT Code
<xsl:choose>
<xsl:when test="(TargetBonus >= 0)"><xsl:value-of select="TargetBonus"/></xsl:when>
<xsl:otherwise>Main</xsl:otherwise>
</xsl:choose>
Above logic I am getting Error like:
Cannot convert string "" to double
I am not able to find the exact issue

You have an empty <TargetBonus> element in your input. This will cause the test TargetBonus >= 0 to fail with a type conversion error.
Convert to number explicitly.
<xsl:when test="number(TargetBonus) >= 0]">...</xsl:when>
This will turn any invalid values (including the empty string) into NaN, and then the comparison will be possible. NaN >= 0 will result in false, which probably is what you expect.

Related

Modify date as per matching a attribute name value in XSLT

I have an array of element where a:value element can have different values in it. In case the element contains date in Zulu format i.e.: 2019-04-17T10:42:48.0135859, I need to change it to YYYY-MM-DD format. I have already come up with a solution. However, I am more interested in the matching i:type="b:dateTime" in my condition. Which means if i:type is equal to or contains b:dateTime then the XSLT will fetch the date and do the required transformation.
The input XML is:
<Properties
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
>
<a:KeyValueOfstringanyType>
<a:Key>dtDynamicModifyDate</a:Key>
<a:Value i:type="b:dateTime"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>2019-04-17T10:42:48.0135859</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>tiEnrollmentStatus</a:Key>
<a:Value i:type="b:string"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>Enrolled</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>tiNumberOfEnrollments</a:Key>
<a:Value i:type="b:int"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>1</a:Value>
</a:KeyValueOfstringanyType>
<a:KeyValueOfstringanyType>
<a:Key>dtModifyDate</a:Key>
<a:Value i:type="b:dateTime"
xmlns:b="http://www.w3.org/2001/XMLSchema"
>2019-04-16T15:57:39.331-04:00</a:Value>
</a:KeyValueOfstringanyType>
</Properties>
The transformation is available here: https://xsltfiddle.liberty-development.net/ncdD7mC/1
Instead of this condition, I want the above condition to be checked (i:type is equal to or contains b:dateTime)
<xsl:when test="contains($payload/*[local-name()='Value'], '-') and contains($payload/*[local-name()='Value'], 'T') and contains($payload/*[local-name()='Value'], ':')">
Any pointer for the XPATH will be appreciated.
Cheers,
Sierra
The expression I think you are looking for is this...
<xsl:when test="$payload/*[local-name()='Value']/#*[name()='i:type'] ='b:dateTime'">
However, this would fail if the namespace prefix changed, so perhaps you should do this:
<xsl:when test="$payload/*[local-name()='Value']/#*[local-name()='type'] ='b:dateTime'">
But this could potentially not give you the right results if you had two attributes named type in different namespace. The only real solution is to declare the xmlns:i namespace in the XSLT, then you would do this:
<xsl:when test="$payload/*[local-name()='Value']/#i:type ='b:dateTime'">

xslt check if a variable is a decimal with digits after decimal seperator

I want to show decimal inputs like 100.1, 100.0 in a different format from integer inputs like 100
I have used the following check for identifying decimals(The variable input is of numeric type)
<xsl:when test="not(floor($input) = $input)">
It works for cases like 100.1 but it does not work for cases like 100.00, this would return false saying that this is not a decimal.
I have then tried to use
<xsl:when test="$input castable as xs:decimal">
This is would not work for integers like 100 as the check would return true.
I tried
<xsl:when test="$input instance of xs:decimal">
for which I am getting false for values like 100.50, not sure why.
Is there any other way I can solve this?
If you want to distinguish between 100 and 100.0, you cannot be in the numeric domain. Try perhaps:
<xsl:when test="contains($input, '.')">
or use regex.
You really need to show how you have declared the type of the variable $input (or in the absence of a type declaration, how you have initialized its value). It makes a big difference.
Note that 100.5 as an XPath literal produces the xs:decimal value 100.5, but 100.5 held as the value of an untyped attribute node will be converted to an xs:double value approximately equal to 100.5.
In principle you can identify decimals that are not integers using
$x instance of xs:decimal and not($x instance of xs:integer)
but that assumes that you created the value as an xs:decimal or xs:integer in the first place; if you do xs:decimal("100") then you will probably[*] get an xs:decimal that is not an xs:integer.
[*] I say probably, because the spec requires it to be an xs:decimal, but it arguably permits it to be a subtype of xs:decimal, e.g. it could even return an instance of xs:unsignedByte here if it chose, or for that matter an instance of saxon:integer-in-range-1-to-100, so long as that is defined as a subtype of xs:decimal.]

XML when statement doesn't work

The following is giving me the "memberstable is an unexpected token" error.
<xsl:when value-of memberstable/#member_cancontactthem =1>
<td bgcolor="#ff00ff">
<xsl:value-of select="You can contact this member"/></td>
</xsl:when>
I've used this to initialize it:
<xsl: value of select = "memberstable/#member_cancontactthem" />
The value in the DB is boolean, so either 1 or 0.
Until now, all suggestions will produce errors if I am not mistaken. xsl:when needs a test attribute:
<xsl:when test="memberstable[#member_cancontactthem='1']">
is the correct syntax. Also, xsl:when must be inside an xsl:choose element.
In general, please be careful with whitespace, and with hyphenations (for instance, value of is not the same as value-of) and make sure all attribute values are between quotes. XSLT must respect the rules of XML, which is not as forgiving as HTML.

XSLT Date Comparisons

<xsl:variable name="date1" select="2011-10-05"/>
<xsl:variable name="date2" select="2011-10-05"/>
<xsl:variable name="date3" select="2011-10-06"/>
<xsl:if test="$date2 = $date1 or $date2 < $date1">
..do something
</xsl:if>
<xsl:if test="$date3 = $date1 or $date3 > $date1">
.. do something
</xsl:if>
Both should evaluate true, but the second if doesn't. For the life of me I can't comprehended why!
In the actual transform the dates themselves are being drawn from an XML document but debugging through VS2010 i can see the values are as above.
Must be something fairly fundamental i'm doing wrong - any help would be brilliant!
I tried this in Oxygen/XML... select="2011-10-05 is being interpreted as an arithmetic expression, giving the value 1996 (2011 minus 10 minus 5) and "2011-10-06" is intrepreted as 1995.
What you want is
<xsl:variable name="date1" select="'2011-10-05'"/>
<xsl:variable name="date2" select="'2011-10-05'"/>
<xsl:variable name="date3" select="'2011-10-06'"/>
Note the extra single quotes.
From the XSLT 1.0 Specification:
If the variable-binding element has a select attribute, then the value
of the attribute must be an expression and the value of the variable
is the object that results from evaluating the expression.

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.