Tech Blog

Understanding the BizTalk Mapper: Part 11 – Advanced Functoids

Interestingly, all of the advanced functoids emit XSLT. No C# in sight at all.
The reason for this is that the functoids in this category all perform operations
best suited to trees of data i.e. XML.
The only way to do this in C# would be to load the data into a DOM (i.e. XmlDocument)
or XmlReader, or treat the XML as string data and search for tokens.

Note: this category was the one that actually started this series – I felt
that if you knew the XSLT emitted by these functoids it would help understand when
to use them, and what you can achieve with them.

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:

Assert Record Count
Index Scripting
Iteration Table Looping
Looping Table Extractor
Mass Copy Value Mapping
Nil Value Value Mapping (Flattening)

Note:

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

Advanced Functoids

 

Assert

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:if test=“(value-test)=’false’>

     
<
xsl:message terminate=yes>

     
  <
xsl:value-of select=(value-error) />

     
</
xsl:message>

</xsl:if>

<xsl:if test=(value-test)=’true’>

     
<
xsl:variable name=var:v1 select=“(value-out) />

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

</xsl:if>

Note: (value-test) is the element/attribute/value
tested for a true/false value.


(value-error) is the element/attribute/value used as the
error text.


(value-out) is the element/attribute/value emitted if there
is no error.

 

 

Index

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:variable name=var:v1 select=./(node)[index][index][…]/(element)/(attribute) />

for example:

<xsl:variable name=var:v1 select=./Employee[2]/@id />

Note: in the above code, Employee is the repeating
node, 2 is the index we want to use, and @id is an attribute of the Employee element
we wish to retrieve.


This functoid uses standard XSLT indexing to build up an XSLT select query.

The sample code shown above is a very simple example.
 

 

Iteration

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:variable name=var:v1 select=position() />

  Note: the functoid places the above code under the relevant
element we’re getting the iteration (index) of.


The variable is then used to emit the index at the appropriate place.
 

 

Looping

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:for-each select=(node)>

</xsl:for-each>

Note: where (node) is whatever input node is being looped-over.

The Looping functoid is unique in that if you link from a repeating node in
the source tree, then the Mapper will implicitly insert a looping functoid (although
no functoid shape will be visible on the map).


Understanding how to use the looping functoid is a vital part of creating advanced
maps (e.g. concatenating multiple messages into one, or flattening loops).


If you have more than one input element into the loop, then a for-each loop
is created over each input element, and one output element is created for each input
element. This is a common way of concatenating (aggregating) two separate messages.

 

 

Mass Copy

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:copy-of select=./@* />

<xsl:copy-of select=./* />

Note: the functoid places the above code under the appropriate
destination element, and the “.” indicates the current element being processed from
the source message.


As an example:

<ns0:Employees>

  <xsl:for-each select=Employee>

    <Employee>

     
<
xsl:copy-of select=./@* />

     
<
xsl:copy-of select=./* />

    </Employee>

  </xsl:for-each>

</ns0:Employees>
 

 

Nil Value

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:attribute name=xsi:nil>

   <xsl:value-of select=‘true’ />

</xsl:attribute>

Note: the functoid places the above code under the appropriate
element in the destination message.


If a parameter is supplied to the functoid, then the above code is wrapped in
an <xsl:if> node.


For example:

<xsl:if test=@name=’true’>

<Field>

  <xsl:attribute name=xsi:nil>

    <xsl:value-of select=‘true’ />

  </xsl:attribute>

</Field>

</xsl:if>
 

 

Record Count

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:variable name=var:v1 select=count(node-set) />

Note: (node-set) is an element/record which repeats.

The variable is then used in a value-of statement.

For example:

<xsl:variable name=var:v1 select=count(/ns0:Employees/Employee) />

<ns0:Employees>

  <Employee>

    <xsl:attribute name=id>

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

    </xsl:attribute>

  </Employee>

</ns0:Employees>
 

 

Scripting

 
 

Generates: XSLT/Inline Script

Has XSLT Equivalent: N/A

  Emitted Code:

External Assembly

Emits XSLT to call the appropriate method, along with an Extension Object file
containing the strong name of the assembly to use.


For example (this example passes in two constant parameters to the method):

<xsl:variable name=var:v1 select=ScriptNS0:AddComponent(‘1’,
‘2’)
/>


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

 

<ExtensionObjects>

  <ExtensionObject Namespace=http://schemas.microsoft.com/BizTalk/2003/ScriptNS0 AssemblyName=Microsoft.BizTalk.DefaultPipelines,
Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
ClassName=Microsoft.BizTalk.DefaultPipelines.PassThruReceive />


</ExtensionObjects>

 

Inline C#

Inline JScript .NET

Inline Visual Basic .NET

Emits a call to the method, and wraps the actual code in a CDATA block.

For example:

<xsl:variable name=var:v1 select=userC#:MyConcat’1′,
‘2’)
/>


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

 

  <msxsl:script language=C# implements-prefix=userC#><![CDATA[

///*Uncomment the following
code for a sample Inline C# function


//that concatenates two inputs.
Change the number of parameters of


//this function to be equal
to the number of inputs connected to this functoid.*/


 

