Logical Functoids Cannot Connect to XML Attribute Nodes
October 24, 2014 Leave a comment
After working with BizTalk Server for over ten years, I was amazed to discover only today that the BizTalk 2010 Mapper does not allow you to connect a logical functoid to an XML attribute node!
Logical functoids are “special” in that they don’t output values when connected to a node in the target schema. Rather, the Boolean value that they do emit is often used as a conditional flag for determining the connected node’s appearance in the result. If a logical functoid connected to a record or an element evaluates to “false”, then the record/element will not be present in the output.
The question is… why doesn’t this work for attribute nodes as well?? Try to connect a logical functoid to one and the cursor turns into the dreaded “No you don’t!!” symbol, as shown in this screenshot:
Hoping this was an issue fixed in BizTalk 2013, I tried it there as well. But alas – the same constraint applies.
How It Should Work
If you connect the logical functoid to an element node, for example, than the resulting XSLT creates a variable that holds the emitted value of the functoid and uses this as a condition for outputting the target node:
So why can’t this be done for the attribute as well?
The Code Doesn’t Lie
In response to my tweet about this today (which spawned a lengthy discourse from the community, mostly debating use of the mapper vs. XSLT vs. beer), Microsoft MVP Sandro Pereira showed us underlying proof of the lack of support for attributes:
The ConnectionType.Attribute enum is missing from the OutputConnectType property. Is this an oversight, or is it by design? If it’s the latter, I’d love to know why…
Why Is This Important?
Take the example shown in the first screenshot above. Let’s assume that the target “Id” attribute node had a data-type of “xs:int”, but the source “NumericElement” node might contain a string value (yeah… never trust a node by its name alone!). You don’t want an invalid output message, so you would like to use the Logical Numeric functoid to test for a valid number value; by connecting this to a target node you can control whether the node is created or not (despite any other value mappings). If the result is “false” (which it would be if the “NumericElement” was missing, nil, or contained a non-numeric value), then the target node would not appear in the output message – and you’d avoid schema validation issues.
This is a common mapping pattern which works extremely well when logical functoids are connected to records or elements. But… not so for attribute nodes. Just wait until the E.R.A. (Equal Rights for Attributes) hears about this…
Workarounds
A simple workaround for this example would be to use the value mapping functoid with the output of the Logical Numeric functoid as the first input:
Sure, that works. And if your logic is more complicated, you could always rely on a scripting functoid using Inline XSLT (not required for this simple example but shown here just to prove it’s possible):
But this still begs the question of why this can’t be made as simple as it is for elements & records, especially when the documentation clearly indicates that Logical Functoids should be able to connect to attributes:
“Use Logical functoids to perform a variety of logical operations, often controlling whether a particular element or attribute is created in an output instance message.”
Maybe someday, in some future world where integration harmony reigns, attributes will finally be recognised as first-class citizens and afforded the same dignity and respect as all XML nodes. (“I have a dream!”)
Until then, keep dragging out those Value Mapping functoids (or write some XSLT)…