如何读取大型xml文件而不将其加载到内存中并使用XElement

hIp*_*pPy 6 xml xelement xpath linq-to-xml large-files

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

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

请帮忙.谢谢.

Mar*_*nen 8

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

  • 我认为`XNode.ReadFrom`文档页面上的示例代码中存在一个错误.声明`XElement el = XElement.ReadFrom(reader)as XElement;`应该是`XElement el = new XElement(reader.Name,reader.Value);`而不是.按原样,每两个'Child'元素中的第一个元素在它读取的XML文件中被跳过. (4认同)

Ken*_*itt 6

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但我发现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();
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 是的。第一个例子不起作用。它会读太多并跳过所有其他“Child” (2认同)