Monday, November 23, 2009

Don't Forget to use the Correct XPath Selector!

Working with the Business Rules Engine in BizTalk is more than just a little challenging at times. The tool is incredible in terms of what it can do and it is fast. The problem is that it isn't always the most intuitive thing to work with. I've been struggling with it a bit lately and found a very basic but simple truth--when having the BRE analyze a document for you, make sure you apply the correct XPath Selector when selecting nodes or creating Vocabularies.

In my most recent project, I have a document that contains a quantity node. What I wanted the BRE to do was to calculate the sum of all the quantities beneath a parent node and put the result in yet another node. The format was something like this:


<shipments>
<batch>
<shipment>
<quantityX>3</quantityX>
<quantityY>4</quantityY>
<shipment>
<shipment>
...Another shipment
<shipment>
<quantities>
<totalx>5</totalX>
<totaly>6</totalY>
<quantities>
</batch>
<batch>
...Another batch
</batch>
</shipments>


The rule followed this logic:

IF
/shipments/batch/quantities/totalX is equal to '0'

THEN
/shipments/batch/quantities/totalX = CalculateSum(
"/shipments/batch",
"./shipment/quantityX")

The CalculateSum function was simply .NET code that accepted a reference node and calculated the sum of all the items that matched an XPath expression beneath that node.

The problem here was the selector used for a quantityX node vs. the totalX node. If you simply "drag-and-drop" fields from a schema into the rules it will give you something like that above. However, you'll get an incorrect total because the rules engine creates an object in memory based on the selector. You can easily see which selector is being used by looking at the XPath Selector property when you select a node (lower left portion of the screen in the Business Rules Composer). If the Selector is different between parts of your IF/THEN work, you'll find that things won't always match up.

What had happened here was that the sum was being built on a selector of "/shipments/batch" with an XPath field of "quantityX". The rules engine was referencing a selector of "/shipments/batch/quantities". Since these were different, not all the quantities where added correctly. The rules engine wasn't passing the correct data into our CalculateSum function.

The solution is pretty simple, but not intuitive. You simply need to structure your XPath Selector and XPath Fields so that the selectors are holding the same reference point.
In the above example the Selector would be "/shipments/batch" for both items. The XPath fields would then be altered to reference from that point. For the total line, the XPath field would be "quantities/totalX". For the quantity line to be added the XPath field would be "/shipment/quantityX". But most importantly, both fields use the SAME XPATH SELECTOR!

No comments:

Post a Comment