Как прочитать большой XML-файл, не загружая его в память и не используя XElement - PullRequest
6 голосов
/ 12 февраля 2010

Я хочу прочитать большой XML-файл (100 + M). Из-за его размера я не хочу загружать его в память с помощью XElement. Я использую запросы linq-xml для анализа и чтения.

Какой лучший способ сделать это? Любой пример сочетания XPath или XmlReader с linq-xml / XElement?

Пожалуйста, помогите. Спасибо.

Ответы [ 3 ]

8 голосов
/ 12 февраля 2010

Да, вы можете комбинировать XmlReader с методом XNode.ReadFrom , см. Пример в документации, где C # используется для выборочной обработки узлов, найденных XmlReader, как XElement.

6 голосов
/ 17 августа 2013

Пример кода в документации 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();
                }
            }
        }
    }
1 голос
/ 12 февраля 2010

Просто имейте в виду, что вам придется читать файл последовательно, а ссылка на братьев и сестер или потомков будет в лучшем случае медленной, а в худшем - невозможной. В противном случае @MartinHonnn имеет ключ.

...