Reputation: 79
I have this xml file:
<pas>
<rulepar>
<name1>Hi</name1>
<name2></name2>
<type>DOUBLE</type>
<oper>HIGH</oper>
<val1>103619.9</val1>
<bId>2</bId>
</rulepar>
<rulepar>
<name1>Hi</name1>
<name2></name2>
<type>Text</type>
<oper>LOW</oper>
<sumval1>-103.67</sumval1>
<bId>3</bId>
</rulepar>
</pas><rulepar>
<name1>Hi</name1>
<name2></name2>
<type>Text</type>
<oper>LOW</oper>
<val1>10</val1>
<bId>3</bId>
</rulepar>
</pas>
with this xsl file:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" xml:space="preserve"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="val1|sumval1">
<val111><xsl:value-of select="."/></val111>
</xsl:template>
when I make my transformation, I have this as result:
<pas>
<rulepar>
<name1>Hi</name1>
<name2></name2>
<type>DOUBLE</type>
<oper>HIGH</oper>
<val111>103619.9</val111>
<bId>2</bId>
</rulepar>
<rulepar>
<name1>Hi</name1>
<name2></name2>
<type>Text</type>
<oper>LOW</oper>
<val111>-103.67</val111>
<bId>3</bId>
</rulepar>
</pas><rulepar>
<name1>Hi</name1>
<name2></name2>
<type>Text</type>
<oper>LOW</oper>
<val111>10</val111>
<bId>3</bId>
</rulepar>
</pas>
I expected normally this output:
<pas>
<rulepar>
<name1>Hi</name1>
<name2></name2>
<type>DOUBLE</type>
<oper>HIGH</oper>
<val111>103619</val111>
<bId>2</bId>
</rulepar>
<rulepar>
<name1>Hi</name1>
<name2></name2>
<type>Text</type>
<oper>LOW</oper>
<val111>-103</val111>
<bId>3</bId>
</rulepar>
</pas><rulepar>
<name1>Hi</name1>
<name2></name2>
<type>Text</type>
<oper>LOW</oper>
<val111>10</val111>
<bId>3</bId>
</rulepar>
</pas>
So, how can I do to get only the integer part of the number 103619.9 in the result as shown in the expected output file? I want a solution that can be walk also when the number is only a decimal number and also if this number is <0. Thanks for your help.
Upvotes: 2
Views: 7183
Reputation: 243579
This XPath 1.0 expression gets you the integer part of the number -- regardless if the number is positive or negative:
floor(.)*(. >= 0) + ceiling(.) * not(. >= 0)
Explanation:
In case the number is positive we use the floor()
function.
In case the number is negative we use the ceiling()
function.
We combine the two functions (above) using the fact that number(true()) = 1
and number(false()) = 0
Here is a complete example:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="text()">
<xsl:value-of select="floor(.)*(. >= 0) + ceiling(.) * not(. >= 0)"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<t>
<a>2.34</a>
<b>-3.14</b>
</t>
the wanted, correct result is produced:
2
-3
Upvotes: 5
Reputation: 900
Try this
<value111><xsl:value-of select="floor(number(.))"/></value111>
Upvotes: 1
Reputation: 43823
The XPath floor()
function which
evaluates a decimal number and returns the largest integer less than or equal to the decimal number
will work if the values are all positive and the XPath would look like
<value111><xsl:value-of select="floor(number(.))"/></value111>
However, it will not work if the value is -2.1
for example, as the above code would result in -3
.
If there is a possibility that a value will be negative then using the substring-before()
function will work for both positive and negative numbers iff there is only one decimal point.
<value111><xsl:value-of select="substring-before(., '.')"/></value111>
Note: not sure if the question has a typo but the matching pattern for one of the templates is incorrect. It should be
<xsl:template match="val1|sumval1">
instead of
<xsl:template match="value1|sumval1">
Upvotes: 2