To Be, Or Logical Not To Be: If-Then-Else in BizTalk Maps

Stumbling around various BizTalk-related blogs, there appears to be a common scenario which is addressed a wide variety of ways: How to handle If, Then, Else in schema transformations / mapping.

One perplexing scenario I encountered earlier this year was surrounding a procurement system integration with an ERP system.  Items entered prior to a certain date would have a different item number than items entered after that date, even if it may be the same item.  To accommodate this, the originating system stored the "legacy item number" as metadata in its item master table.

The problem is we had some rather inconsistent output.  When the legacy item number was present, no problem.  When the legacy number was not present, sometimes we would get a nil value (xsi:nil="true") and sometimes the field would just be blank.  Don't ask me why; this wasn't my system.

So, here's the logic we'll try to implement with the BizTalk mapper:

If LegacyItemNumber is blank or LegacyItemNumber is nil, use ItemNumber; Else, use LegacyItemNumber.

Our incoming schema (simplified for this demo) looks like this:

InSchema

And our outbound schema looks like this:

OutSchema

Now, let's set up a simple map:

BizTalk Map

We're using a couple of functoids here that are new to BizTalk 2006, and they make our job a little easier:

  • Logical IsNil functoid IsNil: Returns "true" if the input value is an XML "nil" value.
  • Logical NOT functoid Logical Not: Returns the opposite boolean of its input.

We've mapped the LegacyItemNumber element to the IsNil functoid and an  Equal functoid which also has a blank constant for its second parameter.  Both of these functoids map to a  Logical Or functoid. 

This means if LegacyItemNumber is empty *or* if it's nil, the Logical Or returns "true" to the first  Value Mapping functoid.  This Value Mapping functoid has the ItemNumber element as its second input, meaning if LegacyItemNumber is blank or nil, we'll return the new ItemNumber value.

Likewise, if the Logical Or returns false (the legacy value is neither blank nor nil), the Logical Not functoid returns "true" to its Value Mapping functoid, which has the legacy value as its second parameter.

Both of the Value Mapping functoids are mapped to our output element, PartID; however we shouldn't encounter a case where both values are returned, since we're using the Logical Not value for the second one, making it impossible for both functoids to receive a "true" value.

Let's test it.

Input 1 -- Legacy value is present:

Input 1

Output 1:

Output 1

Input 2 -- Legacy value is blank:

Input 2

Output 2:

Output 2

Input 3 -- Legacy value is nil:

Input 3

Output 3:

Output 3

So there it is, a simple if-then-else... with a twist (if/or, then, else).  If there are better or easier ways of accomplishing this, I'd be interested to know.

 

Technorati tags: BizTalk