Tech Blog

Understanding the BizTalk Mapper: Part 9 – Cumulative Functoids

Of the functoids in this category, only Cumulative Sum has a counterpart in
XSLT v1.0 – all the others can be performed in XSLT v2.0, but not XSLT v1.0.

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:

Cumulative Average Cumulative Minimum
Cumulative Concatenate Cumulative Sum
Cumulative Maximum Common Code

Note:

This is the ninth 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)
.

Cumulative Functoids

Note:
All of the cumulative functoids work in the same way.


They each emit three calls to each of the three
C# methods.


For example, the Cumulative Concatenate functoid
emits the following:

<xsl:variable name=”var:v1 select=”userC#:InitCumulativeConcat(0)
/>


<xsl:for-each
select
=”/ns0:Employees/Employee“>

  <xsl:variable name=”var:v2 select=”userC#:AddToCumulativeConcat(0,string(@name),”1000″)
/>


</xsl:for-each>

<xsl:variable name=”var:v3 select=”userC#:GetCumulativeConcat(0)
/>


<xsl:attribute
name
=”name“>

  <xsl:value-of select=”$var:v3
/>


</xsl:attribute>

 

There’s an initialise call, followed by a loop
over a given element/attribute (which a call to the Add method) and then a final call
to get the cumulative result.


 

The first parameter to each of the methods (0
in the above example) is the index of this type of functoid in the map e.g. the second
occurrence of the Cumulative Concatenate functoid would use 1 etc.

 

Cumulative
Average

 

 

Generates: C#

Has XSLT Equivalent: in 2.0 only

  Emitted Code:

public string InitCumulativeAvg(int index)

{

    if (index
>= 0)


    {

        if (index
>= myCumulativeAvgArray.Count)


       
{


            int i
= myCumulativeAvgArray.Count;


            for (;
i <= index; i++)


           
{


               
myCumulativeAvgArray.Add(“”);


               
myCumulativeAvgCountArray.Add(0);


           
}


       
}


        else

       
{


           
myCumulativeAvgArray[index] = “”;


           
myCumulativeAvgCountArray[index] = 0;


       
}


    }

    return “”;

}

 

private System.Collections.ArrayList myCumulativeAvgArray
= new System.Collections.ArrayList();


private System.Collections.ArrayList myCumulativeAvgCountArray
= new System.Collections.ArrayList();


 

public string AddToCumulativeAvg(int index, string val, string notused)

