【问题标题】:How to read large xml file without loading it in memory and using XElement如何读取大型 xml 文件而不将其加载到内存中并使用 XElement
【发布时间】:2011-01-16 00:46:10
【问题描述】:

我想读取一个大的 xml 文件 (100+M)。由于它的大小,我不想使用 XElement 将它加载到内存中。我正在使用 linq-xml 查询来解析和读取它。

最好的方法是什么?关于 XPath 或 XmlReader 与 linq-xml/XElement 组合的任何示例?

请帮忙。谢谢。

【问题讨论】:

    标签: xml xpath linq-to-xml large-files xelement


    【解决方案1】:

    是的,您可以将 XmlReader 与 method XNode.ReadFrom 结合使用,请参阅文档中的示例,该示例使用 C# 选择性地将 XmlReader 找到的节点作为 XElement 处理。

    【讨论】:

    • 太棒了。我正在开发一个将处理多个 200M XML 文件的应用程序,而 XDocument 正在杀死我。这取得了巨大的进步。谢谢。
    • 我认为XNode.ReadFrom 文档页面上的示例代码中存在错误。声明 XElement el = XElement.ReadFrom(reader) as XElement; 应该改为 XElement el = new XElement(reader.Name, reader.Value);。按原样,每两个“子”元素中的第一个在它读取的 XML 文件中被跳过。
    • 查看我的答案以获得适合我的代码;请参阅Jon Skeetthis answer,了解为什么不应混合使用两种“读取”方法。 [Jon 的回答没有明确提到 XNode.ReadFrom 方法,但我相信同样的问题也适用。]
    【解决方案2】:

    请记住,您必须按顺序读取文件,并且引用兄弟姐妹或后代将是最好的情况,最坏的情况是不可能的。否则@MartinHonnn 有钥匙。

    【讨论】:

      【解决方案3】:

      MSDN文档中XNode.ReadFrom方法的示例代码如下:

      class Program
      {
          static IEnumerable<XElement> StreamRootChildDoc(string uri)
          {
              using (XmlReader reader = XmlReader.Create(uri))
              {
                  reader.MoveToContent();
                  // Parse the file and display each of the nodes.
                  while (reader.Read())
                  {
                      switch (reader.NodeType)
                      {
                          case XmlNodeType.Element:
                              if (reader.Name == "Child")
                              {
                                  XElement el = XElement.ReadFrom(reader) as XElement;
                                  if (el != null)
                                      yield return el;
                              }
                              break;
                      }
                  }
              }
          }
      
          static void Main(string[] args)
          {
              IEnumerable<string> grandChildData =
                  from el in StreamRootChildDoc("Source.xml")
                  where (int)el.Attribute("Key") > 1
                  select (string)el.Element("GrandChild");
      
              foreach (string str in grandChildData)
                  Console.WriteLine(str);
          }
      }
      

      但是我发现示例中的StreamRootChildDoc方法需要修改如下:

          static IEnumerable<XElement> StreamRootChildDoc(string uri)
          {
              using (XmlReader reader = XmlReader.Create(uri))
              {
                  reader.MoveToContent();
                  // Parse the file and display each of the nodes.
                  while (!reader.EOF)
                  {
                      if (reader.NodeType == XmlNodeType.Element && reader.Name == "Child")
                      {
                          XElement el = XElement.ReadFrom(reader) as XElement;
                          if (el != null)
                              yield return el;
                      }
                      else
                      {
                          reader.Read();
                      }
                  }
              }
          }
      

      【讨论】:

      • 是的。第一个例子不起作用。它会读得太多并跳过所有其他“孩子”
      猜你喜欢
      • 2011-09-22
      • 1970-01-01
      • 2017-06-16
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      相关资源
      最近更新 更多