BizTalk Mapper Patterns: Automatically Link The Record Elements By Structure, Name or Using Mass Copy

Posted: December 28, 2013  |  Categories: BizTalk Maps

Exchanging or routing messages between existing applications, systems or external partners is one of the many common scenarios in Enterprise integration solutions. And sometimes they are build base on the same data model, however, because they are built in different systems and teams they can have slight small differences like the order of the elements, the name of the elements, the structure or even the namespace. As a result of that, we need to be able to transform the original message to the expect message by those systems.

BizTalk Mapper provides you with just-in-time assistance, through a shortcut menu, when you create links between two record elements of source and destination schemas:

  • You can create multiple links simultaneously if:
    • Relevant schema structures must be the same were node names are different but the order is the same or similar;
    • Or Record, elements or field names must match;
  • You can manually create single links by dragging and dropping the source element to the destination element if the destination schema don’t have similar structures or the same names;
  • Or you can use Mass Copy Functoid to copy the element in the input instance message to a destination schema that uses the <any> Element (some kind of generic schema). This functoid also copies any and all of its substructure and it will re-create it in the output instance message at the linked node in the destination schema.

The BizTalk Mapper provides you with just-in-time assistance, through a shortcut menu, when you create links between two record elements of source and destination schemas.

So for accomplish that, open your map and:

  • Drag-and-drop the root name of the source schema, in this case, “PurchaseOrder” to the root name of the destination schema, which will be in this case “PO”, and release the direct button of the mouse.
just in time assistance BizTalk Mapper
  • A windows assistance will pop up where you can select create record-to-record links automatically in the following ways:
    • Direct Link: Using this technique, the BizTalk Mapper links the record from the source schema to the selected record in the destination schema. This will not copy any kind of hierarchy structure from the source to the destination, it will only link the record or node.
    • Link by Structure: Using this technique, the BizTalk Mapper attempts to match the Record and Field nodes within the Record nodes being linked according to the structures of those Record nodes, regardless of names of the corresponding nodes within those structures.
    • Link By Name: Using this technique, the BizTalk Mapper attempts to match the Record and Field nodes within the Record nodes being linked according to the names of the corresponding nodes, regardless of their structure, within the Record nodes being linked.
    • Mass Copy: The Mass Copy functoid enables your maps to use schemas that include any and anyAttribute elements. For information about the functoids available in BizTalk Mapper.

Our scenario will have a Purchase Order that will need to be mapped to 3 different systems with 3 different target schemas.

  • System A has a similar schema of our system, with the same structure and the same names, but they are presented in a different order;
    • Because the destination schema have the same names of the source schema, the best approach in this scenario is to use the Link By Name option
  • The System B have also a similar schema of our system, we as the same order and the same schema structure, however, the elements have different names;
    • Because the destination schema has the structure of the source schema, the best approach in this scenario is to use the Link By Structure option
  • The System C has a canonical schema (or generic schema) that will accept any structure.
    • Because the destination schema will accept any kind of structure, the best approach in this scenario is to use the Mass Copy option

Scenario A: How to link the record elements by name

To accomplish that we need:

  • Drag the mouse from the root name “PurchaseOrder” in the source schema, and then drop it to root name “PO” in the destination schema.
  • On the shortcut menu, click “Link by Name” option. The BizTalk Mapper will attempt to match all the Record, Elements and Field nodes under the “PurchaseOrder” node according to their names, regardless of their structure, within the node “PO”.

And the BizTalk Mapper will automatically map all the elements from the source schema to the target schema that have the same name, as the picture below will show:

Link by Name

Of course this technique as some limitations, the elements need to have the exact same name, and will only work in some scenarios.

Scenario B: How to link the record elements by structure

To accomplish that we need:

  • Drag the mouse from the root name “PurchaseOrder” in the source schema, and then drop it to root name “ExternalPO” in the destination schema.
  • On the shortcut menu, click “Link by Structure” option. The BizTalk Mapper will attempt to match all the Record, Elements and Field nodes under the “PurchaseOrder” node according to the structure of those elements, regardless of names of the corresponding nodes within those structures, within the node “ExternalPO”.

And the BizTalk Mapper will automatically map all the elements from the source schema to the target schema that have the same structure, as the picture below will show:

Link by Structure

Again this technique has the same limitations as the previous one.

Scenario C: How to link using a mass copy functoid

To accomplish that we need:

  • Drag-and-drop the Mass Copy functoid from the Toolbox to the map grid page and then:
    • Link the source root name “PurchaseOrder” as an input parameter for the Mass Copy functoid;
    • Link the Mass Copy functoid to the destination root name “CanonicalPurchaseOrder” to set the output parameter from the Mass Copy functoid;
Mass Copy

The only problem in using the Mass Copy functoid is that it will move all the elements and values from the source schema to the destination schema but it also will include the targetNamespace of source schema in the destination schema and this behavior can be a problem in some scenarios.

An example of the map output:

