Как лучше всего использовать XPath с очень большими файлами XML в .NET? - PullRequest
17 голосов
/ 02 января 2009

Мне нужно выполнить некоторую обработку довольно больших XML-файлов (в данном случае они могут быть больше гигабайта), включая выполнение некоторых сложных запросов xpath. У меня проблема в том, что стандартным способом, которым я обычно делаю это через библиотеки System.XML, нравится загружать весь файл в память, прежде чем он что-либо с ним делает, что может вызвать проблемы с памятью для файлов такого размера.

Мне вообще не нужно обновлять файлы, просто читая их и запрашивая содержащиеся в них данные. Некоторые запросы XPath довольно сложны и проходят через несколько уровней отношений типа родитель-потомок - я не уверен, повлияет ли это на возможность использования потокового считывателя вместо загрузки данных в память в виде блока.

Один из способов понять, как это работает, - выполнить простой анализ с использованием потокового подхода и, возможно, обернуть операторы XPath в преобразования XSLT, которые я потом смогу выполнить по файлам, хотя это кажется немного запутанным.

С другой стороны, я знаю, что есть некоторые элементы, по которым запросы XPath не будут проходить, поэтому, я думаю, я мог бы разбить документ на серию более мелких фрагментов на основе его исходной древовидной структуры, которая, возможно, могла бы быть достаточно маленькой для обработки в памяти, не вызывая слишком много хаоса.

Я попытался объяснить свою цель здесь, так что, если я лаю совсем не по дереву с точки зрения общего подхода, я уверен, что вы, ребята, можете исправить меня ...

Ответы [ 10 ]

9 голосов
/ 04 апреля 2009

XPathReader - это ответ. Он не является частью среды выполнения C #, но доступен для загрузки из Microsoft. Вот статья MSDN .

Если вы создаете XPathReader с XmlTextReader, вы получаете эффективность потокового чтения с удобством выражений XPath.

Я не использовал его для файлов размером в гигабайт, но я использовал его для файлов размером в десятки мегабайт, чего обычно достаточно для замедления решений на основе DOM.

Цитата из приведенного ниже: «XPathReader предоставляет возможность выполнять XPath поверх документов XML в потоковом режиме».

Скачать с Microsoft

2 голосов
/ 16 февраля 2011

http://msdn.microsoft.com/en-us/library/bb387013.aspx имеет соответствующий пример, использующий XStreamingElement.

2 голосов
/ 03 января 2009

Гигабайт XML-файлов! Я не завидую вам этой задачей.

Есть ли способ, чтобы файлы могли быть отправлены лучше? Например. Они отправляются вам по сети - если они, то более эффективный формат может быть лучше для всех заинтересованных сторон. Чтение файла в базу данных - неплохая идея, но на самом деле это может занять очень много времени.

Я бы не стал делать все это в памяти, читая весь файл - если у вас не установлена ​​64-битная ОС и много памяти. Что делать, если файл становится 2, 3, 4 ГБ?

Еще одним подходом может быть чтение в файле XML и использование SAX для анализа файла и записи меньших файлов XML в соответствии с некоторым логическим разделением. Затем вы можете обработать эти с помощью XPath. Я использовал XPath на 20-30 МБ файлах, и это очень быстро. Первоначально я собирался использовать SAX, но думал, что попробую XPath, и был удивлен, насколько быстро это было. Я сэкономил много времени на разработку и, вероятно, потерял только 250 мс за запрос. Я использовал Java для анализа, но я подозреваю, что в .NET будет мало различий.

Я читал, что XML :: Twig (модуль Perl CPAN) был написан явно для обработки синтаксического анализа XPath на основе SAX. Вы можете использовать другой язык?

Это также может помочь https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-1044772.html

1 голос
/ 03 января 2009

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

1 голос
/ 02 января 2009

Как насчет того, чтобы просто прочитать все это в базе данных и затем работать с временной базой данных? Это может быть лучше, потому что тогда ваши запросы могут выполняться более эффективно с помощью TSQL.

1 голос
/ 02 января 2009

Похоже, вы уже пытались использовать XPathDocument и не смогли разместить проанализированный XML-документ в памяти .

В этом случае перед началом разделения файла (что в конечном итоге является правильным решением!) Вы можете попробовать использовать Saxon XSLT / XQuery. Он имеет очень эффективное представление загруженного XML-документа в памяти (модель "tinytree" ). Кроме того, Saxon SA (версия с поддержкой shema, которая не является бесплатной) имеет некоторые потоковые расширения . Подробнее об этом здесь .

1 голос
/ 02 января 2009

Для выполнения запросов XPath со стандартными классами .NET все дерево документов должно быть загружено в память, что может быть плохой идеей, если оно может занимать гигабайт. ИМХО XmlReader - хороший класс для обработки таких задач.

1 голос
/ 02 января 2009

Вы уже обрисовали свой выбор.

Либо вам нужно отказаться от XPath и использовать XmlTextReader, либо вам нужно разбить документ на управляемые куски, на которых вы можете использовать XPath.

Если вы выберете последнее, используйте XPathDocument, его ограничение только для чтения позволяет лучше использовать память.

0 голосов
/ 19 марта 2010

Поскольку в вашем случае размер данных может работать в Gbs, вы рассматривали возможность использования ADO.NET с XML в качестве базы данных. Кроме того, объем памяти не будет огромным.

Другим подходом было бы использование Linq to XML с использованием таких элементов, как XElementStream. Надеюсь, это поможет.

0 голосов
/ 02 января 2009

Вы пробовали XPathDocument? Этот класс оптимизирован для эффективной обработки запросов XPath.

Если вы не можете эффективно обрабатывать входные документы с помощью XPathDocument, вы можете рассмотреть возможность предварительной обработки и / или разделения входных документов с помощью XmlReader.

...