Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read entire elements from an XML network stream

I am writing a network server in C# .NET 4.0. There is a network TCP/IP connection over which I can receive complete XML elements. They arrive regularly and I need to process them immediately. Each XML element is a complete XML document in itself, so it has an opening element, several sub-nodes and a closing element. There is no single root element for the entire stream. So when I open the connection, what I get is like this:

<status>
    <x>123</x>
    <y>456</y>
</status>

Then some time later it continues:

<status>
    <x>234</x>
    <y>567</y>
</status>

And so on. I need a way to read the complete XML string until a status element is complete. I don't want to do that with plain text reading methods because I don't know in what formatting the data arrives. I can in no way wait until the entire stream is finished, as is often described elsewhere. I have tried using the XmlReader class but its documentation is weird, the methods don't work out, the first element is lost and after sending the second element, an XmlException occurs because there are two root elements.

like image 257
ygoe Avatar asked Feb 21 '12 13:02

ygoe


3 Answers

Try this:

var settings = new XmlReaderSettings
{
    ConformanceLevel = ConformanceLevel.Fragment
};

using (var reader = XmlReader.Create(stream, settings))
{
    while (!reader.EOF)
    {
        reader.MoveToContent();

        var doc = XDocument.Load(reader.ReadSubtree());

        Console.WriteLine("X={0}, Y={1}",
            (int)doc.Root.Element("x"),
            (int)doc.Root.Element("y"));

        reader.ReadEndElement();
    }
}
like image 56
dtb Avatar answered Nov 14 '22 19:11

dtb


If you change the "conformance level" to "fragment", it might work with the XmlReader.

This is a (slightly modified) example from MSDN:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader reader = XmlReader.Create(streamOfXmlFragments, settings);
like image 24
dillenmeister Avatar answered Nov 14 '22 19:11

dillenmeister


You could use XElement.Load which is meant more for streaming of Xml Element fragments that is new in .net 3.5 and also supports reading directly from a stream.

Have a look at System.Xml.Linq

I think that you may well still have to add some control logic so as to partition the messages you are receiving, but you may as well give it a go.

like image 1
Anastasiosyal Avatar answered Nov 14 '22 19:11

Anastasiosyal