Ok first of all I have to give lots of credit to Martijn Hogendoorn for helping me with this one. I had a question about how to handle a specific problem within a pipeline.
He said Why don't you use the XpathMutatorStream for that.....
Well I never heared of the XpathMutatorStream before and after some explanation of Martijn it became clear how it works.
You define a set of Xpath Queries and Program something in the callback. Then you instantiate the XpathMutatorStream and you're done !.
Once reading of the stream begins your queries will be executed and for every match the callback is executed. And all this is done in a streaming fashion.
Too bad this functionality is only available for bizTalk developers. Equal functionality is available on GotDotNet, it's called XpathReader
But this one is complete streaming so it works for small messages and very large messages as well.
This can be so usefull if you ever have to develop a pipelinecomponent, I am a littlebit puzzled why Microsoft keeps this stuff hidden.
There is almost no documentation about it on the internet and in the SDK it's also absent.
For this stuff to work you will need 2 DLL's. The DLL's are already in the GAC but you cannot reference them in a project,
so you have to get them somewhere. ( I got them because I installed Martijn's Management tool for BizTalk 2004).
the DLL's are Microsoft.BizTalk.Streaming.dll and Microsoft.BizTalk.XPathReader.dll
( or have a read of this article how to get that dll)
private void DoTheMagic()
// Set up the Xml Document
System.Xml.XmlDocument XDOC = new XmlDocument();
// Set up the stream and rewind
MemoryStream memstream = new MemoryStream();
memstream.Position = 0;
// Define the XpathMutator
XPathMutatorStream VersionStream = MatchVersion(memstream);
// Read the stream and see the magic happen
XmlTextReader reader = new XmlTextReader(VersionStream);
private XPathMutatorStream MatchVersion(MemoryStream OriginalStream)
// Define the Xpath Collection
XPathCollection VersionQueries = new XPathCollection();
// Add the Mutator to this Stream
ValueMutator VersionMatcher = new ValueMutator(this.VersionMatcher);
XPathMutatorStream VersionStream = new XPathMutatorStream(OriginalStream, VersionQueries, VersionMatcher);
VersionStream.AfterLastReadEvent +=new AfterLastReadEventHandler(EndOfVersionStreamReached);
return VersionStream ;
private void VersionMatcher(int matchIdx, XPathExpression matchExpr, string origVal, ref string finalVal)
System.Diagnostics.Debug.WriteLine("Xpath :" + matchExpr + " Value " + origVal);
finalVal = origVal;
private void EndOfVersionStreamReached(object src, EventArgs args)
System.Diagnostics.Debug.WriteLine("LastRead of VersionStream");
/// Reformat an xpath query
/// <param name="oldXpath"></param>
private string FormatXpathQuery(string oldXpath)
// See if there is anything in there that look like 
// if so the user probably formatted the string already
if ( oldXpath.IndexOf("[") > 0 )
// Ok so there is no stuff in there like [local-name()=
// But we need that for the XpathQuery to work
// So reformat the query by putting [local-name()= before every node
// the user wants to select on
// Define the delimiter
string delimStr = "/";
char  delimiter = delimStr.ToCharArray();
// Now split the string
string Split = oldXpath.Split(delimiter);
// Define the stringbuilder to build the resultstring
System.Text.StringBuilder Builder = new System.Text.StringBuilder();
// Enumerate all the strings
foreach (string s in Split)
// If Lenght > 0 reformat the xpath query
if ( s.Length > 0 )