none
Convert string xml into xml inside a pipeline

    Question

  • Hi all,
     
    I am stucked with one issue where I have One Main XML file having one Field Element which is of string type and contains XML String. For Example
    <ms0:Test xmlns:ms0="http://TestStringPipe.Main">
      <FField>&lt;ns0:Children xmlns:ns0="http://TestStringPipe.Child;
      &lt;FName&gt;FName_0&lt;/FName&gt;
      &lt;LName&gt;LName_0&lt;/LName&gt;
    &lt;/ns0:Children&gt;</FField>
    </ms0:Test>


    Now I want to get only
    &lt;ns0:Children xmlns:ns0="http://teststringpipe.child/;
      &lt;FName&gt;FName_0&lt;/FName&gt;
      &lt;LName&gt;LName_0&lt;/LName&gt;
    &lt;/ns0:Children&gt;

    as an XML file through pipeline and I am also having schema of it
    Can It be done?

    Thanks

    Nikhil
    Friday, March 06, 2009 11:11 AM

Answers

  • Hi there,

    Create a custom pipeline component and extract the inner text of your field into, and use the HttpUtility.HtmlDecode method to decode it into the proper XML from what's in the FField. You need a reference to System.Web to be able to use HttpUtility.HtmlDecode. After that assign the results back to the body of the body part of the message, and promoted the message type.

    Your code would look similar to this (sorry I don't have more time to create the full code):

    ---get stream from body part of message first as per usual pipeline custom component norm then:

     XmlDocument xDoc1 = new XmlDocument();
    XmlNamespaceManager xNSMan = new XmlNamespaceManager(xDoc1.NameTable);
    xNSMan.AddNamespace("ms0", "http://TestStringPipe.Main");
    xDoc1.Load(...); --load from body part's stream
    ... = HttpUtility.HtmlDecode(xDoc1.SelectSingleNode("/ms0:Test/FField", xNSMan).InnerText); --load this back into body part stream

    --promote the message type

    Thiago Almeida - http://connectedthoughts.wordpress.com
    • Marked as answer by NIKHIL _ Wish Tuesday, March 10, 2009 1:44 PM
    Friday, March 06, 2009 12:03 PM
  • Thiago's solution would work, but one has to be careful with this approach as you will be loading each message to memory in the pipeline.
    If you have low volume and small messages this would be just fine, if you have high volume and/or large messages this is not ideal.

    Unfortunately the alternative is not as simple (but not that complex either) - you will have to resort to steaming pipeline processing -
    There are already a few samples on the blogsphere, I might be tempted to publish one at some point, but generally you need to wrap the message body stream in your own stream and replace the message's stream in your own.

    Your stream would then override the stream's read method (all other stream method can simply be passed through to the undelying stream) and you will perform all your logic there - generally you would want to
    a) skip the wrapping XML content - so - when the stream is read, you keep reading the underlying stream until you reach the actual content you wish to process; only then you return the buffer
    b) when returnign the buffer - unescape the content to look like XML.

    I know it sounds complex, I can never describe it clearly enough :-( but the Professional BizTalk 2006 book by Darren Jefford, Kevin Smith and Ewan Fairweather has a good section on this; you can read some of it here (but you really ought to buy it as well! :-))



    Yossi Dahan | [To help others please mark replies as answers if you found them helpful]
    • Marked as answer by NIKHIL _ Wish Tuesday, March 10, 2009 1:44 PM
    Tuesday, March 10, 2009 9:10 AM

All replies

  • Friday, March 06, 2009 11:18 AM
  • Hi there,

    Create a custom pipeline component and extract the inner text of your field into, and use the HttpUtility.HtmlDecode method to decode it into the proper XML from what's in the FField. You need a reference to System.Web to be able to use HttpUtility.HtmlDecode. After that assign the results back to the body of the body part of the message, and promoted the message type.

    Your code would look similar to this (sorry I don't have more time to create the full code):

    ---get stream from body part of message first as per usual pipeline custom component norm then:

     XmlDocument xDoc1 = new XmlDocument();
    XmlNamespaceManager xNSMan = new XmlNamespaceManager(xDoc1.NameTable);
    xNSMan.AddNamespace("ms0", "http://TestStringPipe.Main");
    xDoc1.Load(...); --load from body part's stream
    ... = HttpUtility.HtmlDecode(xDoc1.SelectSingleNode("/ms0:Test/FField", xNSMan).InnerText); --load this back into body part stream

    --promote the message type

    Thiago Almeida - http://connectedthoughts.wordpress.com
    • Marked as answer by NIKHIL _ Wish Tuesday, March 10, 2009 1:44 PM
    Friday, March 06, 2009 12:03 PM
  • Thiago's solution would work, but one has to be careful with this approach as you will be loading each message to memory in the pipeline.
    If you have low volume and small messages this would be just fine, if you have high volume and/or large messages this is not ideal.

    Unfortunately the alternative is not as simple (but not that complex either) - you will have to resort to steaming pipeline processing -
    There are already a few samples on the blogsphere, I might be tempted to publish one at some point, but generally you need to wrap the message body stream in your own stream and replace the message's stream in your own.

    Your stream would then override the stream's read method (all other stream method can simply be passed through to the undelying stream) and you will perform all your logic there - generally you would want to
    a) skip the wrapping XML content - so - when the stream is read, you keep reading the underlying stream until you reach the actual content you wish to process; only then you return the buffer
    b) when returnign the buffer - unescape the content to look like XML.

    I know it sounds complex, I can never describe it clearly enough :-( but the Professional BizTalk 2006 book by Darren Jefford, Kevin Smith and Ewan Fairweather has a good section on this; you can read some of it here (but you really ought to buy it as well! :-))



    Yossi Dahan | [To help others please mark replies as answers if you found them helpful]
    • Marked as answer by NIKHIL _ Wish Tuesday, March 10, 2009 1:44 PM
    Tuesday, March 10, 2009 9:10 AM
  • Yossi makes a great point that needs to be taken into consideration with every custom pipeline component. I was going by the sample message Nikhil, but that might not be the message size in the final solution - thanks Yossi!
    Thiago Almeida - http://connectedthoughts.wordpress.com
    Tuesday, March 10, 2009 8:00 PM