Tech Blog

Understanding the BizTalk Mapper: Part 4 – Mathematical Functoids

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:

  1. Whether XSLT or C# is emitted
  2. Whether an XSLT equivalent exists
  3. The XSLT or C# emitted by the functoid
  4. 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

Note:

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?

Download the complete series as a single Microsoft
Word document (1.2MB)
or Adobe
PDF document (620kb)
.

Mathematical Functoids

 

Absolute Value

 

 

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).
 

 

Addition

 

 

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)
+ number) or the sum(number, number, …) function

 

XSLT 2.0 Equivalent: Use the “+” operator e.g. ((number + number)
+ number) or the sum(number, number, …) function

 

 

Division

 

 

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

 

 

Integer

 

 

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’.
 

 

Maximum Value

 

 

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
 

 

Minimum Value

 

 

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
 

 

Modulo

 

 

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

 

 

Multiplication

 

 

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)
* number)

 

XSLT 2.0 Equivalent: Use the “*” operator e.g. ((number * number)
* number)

 

 

Round

 

 

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).
 

 

Square Root

 

 

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.
 

 

Subtraction

 

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. ((numbernumber)
number)

 

XSLT 2.0 Equivalent: Use the “-” operator e.g. ((numbernumber)
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);


}

Back to Tech Blog