<ns0:CanonicalPurchaseOrder xmlns:ns0="http://BizTalkMapperSemanticTranslatorPattern.CanonicalPurchaseOrder">
 <From xmlns:ns0="http://BizTalkMapperSemanticTranslatorPattern.PurchaseOrder">From_0</From>
 <To xmlns:ns0="http://BizTalkMapperSemanticTranslatorPattern.PurchaseOrder">To_0</To>
 <LineItems xmlns:ns0="http://BizTalkMapperSemanticTranslatorPattern.PurchaseOrder">
 <Item>
 <Product>Product_0</Product>
 <Description>Description_0</Description>
 <Price>10</Price>
 <Quantity>10</Quantity>
 </Item>
 </LineItems>
</ns0:CanonicalPurchaseOrder>

So how can we avoid this behavior?

However, sometimes the destination schema expects a different message, without the namespaces in the element:

<CanonicalPurchaseOrder xmlns:ns0="http://BizTalkMapperSemanticTranslatorPattern.CanonicalPurchaseOrder">
  <From>From_0</From>
  <To>To_0</To>
  <LineItems>
     <Items>
        <Product>Product_0</Product>
        <Description>Description_0</Description>
        <Price>10</Price>
        <Quantity>10</Quantity>
     </Items>
  </LineItems>
</CanonicalPurchaseOrder>

I already saw this scenario many times. So how can we accomplish this?

There is no easy way to accomplished this without the need to use custom XSLT and you will need to customize the syntax to your scenario.

In this sample if we need to map everything without namespaces we need to “replace” the Mass Copy functoid for a Scripting functoid:

  • Drag-and-drop the Scripting functoid from the Toolbox to the map grid page and then:
    • And Link the Scripting functoid to the destination root name “CanonicalPurchaseOrder” to set the output parameter from the Scripting functoid;
    • This functoid will not have any input parameters;
  • Double-click on the Scripting functoid to show the Properties window, then:
    • Select the “Script Functoid Configure” tab, and then choose “Inline XSLT” as your selected script type
    • In the “Inline script” text box enter the following XSLT code without the comments (they are only for explaining the operation of the script):
<CanonicalPurchaseOrder>
      <xsl:for-each select="/s0:PurchaseOrder/*">
        <xsl:if test="local-name()!='LineItems'">
          <xsl:element name="{local-name(.)}">
            <xsl:value-of select="." />
          </xsl:element>
        </xsl:if>
      </xsl:for-each>

      <xsl:choose>
        <xsl:when test="count(/s0:PurchaseOrder/LineItems) &amp;gt; 0">
          <LineItems>
            <xsl:for-each select="/s0:PurchaseOrder/LineItems/*">
              <Items>
                <xsl:for-each select="./*">
                  <xsl:element name="{local-name(.)}">
                    <xsl:value-of select="." />
                  </xsl:element>
                </xsl:for-each>
              </Items>
            </xsl:for-each>
          </LineItems>
        </xsl:when>
      </xsl:choose>
</CanonicalPurchaseOrder>

Basically what we are doing is:

  • The Scripting functoid will not add the root name, so we need to manually add it
  • There we are getting all the element inside “PurchaseOrder” but because we need to travel all the elements inside the LineItems we need to treat this different so we will get all the element except the ” LineItems”
  • The next step is to check if there is “LineItems”
  • If exist we will travel all the element inside the LineItems (for each)
  • Because the “LineItems” only contains one record we will add this manually but we need an additional cycle this time to travel all the elements inside the record Item

And with that, we create our own custom Mass copy Functoid

You can download the source code from:
Automatically Link The Record Elements By Structure, Name or Using Mass CopyAutomatically Link The Record Elements By Structure, Name or Using Mass Copy
GitHub

Author: Sandro Pereira

Sandro Pereira lives in Portugal and works as a consultant at DevScope. In the past years, he has been working on implementing Integration scenarios both on-premises and cloud for various clients, each with different scenarios from a technical point of view, size, and criticality, using Microsoft Azure, Microsoft BizTalk Server and different technologies like AS2, EDI, RosettaNet, SAP, TIBCO etc. He is a regular blogger, international speaker, and technical reviewer of several BizTalk books all focused on Integration. He is also the author of the book “BizTalk Mapping Patterns & Best Practices”. He has been awarded MVP since 2011 for his contributions to the integration community.

2 thoughts on “BizTalk Mapper Patterns: Automatically Link The Record Elements By Structure, Name or Using Mass Copy”

  1. I’ve read a couple of places (including a BizTalk book) that you should be able to “override” a mass-copy on a field by field basis by simply linking a functoid to the field to be overridden. “Example a field need to be passed a current date, then have the Date functoid placed a link to destination field this will override mass copy. ” This does not seem to work and generates a warning from the mapper on validation. It doesn’t make sense to me that this should work. Am I missing something?

  2. Want to understand when on directlinks sometimes from the xslt page I can see that foreach is added if it unbounded node and sometimes it is not adding foreach for the node. why this ambiguity or is it any scenario based

Leave a Reply

Your email address will not be published. Required fields are marked *

turbo360

Back to Top