When you want to debatch an XML file under BizTalk, there are two ways to do this either with a pipeline or with XPath.
Here it is going to be about the second way, and we will start with the unitary debatching. But for this case, it is simpler to use a pipeline because you don’t have to know the XPath language, it will be easier to understand and modify during further development. For more information on this, I urge you to go to the following blog post : DEBATCHING AN XML MESSAGE IN AN ORCHESTRATION WITH A PIPELINE.
However, when you need a complex debatching, the use of the XPath becomes more evident, as what we will see here, with the debatching by block (or packet) of message, or by filtering of a node in the XML file. To better assimilate the concept, an example of a message containing a list of animals will illustrate my comments.
For a unitary debatch, I propose a minimalist orchestration composed of :
vNbAnimals = xpath(mReceivedAnimals, "count(/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']/*[local-name()='Animal' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal'])");
mDebatchedAnimal = xpath(mReceivedAnimals, "/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']/*[local-name()='Animal' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal']["+ vCounterAnimalString +"]" );
For a debatching by block, we resume the pattern of the previous Orchestration :
// Definition of the block size vBlockSize = 3; // Total number of Animal type messages vNbAnimals = xpath(mReceivedAnimals, "count(/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']/*[local-name()='Animal' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal'])");
// Incrementing the max counter with the block size vCounterAnimalMaxBlock = vCounterAnimalMinBlock + vBlockSize; // If we are out of the number of animals, the max counter equals the total number of animals to get the remaining animals if (vCounterAnimalMaxBlock > vNbAnimals){ vCounterAnimalMaxBlock = vNbAnimals; } // Converting the min and the max positions to be able to use them in the XPath XPathvCounterAnimalMinBlockString = vCounterAnimalMinBlock.ToString(); vCounterAnimalMaxBlockString = vCounterAnimalMaxBlock.ToString(); // Incrementing the min counter vCounterAnimalMinBlock = vCounterAnimalMaxBlock;
// Initializing of mDebatchedAnimals to avoid mDebatchedAnimals = mReceivedAnimals; // XPath retrieves messages over a given interval xpath(mDebatchedAnimals, "/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']") = xpath(mReceivedAnimals, "/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']/*[local-name()='Animal' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal'][position() > "+ vCounterAnimalMinBlockString +" and position() <= "+ vCounterAnimalMaxBlockString +"]" ); a
For a filter debatch, the orchestration design becomes a bit more complex and here we are using atomic transaction in order to handle XML nodes :
// Choosing the filtered node vFilter =“Locomotion”; // Ou vFilter = “Diet”; // Getting the list of different locomotion (or diet) vFilterList = xpath(mReceivedAnimals, "/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']/*[local-name()='Animal' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal']/*[local-name()='"+ vFilter +"' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal']"); // Defining the total number of locomotion (or diet) for the looping vNbFilter = vFilterList.Count;
// Initializing of mDebatchedAnimals mDebatchedAnimals = mReceivedAnimals; // For each separate locomotion (=vFilter), XPath retrieves all animals with the same value (=vFilterString) xpath(mDebatchedAnimals, "/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']") = xpath(mReceivedAnimals, "/*[local-name()='Animals' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals']/*[local-name()='Animal' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal'][*[local-name()='"+vFilter+"' and namespace-uri()='http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal']='" + vFilterString + "']" ); // Adding the new filter to a list for the checking of new filters vDistinctFilterList.Add(vFilterString);
<ns0:Animals xmlns:ns0="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals"> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Fox</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Sloth</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Arboreal</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Mole</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Subterranean</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Horse</ns1:Name> <ns1:Diet>Herbivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Shark</ns1:Name> <ns1:Diet>Carnivorous</ns1:Diet> <ns1:Locomotion>Aquatic</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Lion</ns1:Name> <ns1:Diet>Carnivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Crow</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Aerial</ns1:Locomotion> </ns1:Animal> </ns0:Animals>
We observe 7 files corresponding to the 7 animals of our input file :
And each file contains a unitary message of type animal as follows :
<ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Horse</ns1:Name> <ns1:Diet>Herbivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal>
We observe well 3 files corresponding to the animals grouped 3 by 3 of our input file :
So, 2 files contain a message of type animals with 3 animals as follows :
<ns0:Animals xmlns:ns0="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals"> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Fox</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Sloth</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Arboreal</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Mole</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Subterranean</ns1:Locomotion> </ns1:Animal> </ns0:Animals>
And 1 last file with the remaining animals, that is, one animal :
<ns0:Animals xmlns:ns0="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals"> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Crow</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Aerial</ns1:Locomotion> </ns1:Animal> </ns0:Animals>
Filter on the animals means of locomotion
There are 5 files corresponding to the 5 different types of locomotion :
And each file contains a message of animal type grouping animals with the same means of locomotion as follows :
<ns0:Animals xmlns:ns0="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals"> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Fox</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Horse</ns1:Name> <ns1:Diet>Herbivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Lion</ns1:Name> <ns1:Diet>Carnivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> </ns0:Animals>
Filter on the diet of animals
This time, we observe 3 files corresponding to the 3 different types of diets:
And each file contains a message of animal type grouping animals with the same diet as follows :
<ns0:Animals xmlns:ns0="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animals"> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Fox</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Terrestrial</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Sloth</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Arboreal</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Mole</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Subterranean</ns1:Locomotion> </ns1:Animal> <ns1:Animal xmlns:ns1="http://MiddleWay.Blogs.Biztalk.XpathDebatching.Animal"> <ns1:Name>Crow</ns1:Name> <ns1:Diet>Omnivorous</ns1:Diet> <ns1:Locomotion>Aerial</ns1:Locomotion> </ns1:Animal> </ns0:Animals>
To avoid having to retouch the code and redeploy everything with every update of the block size or the node to be filtered, I recommend that you implement this data through an external Manager such as the SSO application.