从XML网络流中读取整个元素

时间:2012-02-21 13:17:58

标签: c# .net xml networking

我正在使用C#.NET 4.0编写网络服务器。有一个网络TCP / IP连接,我可以通过它连接完整的XML元素。他们定期到达,我需要立即处理它们。每个XML元素本身都是一个完整的XML文档,因此它有一个开放元素,几个子节点和一个结束元素。整个流没有单个根元素。所以当我打开连接时,我得到的是这样的:

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

然后一段时间后它继续:

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

等等。我需要一种方法来读取完整的XML字符串,直到状态元素完成。我不想用纯文本阅读方法这样做,因为我不知道数据的格式是什么。我无法等到整个流完成,正如其他地方经常描述的那样。我已经尝试过使用XmlReader类,但是它的文档很奇怪,方法无法解决,第一个元素丢失,发送第二个元素后,因为有两个根元素而发生XmlException。

5 个答案:

答案 0 :(得分:7)

试试这个:

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();
    }
}

答案 1 :(得分:1)

如果您将“一致性级别”更改为“片段”,则可以使用XmlReader

这是MSDN的一个(稍加修改)示例:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader reader = XmlReader.Create(streamOfXmlFragments, settings);

答案 2 :(得分:1)

您可以使用XElement.Load,这对于.net 3.5中新增的Xml元素片段的流式传输更有意义,并且还支持直接从流中读取。

查看System.Xml.Linq

我认为您可能仍然需要添加一些控制逻辑以便对您收到的邮件进行分区,但您也可以试一试。

答案 3 :(得分:0)

我不确定是否有内置功能。 我打开一个字符串生成器,填充它直到我看到</status>标记,然后使用普通的XmlDocument解析它。

答案 4 :(得分:0)

与dtb的解决方案没有实质性的区别,但是linqier

static IEnumerable<XDocument> GetDocs(Stream xmlStream)
{
    var xmlSettings = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment };
    using (var xmlReader = XmlReader.Create(xmlStream, xmlSettings))
    {
        var xmlPathNav = new XPathDocument(xmlReader).CreateNavigator();
        foreach (var selectee in xmlPathNav.Select("/*").OfType<XPathNavigator>())
            yield return XDocument.Load(selectee.ReadSubtree());
    }
}

我在PowerShell中遇到了类似的问题,但提问者的问题是在C#中,所以我试图翻译它(并验证它是否有效)。 Here是我找到线索的地方让我超越了最后的小障碍(“...... XPathDocument通过创建一个”透明“的根节点并保留它的碎片的方式。我说它是透明的,因为你的XPath查询可以使用根节点轴并仍然可以正确地解析为片段......“)

我正在使用的XML片段恰好是小的。如果你有更大的块,你可能想要查看XStreamingElement - 它可以增加很多复杂性,但是在处理大量XML时也会大大减少内存使用。