public string MyConcat(string
param1, string param2)


{

     
return param1+param2;


}

]]>

  </msxsl:script>

 

Inline XSLT

Emits the XSLT as entered at the appropriate place in the destination tree.

 

Inline XSLT Call Template

Emits the template and a call to the template.

For example:

<xsl:call-template name=MyXsltConcatTemplate>

     
<
xsl:with-param name=param1 select=‘1’ />

     
<
xsl:with-param name=param2 select=‘2’ />

</xsl:call-template>

 

<xsl:template name=MyXsltConcatTemplate>

     
<
xsl:param name=param1 />

     
<
xsl:param name=param2 />

     
<
xsl:element name=field>

     
   <
xsl:value-of select=$param1 />

     
   <
xsl:value-of select=$param2 />

     
</
xsl:element>

</xsl:template>

 
 

 

Table Looping

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

(auto generated)

Note: the Table Looping functoid (along with the Table
Extractor
functoid) builds custom XSLT in the destination XSLT. This custom XSLT
will comprise a number of for-each loops (for the repeating element specified
as the first parameter to the Table Looping functoid), and then a number of
structures, one per row configured in the functoid.


If the Gated property is set, then each structure is surrounded by an if statement.

 

This is an example of the output generated by use of the Table Looping / Table
Extractor
functoids.


In this sample, we’re filtering the input list, so that the output only contains Employee nodes
with a department value of ‘Managers’.


In this example, the Table Looping functoid has the source Employee element
as input, with number of columns set to 5, followed by a Logical Equal functoid
(true if @department equals ‘managers’, followed by a single constants (Management)
and then three attributes (@name, @id, @department).


 

The sample XML used as input was:

<ns0:Employees >=http://TestMaps.Employees>

  <Employee name=Mary
Briggs
id=1 department=Managers />


  <Employee name=Sam
Gamgee
id=5 department=Staff />


  <Employee name=Frodo
Smith
id=20 department=Staff />


</ns0:Employees>

 

The looping functoid was then setup to generate one record (row) per input element,
with the Gated property set on the first column the Logical Equal functoid).


Four Table Extractor functoids were setup, with each one connecting to one of
the four attributes on the output message (@type, @name, @id, @department).


This is the XSLT generated by these functoids:

<xsl:template match=/s0:Employees>

<ns0:Employees>

  <xsl:for-each select=Employee>

    <xsl:variable name=var:v1 select=userCSharp:LogicalEq(string(@department),
‘Managers’)
/>


    <xsl:if test=$var:v1>

     
