Tips and Tricks for handling numbers in BPEL or OIC

 While integrating with multiple systems and moving data from one system to the other, we generally come across scenarios, wherein we need to change the format of the number or perform operations like floor, ceil, round, divide, multiply, add, etc. on numbers. We will be going through various mathematical functions available in XSLT 1.0, which would be helpful in such scenarios, and also some generic errors which we encounter usually.

- Mathematical Operations
  1. Divide
  2. Multiply
  3. Add
  4. Subtract
  5. Square-root
  6. Round
  7. Floor
  8. Ceil
  9. Advanced Number formatting

Mathematical Operations

1. Divide

To divide 2 numbers, we can use the div operator to divide two numbers.
Syntax: 
    $num1 div $num2
Example: 
    Let us assume we want to divide 120 by 7.
XSL:
<divide><xsl:value-of select="120 div 7"/></divide>
Output
<divide>17.14285714285714285714</divide>

2. Multiply

To multiply 2 numbers, we can use the * operator.
Syntax: 
    $num1 * $num2
Example: 
    Let us assume we want to multiply 120 by 7.
XSL:
<multiply><xsl:value-of select="120 * 7"/></multiply>
Output
<multiply>840</multiply>

3. Add

To add 2 numbers, we can use the + operator.
Syntax: 
    $num1 + $num2
Example: 
    Let us assume we want to add 120 and 7.
XSL:
<add><xsl:value-of select="120 + 7"/></add>
Output
<add>127</add>

4. Subtract

To subtract one number from another, we can use the - operator.
Syntax: 
    $num1 $num2
Example: 
    Let us assume we want to subtract 7 from 120.
XSL:
<subtract><xsl:value-of select="120 - 7"/></subtract>
Output
<subtract>113</subtract>

5. Square Root

To find a square root of a number, we can use the oraext:square-root function. 
Syntax: 
    oraext:square-root($number)
Example: 
    Let us assume we want to find a square root of 121.
XSL:
<square-root><xsl:value-of select="oraext:square-root(121)"/></square-root>
Output
<square-root>11</square-root>

6. Round

To round a number to the nearest integer we can use the round($number) function available in XSLT. 
Syntax: 
    round($number)
XSL:
<roundInt><xsl:value-of select="round(17.64285714285714285714)"/></roundInt>
Output
<roundInt>18</roundInt>

What if we want to round the number to 2 or 3 decimal places. Since the round function only takes one argument, we cannot pass the number of decimal digits we want to round the number to. To do so we can try the below-mentioned method.

We can multiply the number by 10m, round the number, and then divide the result by 10m. Here, m denotes the number of decimal places.
Pseudo Code:
    (round($number * 10m) )/ 10m
Example
Let us assume we want to round to two decimal places. Here, the value of m will be 2. 10m will be equal to 100.
XSL:
<roundDec1><xsl:value-of select="round(17.64285714285714285714 * 100 ) div 100"/></roundDec1>
Output
<roundDec1>17.64</roundDec1>

7. Floor

To return the largest integer less than or equal to the number we can use the floor($number) function available in XSLT. 
Syntax: 
    floor($number)
XSL:
<floorInt><xsl:value-of select="floor(17.64285714285714285714)"/></floorInt>
Output
<floorInt>17</floorInt>

What if we want to perform floor operation on the number and have output with 2 or 3 decimal places. Since the floor function only takes one argument, we cannot pass the number of decimal digits we want to floor the number to. To do so we can try the below-mentioned method.

We can multiply the number by 10m, floor the number, and then divide the result by 10m. Here, m denotes the number of decimal places.
Pseudo Code:
    (floor($number * 10m) )/ 10m
Example
Let us assume we want to floor the number to three decimal places. Here, the value of m will be 3. 10m will be equal to 1000.
XSL:
<floorDec1><xsl:value-of select="floor(17.64285714285714285714 * 1000 ) div 1000"/></floorDec1>
Output
<floorDec1>17.642</floorDec1>

8. Ceil

To return the largest integer greater than or equal to the number we can use the ceiling($number) function available in XSLT. 
Syntax: 
    ceiling($number)
XSL:
<ceilInt><xsl:value-of select="ceiling(17.14285714285714285714)"/></ceilInt>
Output
<ceilInt>18</ceilInt>

