2014-08-01 5 views
1

Это висит приложение:Чтение XML с помощью XPathDocument с помощью NetworkStream

XPathDocument xPathDocument = new XPathDocument(networkStream); 

Я думаю, что это связано с XPathDocument все еще ждет данных, но как предотвратить это?

+0

Что именно вы хотите? XPathDocument (...) должен ждать, пока все данные XML не будут получены, чтобы создать действительный объект XPathDocument, правильно? – elgonzo

+0

Сделайте это в 'Task.Run' – Atomosk

+0

@Atomosk: что это поможет? приложение не остановится, но XML еще не готов. – Milek7

ответ

2

Из-за того, что сервер не закрыл соединение после отправки всего XML (соединение остается открытым для будущего общения) XPathDocument все еще ждет данных. Сервер не предоставляет никаких других данных, чтобы определить, завершена ли передача XML. Однако можно проверить, что весь XML получен с завершением корневого тега. XPathDocument dosen't ищет конец корневого тега, поэтому это решение немного сложно, но работает. Я читаю поток с помощью XmlReader и воспроизвожу XML с помощью XmlWriter, который записывает в StringWriter. В конце строки вывод из StringWriter сводится к StringReader, который читается XmlReader. И finnaly, XPathDocument считывает данные из этого XmlReader. Вот пример кода:

 XmlReader xmlReader = XmlReader.Create(networkStream); 
     StringWriter stringWriter = new StringWriter(); 
     XmlWriter xmlReadBuffer = XmlWriter.Create(stringWriter); 

     while (xmlReader.Read()) 
     { 
      switch (xmlReader.NodeType) 
      { 
       case XmlNodeType.XmlDeclaration: 
        xmlReadBuffer.WriteStartDocument(); 
        break; 
       case XmlNodeType.Element: 
        xmlReadBuffer.WriteStartElement(xmlReader.Name); 
        if (xmlReader.HasAttributes) 
         xmlReadBuffer.WriteAttributes(xmlReader, false); 
        if (xmlReader.IsEmptyElement) 
         goto case XmlNodeType.EndElement; 
        break; 
       case XmlNodeType.EndElement: 
        if (xmlReader.Depth == 0) 
        { 
         xmlReadBuffer.WriteEndElement(); 
         xmlReadBuffer.WriteEndDocument(); 
         goto EndXml; 
        } 
        xmlReadBuffer.WriteEndElement(); 
        break; 
       case XmlNodeType.Text: 
        xmlReadBuffer.WriteString(xmlReader.Value); 
        break; 
       default: 
        break; 
      } 
     } 

    EndXml: 
    xmlReadBuffer.Flush(); 

    XPathDocument xPathDocument = new XPathDocument(XmlReader.Create(new StringReader(stringWriter.ToString()))); 

Большое спасибо за elgonzo, который указал мне на это.

+0

Я знал, что вы можете это сделать :) Ваше решение оказалось несколько короче, чем я ожидал, когда мы вчера говорили в чате. Количество кода, необходимого для этого «обходного пути», довольно терпимо, на самом деле ... – elgonzo

Смежные вопросы