2010-08-06 68 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