2010-08-06 70 views
0

這是週五,我的思想似乎已經轉移到週末思考。異步閱讀可能格式不正確的Xml

鑑於這種XML結構 -

<?xml version="1.0" encoding="utf-8"?> 
<results requiredAttribute="somedatahere"> 
    <entry> 
    <!-- Xml structure in here --> 
    </entry> 
    <entry> 
    <!-- Xml structure in here --> 
    </entry> 
    <entry> 
    <!-- Xml structure in here --> 
    </entry> 
</results> 

而這種代碼(砍倒在覈心代碼),它使用一個XmlReader來讀取數據,並異步地返回數據 -

  response = (HttpWebResponse)request.GetResponse(); 

      using (var reader = XmlReader.Create(response.GetResponseStream())) 
      { 
       Logger.Info("Collector: Before attempt to read data for {0}", url); 

       while (reader.Read()) 
       { 
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "entry") 
        { 
         var el = XElement.ReadFrom(reader) as XElement; 
         if (el != null) 
          yield return el; 
        } 
       } 
      } 

是什麼從屬性requiredAttribute中檢索值的最簡單方法是什麼?

要考慮的關鍵是我不想在任何時候讀取完整的xml文件,因爲文件可能非常大。此外,數據來自HttpStream,因此您無法始終保證數據完整,並且隨後外部結果元素格式良好。這似乎排除閱讀結果元素,然後遍歷它的子元素。

回答

1

堅持純粹基於XmlReader的方法,直到它遇到它會給你解析內容的畸形。

任何其他方法(XPathDocument,XElement,XmlDocument)都會嘗試先解析整個文檔,因此您只會得到適用的異常。

+0

很抱歉,但我看不出你的答案說明了使用屈服時,異步返回檢索到的數據返回屬性值的最簡單的方法? – ChoccyButton 2010-08-06 13:12:00

+0

@Choccy yield沒有任何關係,XML格式錯誤,XElement創建失敗。 – Richard 2010-08-06 16:07:56

+0

該代碼已被使用並且正常工作。如果您嘗試讀取結果元素,但似乎嘗試讀取整個元素,問題就來了。如果您忽略該元素並開始在入門元素級讀取,則讀取器每次只讀取1個條目,這對元素來說工作正常,但意味着您錯過了所需的屬性 – ChoccyButton 2010-08-08 08:58:22

0
if (reader.NodeType == XmlNodeType.Element) 
{ 
    if (reader.Name == "results") 
    { 
     if (reader.MoveToAttribute("requiredAttribute") && reader.ReadAttributeValue()) 
      yield return reader.Value; 
    } 
    if (reader.Name == "entry") 
    { 
     ... 
    } 
} 

測試程序

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Xml; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      foreach (object value in Read()) 
       Console.WriteLine(value); 
     } 
     catch (XmlException ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 

    static IEnumerable<object> Read() 
    { 
     using (var file = File.OpenRead("Test.xml")) 
     { 
      var reader = XmlReader.Create(file, new XmlReaderSettings { IgnoreComments = true }); 
      while (reader.Read()) 
      { 
       if (reader.NodeType == XmlNodeType.Element) 
       { 
        yield return reader.Name; 

        if (reader.Name == "results") 
        { 
         if (reader.MoveToAttribute("requiredAttribute") && reader.ReadAttributeValue()) 
          yield return reader.Value; 
        } 
       } 
      } 
     } 
    } 
} 
+0

這不起作用,因爲它試圖讀取結果元素,如果尚未關閉並且不允許讀者移動到入口元素,或者從我的測試中,它不起作用,無論如何,我可能會做錯什麼 – ChoccyButton 2010-08-08 09:00:01

+0

當然可以。看看編輯後的版本。 – Tergiver 2010-08-08 12:30:41

+0

好的,那麼我的代碼肯定有問題。我已經嘗試了你的建議,第二個如果從未被擊中,但它會進入第一個,如果它讀取完整的結果元素,所以讀者永遠不會進入入口元素 – ChoccyButton 2010-08-09 10:07:34