Advanced XPath filter strategies inside Orchestrations

Published on : Aug 12, 2021

Category : BizTalk Server

Sandro

Author

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:

  • if records exist then, map them and send them to a specific system
  • otherwise, terminate the business flow logic

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. 

Count/Filter all nodes, based on a single filter condition

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).

Count/Filter all nodes, based on a single filter condition with Logical operators:

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.

Count/Filter all nodes, based on multiple filter conditions:

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’]])”));

Count/Filter all nodes, with unique (distinct) values

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.

Download

You can access and download this sample code from GitHub here: POC: BizTalk – Advanced Filter With XPath Inside Orchestrations