{

    if (index
< 0 || index >= myCumulativeAvgArray.Count)


    {

        return “”;

    }

    double d
= 0;


    if (IsNumeric(val, ref d))

    {

        if (myCumulativeAvgArray[index]
== “”)


       
{


           
myCumulativeAvgArray[index] = d;


       
}


        else

       
{


           
myCumulativeAvgArray[index] = (double)(myCumulativeAvgArray[index])
+ d;


       
}


    }

    myCumulativeAvgCountArray[index]
= (int)(myCumulativeAvgCountArray[index]) + 1;


    return (myCumulativeAvgArray[index] is double)
? ((double)myCumulativeAvgArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}

 

public string GetCumulativeAvg(int index)

{

    if (index
< 0 || index >= myCumulativeAvgArray.Count)


    {

        return “”;

    }

    if ((int)(myCumulativeAvgCountArray[index])
== 0 || myCumulativeAvgArray[index] == “”)


    {

        return “”;

    }

    else

    {

        double numer
= (double)(myCumulativeAvgArray[index]);


        double denom
= Convert.ToDouble((int)(myCumulativeAvgCountArray[index]),
System.Globalization.CultureInfo.InvariantCulture);


        double d
= numer / denom;


        return d.ToString(System.Globalization.CultureInfo.InvariantCulture);

    }

}
 

XSLT 1.0 Equivalent: (none)

  XSLT 2.0 Equivalent: avg(node-set) or avg(value, value, value,
…) e.g.
avg(/*[local-name()=’number’
and namespace-uri()=”])


Note: In XSLT 1.0 you can use the Sum() and Count() functions along with
the div operator to calculate an average:

sum(/*[local-name()=’number’
and namespace-uri()=”]) div count(/*[local-name()=’number’ and namespace-uri()=”])
 

 

Cumulative Concatenate

 

 

Generates: C#

Has XSLT Equivalent: in 2.0 only

  Emitted Code:

public string InitCumulativeConcat(int index)

{

    if (index
>= 0)


    {

        if (index
>= myCumulativeConcatArray.Count)


       
{


            int i
= myCumulativeConcatArray.Count;


            for (;
i <= index; i++)


           
{


               
myCumulativeConcatArray.Add(“”);


            }

       
}


        else

       
{


           
myCumulativeConcatArray[index] = “”;


       
}


    }

    return “”;

}

 

public System.Collections.ArrayList myCumulativeConcatArray
= new System.Collections.ArrayList();


 

public string AddToCumulativeConcat(int index, string val, string notused)

{

    if (index
< 0 || index >= myCumulativeConcatArray.Count)


    {

        return “”;

    }

    myCumulativeConcatArray[index]
= (string)(myCumulativeConcatArray[index]) + val;


    return myCumulativeConcatArray[index].ToString();

}

 

public string GetCumulativeConcat(int index)

{

    if (index
< 0 || index >= myCumulativeConcatArray.Count)


    {

        return “”;

    }

    return myCumulativeConcatArray[index].ToString();

}
 

XSLT 1.0 Equivalent: concat(string, string, string,
…)

 

XSLT 2.0 Equivalent: concat(string, string, string,
…)

 

 

Cumulative
Maximum

 

 

Generates: C#

Has XSLT Equivalent: in 2.0 only

  Emitted Code:

public string InitCumulativeMax(int index)

{

    if (index
>= 0)


    {

        if (index
>= myCumulativeMaxArray.Count)


       
{


            int i
= myCumulativeMaxArray.Count;


            for (;
i <= index; i++)


           
{


               
myCumulativeMaxArray.Add(“”);


           
}


       
}


        else

       
{


           
myCumulativeMaxArray[index] = “”;


       
}


    }

    return “”;

}

 

public System.Collections.ArrayList myCumulativeMaxArray
= new System.Collections.ArrayList();


 

public string AddToCumulativeMax(int index, string val, string notused)

{

    if (index
< 0 || index >= myCumulativeMaxArray.Count)


    {

        return “”;

    }

    double d
= 0;


    if (IsNumeric(val, ref d))

    {

        if (myCumulativeMaxArray[index] is string ||
(d > (double)(myCumulativeMaxArray[index])))


       
{


           
myCumulativeMaxArray[index] = d;


       
}


    }

    return (myCumulativeMaxArray[index] is double)
? ((double)myCumulativeMaxArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}

 

public string GetCumulativeMax(int index)

{

    if (index
< 0 || index >= myCumulativeMaxArray.Count)


    {

        return “”;

    }

    return (myCumulativeMaxArray[index] is double)
? ((double)myCumulativeMaxArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}
 

XSLT 1.0 Equivalent: (none)

  XSLT 2.0 Equivalent: max(node-set) or max(value, value, value,
…)


Note: in XSLT 1.0 you can achieve the same result through
use of XPath:


e.g. Number[not(parent::Numbers/Number
&gt; .)]
where <Numbers> and <Number>
are the parent and child nodes respectively.
 

 

Cumulative
Minimum

 

 

Generates: C#

Has XSLT Equivalent: in 2.0 only

  Emitted Code:

public string InitCumulativeMin(int index)

{

    if (index
>= 0)


    {

        if (index
>= myCumulativeMinArray.Count)


       
{


            int i
= myCumulativeMinArray.Count;


            for (;
i <= index; i++)


           
{


               
myCumulativeMinArray.Add(“”);


           
}


       
}


        else

       
{


           
myCumulativeMinArray[index] = “”;


       
}


    }

    return “”;

}

 

public System.Collections.ArrayList myCumulativeMinArray
= new System.Collections.ArrayList();


 

public string AddToCumulativeMin(int index, string val, string notused)

{

    if (index
< 0 || index >= myCumulativeMinArray.Count)


    {

        return “”;

    }

    double d
= 0;


    if (IsNumeric(val, ref d))

    {

        if (myCumulativeMinArray[index] is string ||
(d < (double)(myCumulativeMinArray[index])))


       
{


           
myCumulativeMinArray[index] = d;


       
}


    }

    return (myCumulativeMinArray[index] is double)
? ((double)myCumulativeMinArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}

 

public string GetCumulativeMin(int index)

{

    if (index
< 0 || index >= myCumulativeMinArray.Count)


    {

        return “”;

    }

    return (myCumulativeMinArray[index] is double)
? ((double)myCumulativeMinArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}
 

XSLT 1.0 Equivalent: (none)

  XSLT 2.0 Equivalent: min(node-set) or min(value, value, value)

Note: in XSLT 1.0 you can achieve the same result through
use of XPath:


e.g. Number[not(parent::Numbers/Number
&lt; .)]
 where <Numbers> and <Number> are the parent and
child nodes respectively.
 
 

Cumulative Sum

 

 

Generates: C#

Has XSLT Equivalent: in 1.0 and 2.0

  Emitted Code:

public string InitCumulativeSum(int index)

{

    if (index
>= 0)


    {

        if (index
>= myCumulativeSumArray.Count)


       
{


            int i
= myCumulativeSumArray.Count;


            for (;
i <= index; i++)


           
{


               
myCumulativeSumArray.Add(“”);


           
}


       
}


        else

       
{


           
myCumulativeSumArray[index] = “”;


       
}


    }

    return “”;

}

 

public System.Collections.ArrayList myCumulativeSumArray
= new System.Collections.ArrayList();


 

public string AddToCumulativeSum(int index, string val, string notused)

{

    if (index
< 0 || index >= myCumulativeSumArray.Count)


    {

        return “”;

    }

    double d
= 0;


    if (IsNumeric(val, ref d))

    {

        if (myCumulativeSumArray[index]
== “”)


       
{


           
myCumulativeSumArray[index] = d;


       
}


        else

       
{


           
myCumulativeSumArray[index] = (double)(myCumulativeSumArray[index])
+ d;


       
}


    }

    return (myCumulativeSumArray[index] is double)
? ((double)myCumulativeSumArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}

 

public string GetCumulativeSum(int index)

{

    if (index
< 0 || index >= myCumulativeSumArray.Count)


    {

        return “”;

    }

    return (myCumulativeSumArray[index] is double)
? ((double)myCumulativeSumArray[index]).ToString(System.Globalization.CultureInfo.InvariantCulture)
: “”;


}
 

XSLT 1.0 Equivalent: sum(node-set) or sum(value, value, value,
…)

 

XSLT 2.0 Equivalent: sum(node-set) or sum(value, value, value,
…)

 
  Common Code

(this is common code used by all the cumulative 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