<
xsl:variable name=var:v2 select=‘Management’ />

     
<
xsl:variable name=var:v3 select=@name />

     
<
xsl:variable name=var:v4 select=@id />

     
<
xsl:variable name=var:v5 select=@department />

     
<
Employee>

       
<
xsl:attribute name=type>

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

       
</
xsl:attribute>

       
<
xsl:attribute name=name>

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

       
</
xsl:attribute>

       
<
xsl:attribute name=id>

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

       
</
xsl:attribute>

       
<
xsl:attribute name=department>

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

       
</
xsl:attribute>

     
</
Employee>

    </xsl:if>

  </xsl:for-each>

</ns0:Employees>

</xsl:template>
 

 

Table Extractor

 
 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

(see the Table Looping functoid above)
 

 

Value Mapping

 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<xsl:for-each select=(source
element)
>


<(destination
element parent)
>

  <xsl:if test=(node-test)=’true’>

    <xsl:variable name=var:v1 select=@id />

    <(destination
element)
>

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

    </(destination
element)
>

  </xsl:if>

</(destination
element parent)
>

</xsl:for-each>

Note: if the Value Mapping functoid is used with
a repeating source element, then it will place a for-each element outside of
the parent destination element.


If the source element is not repeating, then the functoid emits a value-of statement,
with an optional if statement (if an element/attribute is used as the first parameter
rather than a constant).


 

For example, if the input message was:

<ns0:Employees >=http://TestMaps.Employees>

  <Employee name=Mary
Briggs
id=1 department=Managers />


  <Employee name=Sam
Gamgee
id=5 department=Staff />


  <Employee name=Frodo
Smith
id=20 department=Staff />


</ns0:Employees>

and the source/destination schemas were the schema used for the above message,
and the Value Mapping functoid linked the id attribute to the Field element,
then the following XSLT would be generated:


<ns0:Employees>

  <xsl:for-each select=Employee>

    <xsl:variable name=var:v1 select=@id />

    <Employee>

      <Field>

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

     
</
Field>

    </Employee>

  </xsl:for-each>

</ns0:Employees>

 

which would generate the following output:

<ns0:Employees >=http://TestMaps.Employees>

     
<
Employee>

           
   <
Field>1</Field>

     
</
Employee>

     
<
Employee>

           
   <
Field>5</Field>

     
</
Employee>

     
<
Employee>

           
   <
Field>20</Field>

     
</
Employee>

</ns0:Employees>
 

 

 

Value Mapping
(Flattening)

 

Generates: XSLT

Has XSLT Equivalent: N/A

  Emitted Code:

<(destination
element parent)
>

<xsl:for-each select=(source
element)
>


  <xsl:if test=(node-test)=’true’>

    <xsl:variable name=var:v1 select=(source-value) />

    <(destination
element)
>

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

    </(destination
element)
>

  </xsl:if>

</xsl:for-each>

</(destination
element parent)
>

Note: the Value Mapping (Flattening) functoid constructs
a for-each loop around the source element, and outputs one instance of the destination
element per instance of the source element.


For example, if the input message was:

<ns0:Employees >=http://TestMaps.Employees>

  <Employee name=name_0 id=1 department=department_2 />

  <Employee name=name_0 id=5 department=department_2 />

  <Employee name=name_0 id=20 department=department_2 />

</ns0:Employees>

and the source/destination schemas were the schema used for the above message,
and the Value Mapping (Flattening) functoid linked the id attribute to the
Field element, then the following XSLT would be generated:


<ns0:Employees>

  <Employee>

    <xsl:for-each select=Employee>

     
<
xsl:variable name=var:v1 select=@id />

     
<
Field>

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

     
</
Field>

    </xsl:for-each>

  </Employee>

</ns0:Employees>

 

which would generate the following output:

<ns0:Employees >=http://TestMaps.Employees>

     
<
Employee>

           
<
Field>1</Field>

           
<
Field>5</Field>

           
<
Field>20</Field>

     
</
Employee>

</ns0:Employees>
 

 

Back to Tech Blog