Подтвердить что ты не робот

Как лучше всего использовать XPath с очень большими XML файлами в .NET?

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Загрузка из Microsoft

Ответ 2

Файлы Gigabyte 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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

Ответ 9

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

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

Ответ 10

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

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