In this blog entry I will show two different ways to use logical functoids to affect the output of the mapping process.  Just as in the last mapping blog entry these two examples are at the top of the list of mapping questions people ask me.

 

The first example will show how to split the incoming data into multiple grouped output records.  So, lets say I receive a shipping list that contains all of the orders for that day.  This listing includes the addresses for locations all over the world.  The destination requires that I group the output based on country.

 

The source schema looks like:

 

 

With the following as the source instance (with fake data, of course):

 

<ns0:Root xmlns:ns0="http://Map_blog_sample.Source">

  <Address>

    <ShipTo>Jim Smith</ShipTo>

    <Address>12 Old Main Street</Address>

    <City>RiverCity</City>

    <State>Maine</State>

    <Zip>12345</Zip>

    <Country>USA</Country>

  </Address>

  <Address>

    <ShipTo>Jim Anderson</ShipTo>

    <Address>87 West End Trail</Address>

    <City>Winnipeg</City>

    <State>Ontario</State>

    <Zip>HP7-21A</Zip>

    <Country>Canada</Country>

  </Address>

  <Address>

    <ShipTo>Phil Hewlett</ShipTo>

    <Address>4897 Bushnell Drive</Address>

    <City>Forest Glen</City>

    <State>Wisconsin</State>

    <Zip>54321</Zip>

    <Country>USA</Country>

  </Address>

</ns0:Root>

 

And the destination schema looks like:

 

 

In order to make this split happen we need to include 2 Equal functoids from the Toolbox in the Logical Functoids section.  Drag a line from the Country Node to each Equal functoid.  Whenever I drag a line to a functoid I like to label the line.  You can label the line by clicking on the line and entering text in the Label property in the Properties Windows.  This is helpful when I open the Input Parameters window for the functoid so that I can see a meaningful label instead of a long XPATH statement.

 

In the Input Parameters window of the first Equal functoid add a constant and label it USA.  Do the same for the second Equal functoid but label the constant Canada.  Now drag a line from the USA functoid to the USAddresses record and drag a line from the Canada functoid to the ForeignAddresses record.  Now all that is left is to drag the lines from the source fields to the matching destination fields.

 

The map looks like this:

 

 

And the destination XML looks like this:

 

<ns0:Root xmlns:ns0="http://Map_blog_sample.Destination">

        <USAddresses>

                <ShipTo>Jim Smith</ShipTo>

                <Address>12 Old Main Street</Address>

                <City>RiverCity</City>

                <State>Maine</State>

                <Zip>12345</Zip>

        </USAddresses>

        <USAddresses>

                <ShipTo>Phil Hewlett</ShipTo>

                <Address>4897 Bushnell Drive</Address>

                <City>Forest Glen</City>

                <State>Wisonsin</State>

                <Zip>54321</Zip>

        </USAddresses>

        <CanadianAddresses>

                <ShipTo>Jim Anderson</ShipTo>

                <Address>87 West End Trail</Address>

                <City>Winnepeg</City>

                <Province>Ontario</Province>

                <Zip>HP7-21A</Zip>

        </CanadianAddresses>

</ns0:Root>

 

 

One thing to notice is the difference between the input and the output order.  There is no way to guarantee the order through the mapping process.  This is because when the BizTalk Mapper generates the XSLT it examines the destination schema structure and then it propagates through any grid layers to pull out the values from the source schema structure.   So, after saying that there is no guarantee to the order there is a way to coach the process.  The order in which elements and attributes appear in an output instance message is dependent on the order of the records and fields of the destination schema.

 

 

The second example will show how to suppress a destination node based on the existence of or lack of a source node.

 

In this scenario the country element will only be filled out if the address is not in the United States - we want the output to include only those records that are in foreign countries.

 

In this scenario we will use the same input instance as well as the same source and destination schemas. 

 

This time the mapper will use the Logical Existence functoid as well as the Value Mapping functoid (5 for this example). 

 

The logical existence functoid will return true if the tags exists but there is no value.  For the logical existence to return false then the entire node must not be present.  In our case we want the logical existence functoid to return false when it iterates over a record where the address would be in the United States. 

 

To create the map follow these steps:

1)  drag a line from the Country node to the logical existence functoid. 

2)  drag a line from the logical existence functoid to each of the 5 Value Mapping functoids.  It is important that these lines be the first lines connected to the value mapping functoids

3) drag a line from the ShipTo element to the first Value Mapping functoid.  Since I may end up at the link in the functoids Property Window I will name the link. 

4) repeat step 3 for each of the remaining elements.  Do not map the Country element.

5) last, drag a line from the Logical Existence functoid to the ForeignAddresses record. 

 

This last item is interesting.  The logical functoids have a special ability in that when they return a true or false and are connected to a destination element or record they will suppress the output of that element or record when the value of the functoid is false.  This is exactly what we want since we do not want a record output for the United States Addresses. 

 

If the line from the logical existence functoid is not drawn to the ForeignAddresses record then the output will look like:

 

<ns0:Root xmlns:ns0="http://Map_blog_sample.Destination">

        <ForeignAddresses></ForeignAddresses>

        <ForeignAddresses>

                <ShipTo>Jim Anderson</ShipTo>

                <Address>87 West End Trail</Address>

                <City>Winnepeg</City>

                <Province>Ontario</Province>

                <Zip>HP7-21A</Zip>

        </ForeignAddresses>

        <ForeignAddresses></ForeignAddresses>

        <ForeignAddresses>

                <ShipTo>Jake Swenson</ShipTo>

                <Address>12 West Winfield Drive</Address>

                <City>Rome</City>

                <Province></Province>

                <Zip>YA1-23U</Zip>

        </ForeignAddresses>

</ns0:Root>

 

Notice that there are extra ForeignAddresses tags.  These are the tags where the input record was a United States address (the country element was missing). 

 

The map should look like this:

 

 

If we follow steps 1 through 5 then the output should look like:

 

<ns0:Root xmlns:ns0="http://Map_blog_sample.Destination">

        <ForeignAddresses>

                <ShipTo>Jim Anderson</ShipTo>

                <Address>87 West End Trail</Address>

                <City>Winnepeg</City>

                <Province>Ontario</Province>

                <Zip>HP7-21A</Zip>

        </ForeignAddresses>

        <ForeignAddresses>

                <ShipTo>Jake Swenson</ShipTo>

                <Address>12 West Winfield Drive</Address>

                <City>Rome</City>

                <Province></Province>

                <Zip>YA1-23U</Zip>

        </ForeignAddresses>

</ns0:Root>