Как постепенно загружать XML в C #? - PullRequest
4 голосов
/ 08 августа 2010

Мне нужно обрабатывать загруженные из ResponseStream асинхронные обратные вызовы XML постепенно.

Ответ есть:

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

схема, и мне нужно иметь способность обрабатывать <node>, прежде чем они завершатся.

Есть ли нормальный способ разобрать его с помощью стандартного .NET?

Ответы [ 3 ]

3 голосов
/ 08 августа 2010
System.Xml.XmlTextReader 

"Представляет читателя, который обеспечивает быстрый, не кэшированный, прямой доступ к данным XML."

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

Edit: Это быстрый взлом, но он показывает, что читатель на самом деле ленивый.

 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 голос
/ 08 августа 2010

Не вызывайте его при асинхронных обратных вызовах, вам не нужно (поверьте мне, это станет яснее ...).

ResponseStream будет загружаться по мере поступления информации.В случае небольшого (для довольно больших значений «small», я боюсь) потока, который не отправляется chunked, это будет, когда весь поток был загружен.Однако если поток передается с использованием кодировки передачи по частям (это то, что происходит в ASP.NET, если буферизация отключена или вызывается Response.Flush(), другие технологии веб-сервера имеют свои эквиваленты), тогда поток будет доступен напервый кусок.

Создайте XMLReader из ResponseStream, когда GetResponse () вернется.Он начнет обработку с первого доступного фрагмента и получит последующие фрагменты, когда они будут достаточно прозрачно поступать в ваш код.

Убедитесь, что работа с этими узлами на основе доступности фактически приносит пользу коду в дальнейшемлиния.Например, если вы выводите данные на консоль или форму, делайте это при обработке каждого узла (или небольшого пакета узлов), тогда как если вы создаете объекты из этих узлов, то yield return их, а не создание коллекции.

Теперь, очевидно, здесь важен вопрос о том, является ли веб-поток разделенным на части, а не код обработки.Если продюсер - другая сторона, которую нельзя убедить сделать это, вам нужно будет перейти на более низкий уровень в вашей обработке.Однако, если это так, то вполне вероятно, что это ложная оптимизация, так как вся обработка будет завершена до того, как они отправят первый байт, и это будет самая большая задержка.Действительно, если задержка для получения всего загруженного ответа является проблемой для вашего кода, то вам нужно , чтобы они начали отправлять куски, так как задержка даже при самом эффективном подходе с вашей стороны все равно будет слишком велика.

Для справки, я совсем недавно подтвердил, что при таком использовании XmlReader на WebResponse, работающем с кусочными данными (где я управлял как клиентским, так и серверным кодом, и мог запускать и отладчик, ипроверить порядок операций), обработка действительно выполняется, поскольку каждый блок доступен.

0 голосов
/ 08 августа 2010

Да, есть читатель, который вы можете использовать.По сути, идет по потоку, и генерирует событие n для каждого идентифицируемого им элемента (элемент, атрибут и т. Д.).

...