In my previous post – How to count XML Nodes Inside Orchestrations – I explained how to use the XPath count() function inside Orchestrations to count the number of nodes present on an XML message. In some cases, you need to count them based on some basic filter conditions.
Often we want these capabilities to implement some business logic inside your Orchestrations, like:
In this blog post, we will be using once again the XPath count() function to explain how to specify advanced filters conditions/expressions inside orchestrations. We can use this approach to count the elements present in an XML message, but also to retrieve them if that is required. For that, we may need a slight adjustment of the XPath query.
Once again, to count the number of nodes present in a message you need to use the following template expression:
<variable_name> = System.Convert.ToInt32(xpath(<message_name>,”count(<xpath_query>)”));
Despite the template expression be the same, you will find several approaches to count the nodes.
In this first example, we want to count or retrieve all the nodes or elements based on a single filter condition. In this case, we count how many nodes exist where Type == ‘P’.
varCountSF = System.Convert.ToInt32(xpath(msgInput,”count(//[local-name()=’XMLSample’]/[local-name()=’Object’]/*[local-name()=’Type’][text()=’P’])”));
Of course, if I would like, for example, to retrieve the value of the first Type element based on that condition, I would use:
<variable_name> = xpath(<message_name>,”string(//*[local-name()=’XMLSample’]/*[local-name()=’Object’][1]/*[local-name()=’Type’][text()=’P’])”);
The result will be ‘P’.
Now, if I want to retrieve the first Name element where Type is ‘P’, then the XPath query will be slightly different:
<variable_name> = xpath(<message_name>,”string(//*[local-name()=’XMLSample’]/*[local-name()=’Object’][*[local-name()=’Type’][text()=’P’]][1]/*[local-name()=’Name’])”);
In this query, the result will be ‘Sandro’ (if you see the sample XML message present in the source code).
Now let’s complicate a little more. Here, I want to count all the nodes or elements based on a single filter but using a Logical Operator. For example, count how many nodes exist where Type == ‘P’ OR Type == ‘A’.
varCountOr = System.Convert.ToInt32(xpath(msgInput,”count(//[local-name()=’XMLSample’]/[local-name()=’Object’]/*[local-name()=’Type’][text()=’P’ or text()=’A’])”));
Still quite simple.
Now, let’s try using multiple filter conditions inside one XPath query. For example, I want to count how many nodes exist where Type == ‘P’ and Name == ‘Sandro’.
varCountMF = System.Convert.ToInt32(xpath(msgInput,”count(//[local-name()=’XMLSample’]/[local-name()=’Object’][[local-name()=’Type’][text()=’P’]][[local-name()=’Name’][text()=’Sandro’]])”));
The last, and probably the most complex, is to count or retrieve distinct nodes or elements, this is a different filter condition. For example, I want to count how many distinct (unique) Name nodes exists on the message. For that, we need to use the preceding-sibling axis.
varCountDistinct = System.Convert.ToInt32(xpath(msgInput,”count(//[local-name()=’XMLSample’]/[local-name()=’Object’][not([local-name()=’Name’]/text()=preceding-sibling::[local-name()=’Object’]/[local-name()=’Name’]/text())]/[local-name()=’Name’])”));
Of course, the same principles explained here can be used for attributes as well.
You can access and download this sample code from GitHub here: POC: BizTalk – Advanced Filter With XPath Inside Orchestrations