0
votes

I am currently developing a custom pipeline component for an XML document flow, where the root node and the first child of that root node needs to be stripped off, leaving only the second child node left (which is now the new root node).

I'm using XDocument as container class for the XML document. Ive written some code which gets the second child node, and creates a new XML document with that node as the root, thus removing the two undesired nodes from the picture.

XNode secondChild = xDoc.Root.Elements().First().NextNode;
XDocument outputXml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
                                             secondChild);

But when I test this setup in Biztalk, I only get an empty document back as a response. It seems to create an empty XML document which is then returned.

To give an example of what I want to achieve:

I want to go from a structure like this:

<Root>
<FirstChild></FirstChild>
<SecondChild></SecondChild>
</Root>

To a simple structure like this:

<SecondChild></SecondChild>

The full code of the Execute method in the pipeline:

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            var originalStream = pInMsg.BodyPart.GetOriginalDataStream();
            XDocument xDoc; //new XML document to return as the message
            using (XmlReader reader = XmlReader.Create(originalStream))
            {
                reader.MoveToContent();
                xDoc = XDocument.Load(reader);
            }

            XNode secondChild = xDoc.Root.Elements().First().NextNode;
            XDocument outputXml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
                                             secondChild);

            // Returning stream, serializing the XML to byte array
            byte[] output = System.Text.Encoding.ASCII.GetBytes(outputXml.ToString());
            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Write(output, 0, output.Length);
            memoryStream.Position = 0;
            pInMsg.BodyPart.Data = memoryStream; //overwrite the original message with the modified stream

            return pInMsg;
        }

Looking around on SO I found this answer, which I tried to follow, but as mentioned it produces an empty document. Is there a different option, other than simply creating a new XDocument?

1
I tried your code, if you just use outputXml.Save("someFilePath") it works, also if i save from memory stream to file `using (FileStream fs = new FileStream("someFilePath", FileMode.Create)) {memoryStream.CopyTo(fs);} it gives correct output, so you need to inspect the subsequent code blocks. Can you copy here the file saving code? - Jeshwel
That's interesting. The pipeline component is implemented in the decode stage of a pipeline deployed to Biztalk and set on a receive location. A send port is then filtering on the associated receive port and outputting the file to local folder. I'm not sure where in this flow the content of the message is being removed. - Leth
So...sorry, why are you even doing this? Never use XmlDocument or XDocument in a custom component. What you describe looks trivially easy to do with a Map. Why all the unnecessary complication of code? - Johns-305
What John said, just create schema that matches the output you want and create a map that maps from the original payload to to desired output. But anyway, make sure you rewind the stream of your output before exiting the pipeline component. - Dijkgraaf

1 Answers

0
votes

If you develop a regular map to edit the document you can place it in the maps section of the receive port. It's simpler to create, test, and install than a pipeline component.

enter image description here