如何在C#中逐步加载XML?

时间:2010-08-08 07:44:32

标签: c# xml progressive-download

我需要逐步处理来自ResponseStream的Async回调XML加载。

回复有:

  <root>
     <node ...>
        .....
     </node>
     <node />
     ...
  </root>

架构,我需要在能力过程<node>完成之前进行处理。

是否有使用标准.NET解析它的正常方法?

3 个答案:

答案 0 :(得分:3)

System.Xml.XmlTextReader 

“表示提供对XML数据的快速,非缓存,仅向前访问的读者。”

http://msdn.microsoft.com/en-us/library/system.xml.xmltextreader.aspx

编辑: 这是一个快速的黑客,但它确实表明读者实际上是懒惰的。

 public class XmlTextReaderTest
    {
        public void RunTest()
        {
            var fs = new XmlTextReader(new Fs(@"c:\TestXml.xml"));
            while (fs.Read())
                File.AppendAllText(@"c:\xLog.txt", "Processing node..." + Environment.NewLine);
        }
    }

    public class Fs : FileStream
    {
        public Fs(string path)
            : base(path, FileMode.Open)
        {

        }

        public override int Read(byte[] array, int offset, int count)
        {
            File.AppendAllText(@"c:\xLog.txt", "Reading from stream..." + Environment.NewLine);
            var ans = base.Read(array, offset, count);
            return ans;
        }
}

答案 1 :(得分:1)

不要在异步回调上调用它,你不需要(相信我,这会更清楚......)。

当信息可用时,ResponseStream将加载。如果一个小的(对于非常大的“小”,我害怕)流量没有被发送分块,这将是整个流下载后的情况。但是,如果使用分块传输编码发送流(这是在ASP.NET中发生的情况,如果关闭缓冲或调用Response.Flush(),则其他Web服务器技术具有相应的功能)然后流将可用在第一块。

当GetResponse()返回时,从ResponseStream创建XMLReader。它将从第一个可用的块开始处理,并在它们非常透明地到达您的代码时获得后续块。

确保您在可用的基础上处理这些节点实际上有利于代码的进一步发展。例如。如果要输出到控制台或表单,请在处理每个节点(或一小批节点)时执行此操作,而如果要从这些节点创建对象,则yield return它们而不是构建集合。

现在,重要的是网络流是否被分块,而不是您的处理代码。如果生产者是另一方无法说服的人,那么您需要在处理中降低到较低级别。然而,如果是这种情况,那么这样做很可能是错误的优化,因为整个处理将在它们发送第一个字节之前完成,这就是最大的延迟。实际上,如果下载整个响应的延迟对您的代码来说是一个问题,那么您需要他们开始发送分块,因为即使是最有效的方法,延迟也会太大

为了记录,我最近确认在WebResponse上使用XmlReader处理分块数据(我控制了客户端和服务器代码,并且可以在调试器中运行并检查操作顺序),处理确实在每个块可用时完成。

答案 2 :(得分:0)

是的,有一个读者可以使用。基本上沿着流并为它标识的每个元素(元素,属性等)抛出一个事件。