What if we want to perform ceiling operation on the number and have output with 2 or 3 decimal places. Since the ceiling function only takes one argument, we cannot pass the number of decimal digits we want to ceil the number to. To do so we can try the below-mentioned method.

We can multiply the number by 10m, ceiling the number, and then divide the result by 10m. Here, m denotes the number of decimal places.
Pseudo Code:
    (ceiling($number * 10m) )/ 10m
Example
Let us assume we want to ceiling the number to three decimal places. Here, the value of m will be 3. 10m will be equal to 1000.
XSL:
<ceilDec1><xsl:value-of select="ceiling(17.14285714285714285714 * 1000 ) div 1000"/></ceilDec1>
Output
<ceilDec1>17.143</ceilDec1>

9. Advanced Number formatting

We may come across the scenarios especially when dealing with financial or accounting integrations, wherein we want the numbers like 1234.56, 45 to be formatted like 1,234.56, $45.00, etc. One common way, while developing integration which we opt for, is multiple substrings and then multiple concatenations. There is a built-in function format-number, which can come in really handy in such situations.

Syntax: 
    format-number($number,$format,[$decimal-format])
Note: Here $decimal-format parameter is optional and we have not used it in examples.

Format Character Table
S.No. Character Description
1 0 Representation for digit. For 0 after the decimal and before the number, it is present. For example, the number 1 with the format as '00.0' will give 01.0
2 # Representation for digit. For 0 after the decimal and before the number, it is absent. For example, the number 1 with the format as '##.#' will give 1
3 . Separator for decimal.
4 , Group Separator. Suppose we want to separate thousands, we may use like #,###.##, When 1000 is passed as input, the output becomes 1,000.
5 % Represent number in %
6 ; Separator to define different formats for negative and positive numbers.

Format number performs the round operation by default(which is banker's rounding) to the number of decimal places defined in format. To understand more on how can we use various formats. Please find below the table consisting of various use cases

S.No. Use Case Format Input Number Formatted Number
1 Always having two Decimal digits #.00 123.456
123.4
123.46
123.40
2 Having a maximum of 2 decimal digits #.## 123.456
123
123.46
123
3 Creating a number in Currency Format $#,###,###.00 123456.789 $123,456.79
4 Display number in percentage 0.13245 ##.##% 13.25%
5 Having different formats for positive and negative numbers. #.000;(#.000) 132.45
-132.45
132.450
(132.450)
XSL:
<format1><xsl:value-of select="format-number(123.456, '#.00')"/></format1>
<format1-1><xsl:value-of select="format-number(123.4, '#.00')"/></format1-1>
<format2><xsl:value-of select="format-number(123.456, '#.##')"/></format2>
<format2-1><xsl:value-of select="format-number(123, '#.##')"/></format2-1>
<format3><xsl:value-of select="format-number(123456.789, '$#,###,###.00')"/></format3>
<format4><xsl:value-of select="format-number(0.13245, '##.##%')"/></format4>
<format5><xsl:value-of select="format-number(132.45, '#.000;(#.000)')"/></format5>
<format5-1><xsl:value-of select="format-number(-132.45, '#.000;(#.000)')"/></format5-1>

Output
<format1>123.46</format1>
<format1-1>123.40</format1-1>
<format2>123.46</format2>
<format2-1>123</format2-1>
<format3>$123,456.79</format3>
<format4>13.25%</format4>
<format5>132.450</format5>
<format5-1>(132.450)</format5-1>

Common Errors

  • We get XPath errors when the data type doesn't match the numeric data type.
  • We get NaN(Not a Number) error when we explicitly try to convert a string or any other data type to a number using the number() function and the string contains some invalid characters apart from what is accepted by the number data type.
XSL to explain NaN errors:
<errors>
        <error><xsl:value-of select="number('123 1')"/></error>
        <error><xsl:value-of select="number('abc')"/></error>
        <error><xsl:value-of select="number('123b')"/></error>
</errors>

Resources:

  • XSLT file containing all the XSL statements used in the blog -- Link
  • The output of the above file -- Link

Please share your valuable feedback ๐Ÿ˜Š๐Ÿ˜Š๐Ÿ˜Š


Comments

Popular posts from this blog

DateTime formatting using xp20:format-dateTime ()

Create Delimited String from XML Nodes and Vice Versa in SOA 12c

Import and Export MDS artifacts in SOA 12c