Mathematics is not a strong point of XSLT. XSLT v1.0 has very poor mathematic support, whilst XSLT v2.0 has better support, but only by a small amount. Therefore most of the functoids in this category can only be implemented in C#.
So if you want to perform a complicated mathematical function (i.e. anything more
than addition or subtraction!) you’re better off using one of these functoids, or
an external assembly.
Once again, inline C# isn’t the fastest, but given a choice between a slow function
and no function, you might not have a choice.
For each functoid I’ve shown:
- Whether XSLT or C# is emitted
- Whether an XSLT equivalent exists
- The XSLT or C# emitted by the functoid
-
Where C# is emitted, the equivalent XSLT to achieve the same functionality (in both
XSLT v1.0 and v2.0)
Functoids covered in this category:
Absolute Value | Modulo |
Addition | Multiplication |
Division | Round |
Integer | Square Root |
Maximum Value | Subtraction |
Minimum Value | Common Code |
This is the fourth in a series of 13 posts about the BizTalk Mapper.
The other posts in this series are (links will become active as the posts become active):
Understanding
the BizTalk Mapper: Part 1 – Introduction
Understanding
the BizTalk Mapper: Part 2 – Functoids Overview
Understanding
the BizTalk Mapper: Part 3 – String Functoids
Understanding the BizTalk Mapper: Part 4 – Mathematical Functoids
Understanding the BizTalk Mapper: Part 5 – Logical Functoids
Understanding the BizTalk Mapper: Part 6 – Date/Time Functoids
Understanding the BizTalk Mapper: Part 7 – Conversion Functoids
Understanding the BizTalk Mapper: Part 8 – Scientific Functoids
Understanding the BizTalk Mapper: Part 9 – Cumulative Functoids
Understanding the BizTalk Mapper: Part 10 – Database Functoids
Understanding the BizTalk Mapper: Part 11 – Advanced Functoids
Understanding the BizTalk Mapper: Part 12 – Performance and Maintainability
Understanding the BizTalk Mapper: Part 13 – Is the Mapper the best choice for Transformation
in BizTalk?
When all of the above have been posted, the entire series will be downloadable as
a single Microsoft Word document, or Adobe PDF file.
Mathematical Functoids |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 2.0 only |
|
Emitted Code: public string MathAbs(string val) { string retval = “”; double d = 0; if (IsNumeric(val, ref d)) { double abs = Math.Abs(d); retval = abs.ToString(System.Globalization.CultureInfo.InvariantCulture); } return retval; } |
||
XSLT 1.0 Equivalent: (none) |
||
XSLT 2.0 Equivalent: abs(number) Note: In XSLT 1.0, you can achieve the desired result through use of an XSLT template and the xsl:when statement (i.e. check if number is < 0). |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 1.0 and 2.0 |
|
Emitted Code: Note: there will be one overload per unique number of parameters. Here we show an example with two input parameters. public string MathAdd(string param0, string param1) { System.Collections.ArrayList listValues = new System.Collections.ArrayList(); listValues.Add(param0); listValues.Add(param1); double ret = 0; foreach (string obj in listValues) { double d = 0; if (IsNumeric(obj, ref d)) { ret += d; } else { return “”; } } return ret.ToString(System.Globalization.CultureInfo.InvariantCulture); } |
||
XSLT 1.0 Equivalent: Use the “+” operator e.g. ((number + number) |
||
XSLT 2.0 Equivalent: Use the “+” operator e.g. ((number + number) |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 1.0 and 2.0 |
|
Emitted Code: Note: there will be one overload per unique number of parameters. Here we show an example with two input parameters. public string MathDivide(string val1, string val2) { string retval = “”; double d1 = 0; double d2 = 0; if (IsNumeric(val1, ref d1) && IsNumeric(val2, ref d2)) { if (d2 != 0) { double ret = d1 / d2; retval = ret.ToString(System.Globalization.CultureInfo.InvariantCulture); } } return retval; } |
||
XSLT 1.0 Equivalent: Use the div operator e.g. number div number |
||
XSLT 2.0 Equivalent: Use the div operator e.g. number div number |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: No |
|
Emitted Code: public string MathInt(string val) { string retval = “”; double d = 0; if (IsNumeric(val, ref d)) { try { int i = Convert.ToInt32(d, System.Globalization.CultureInfo.InvariantCulture); if (i > d) { i = i – 1; } retval = i.ToString(System.Globalization.CultureInfo.InvariantCulture); } catch (Exception) { } } return retval; } |
||
XSLT 1.0 Equivalent: (none) |
||
XSLT 2.0 Equivalent: (none) Note: the floor() function will give an equivalent result e.g. floor(3.90) will give ‘3’. |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 2.0 only |
|
Emitted Code: public string MathMax(string param0, string param1) { double max = Double.NegativeInfinity; System.Collections.ArrayList listValues = new System.Collections.ArrayList(); listValues.Add(param0); listValues.Add(param1); foreach (string obj in listValues) { double d = 0; if (IsNumeric(obj, ref d)) { max = (d >= max) ? d : max; } else { return “”; } } if (Double.NegativeInfinity == max) { return “”; } else { return max.ToString(System.Globalization.CultureInfo.InvariantCulture); } } |
||
XSLT 1.0 Equivalent: (none) |
||
XSLT 2.0 Equivalent: Use the max(number, number, ) function Note: in XSLT 1.0 you could write a fairly complicated XPath statement to achieve this |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 2.0 only |
|
Emitted Code: public string MathMin(string param0, string param1) { double min = Double.PositiveInfinity; System.Collections.ArrayList listValues = new System.Collections.ArrayList(); listValues.Add(param0); listValues.Add(param1); foreach (string obj in listValues) { double d = 0; if (IsNumeric(obj, ref d)) { min = (d < min) ? d : min; } else { return “”; } } if (Double.PositiveInfinity == min) { return “”; } else { return min.ToString(System.Globalization.CultureInfo.InvariantCulture); } } |
||
XSLT 1.0 Equivalent: (none) |
||
XSLT 2.0 Equivalent: Use the min(number, number, ) function Note: in XSLT 1.0 you could write a fairly complicated XPath statement to achieve this |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 1.0 and 2.0 |
|
Emitted Code: public string MathMod(string val, string denominator) { string retval = “”; double v = 0; double d = 0; if (IsNumeric(val, ref v) && IsNumeric(denominator, ref d)) { if (d != 0) { retval = Convert.ToString(v % d, System.Globalization.CultureInfo.InvariantCulture); } } return retval; } |
||
XSLT 1.0 Equivalent: Use the “mod” operator e.g. number mod number |
||
XSLT 2.0 Equivalent: Use the “mod” operator e.g. number mod number |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 1.0 and 2.0 |
|
Emitted Code: Note: there will be one overload per unique number of parameters. Here we show an example with two input parameters. public string MathMultiply(string param0, string param1) { System.Collections.ArrayList listValues = new System.Collections.ArrayList(); listValues.Add(param0); listValues.Add(param1); double ret = 1; bool first = true; foreach (string obj in listValues) { double d = 0; if (IsNumeric(obj, ref d)) { if (first) { first = false; ret = d; } else { ret *= d; } } else { return “”; } } return ret.ToString(System.Globalization.CultureInfo.InvariantCulture); } |
||
XSLT 1.0 Equivalent: Use the “*” operator e.g. ((number * number) |
||
XSLT 2.0 Equivalent: Use the “*” operator e.g. ((number * number) |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: in 1.0 and 2.0 |
|
Emitted Code: public string MathRound(string val) { return MathRound(val, “0”); } public string MathRound(string val, string decimals) { string retval = “”; double v = 0; double db = 0; if (IsNumeric(val, ref v) && IsNumeric(decimals, ref db)) { try { int d = (int)db; double ret = Math.Round(v, d); retval = ret.ToString(System.Globalization.CultureInfo.InvariantCulture); } catch (Exception) { } } return retval; } |
||
XSLT 1.0 Equivalent: round(number) |
||
XSLT 2.0 Equivalent: round(number) Note: the XSLT round() function does not take a second parameter – all number are rounded to 0 decimal places. You can achieve rounding to x dp’s through use of the format-number(number, string) function: e.g. format-number(3.55555, ‘#.00’) – but be aware that rounding in this way might not always give the result you’re looking for e.g. 9.2850 rounds to 9.28 using format-number() (although this can be coded around in XSLT). |
||
|
|
|
Generates: C# |
Has XSLT Equivalent: No |
|
Emitted Code: public string MathSqrt(string val) { string retval = “”; double d = 0; if (IsNumeric(val, ref d)) { if (d >= 0) { double ret = Math.Sqrt(d); retval = ret.ToString(System.Globalization.CultureInfo.InvariantCulture); } } return retval; } |
||
XSLT 1.0 Equivalent: (none) |
||
XSLT 2.0 Equivalent: (none) Note: A square-root can be calculated using an XSLT template – see here for an example. |
||
|
||
Generates: C# |
Has XSLT Equivalent: in 1.0 and 2.0 |
|
Emitted Code: Note: there will be one overload per unique number of parameters. Here we show an example with two input parameters. public string MathSubtract(string param0, string param1) { System.Collections.ArrayList listValues = new System.Collections.ArrayList(); listValues.Add(param0); listValues.Add(param1); double ret = 0; bool first = true; foreach (string obj in listValues) { if (first) { first = false; double d = 0; if (IsNumeric(obj, ref d)) { ret = d; } else { return “”; } } else { double d = 0; if (IsNumeric(obj, ref d)) { ret -= d; } else { return “”; } } } return ret.ToString(System.Globalization.CultureInfo.InvariantCulture); } |
||
XSLT 1.0 Equivalent: Use the “-” operator e.g. ((number – number) |
||
XSLT 2.0 Equivalent: Use the “-” operator e.g. ((number – number) |
||
Common Code (this is common code used by all the mathematical functoids) |
||
public bool IsNumeric(string val) { if (val == null) { return false; } double d = 0; return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d); } public bool IsNumeric(string val, ref double d) { if (val == null) { return false; } return Double.TryParse(val, System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out d); } |