Есть большой XML файл. Порядка полугига. Его надо преобразовать в другой формат.
Есть ли готовые решения, которые не пытаются загрузить файл в память?
Нужно что-то чтобы читало его последовательно.
This software required Windows 95 or better...
So I installed Linux
Здравствуйте, hellas, Вы писали:
H>Есть большой XML файл. Порядка полугига. Его надо преобразовать в другой формат.
... H>Нужно что-то чтобы читало его последовательно.
SAX парсер тебе в руки.
Точно идёт в составе msxml.
expat тоже SAX поддерживает.
Здравствуйте, hellas, Вы писали:
H>Есть большой XML файл. Порядка полугига. Его надо преобразовать в другой формат. H>Есть ли готовые решения, которые не пытаются загрузить файл в память? H>Нужно что-то чтобы читало его последовательно.
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, hellas, Вы писали:
H>>Есть большой XML файл. Порядка полугига. Его надо преобразовать в другой формат. H>>Есть ли готовые решения, которые не пытаются загрузить файл в память? H>>Нужно что-то чтобы читало его последовательно.
CS>Вот это http://www.codeproject.com/cpp/HTML_XML_Scanner.asp я делал как раз для таких целей. CS>Это т.н. push parser — теоретически это самый быстрый способ потоковой обработки XML.
А можно пример обработки файла?
This software required Windows 95 or better...
So I installed Linux
Здравствуйте, hellas, Вы писали:
CS>>Вот это http://www.codeproject.com/cpp/HTML_XML_Scanner.asp я делал как раз для таких целей. CS>>Это т.н. push parser — теоретически это самый быстрый способ потоковой обработки XML.
H>А можно пример обработки файла?
Если я правильно понял вопрос...
Вот самый наипростейший файловый входной stream для сканера
struct file_istream: public markup::instream
{
FILE *f;
file_istream(const char* src): f(0) { f = fopen(...); }
virtual wchar_t get_char() { int t = fgetc(f); return (t == EOF)? 0 : t; }
};
Если в XML используется encoding отличный от ascii то
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, hellas, Вы писали:
H>>Есть большой XML файл. Порядка полугига. Его надо преобразовать в другой формат. H>>Есть ли готовые решения, которые не пытаются загрузить файл в память? H>>Нужно что-то чтобы читало его последовательно.
CS>Вот это http://www.codeproject.com/cpp/HTML_XML_Scanner.asp я делал как раз для таких целей. CS>Это т.н. push parser — теоретически это самый быстрый способ потоковой обработки XML.
Помоему это называется pull parser, нет?
Re: Большой XML файл.
От:
Аноним
Дата:
29.10.06 21:22
Оценка:
Здравствуйте, hellas, Вы писали:
H>Есть большой XML файл. Порядка полугига. Его надо преобразовать в другой формат. H>Есть ли готовые решения, которые не пытаются загрузить файл в память?
Лучше всего воспользоватся стандартными решениями. А стандартные решения это SAX парсеры и expat.
В MSXML 3 (вроде, может и раньше) и выше входит СОМ-базированный SAX парсер. xerces-c- чистый С++. Скорость великолепная у обоих — гарантирую, что парсер боттлнеком не станет. Думаю что на "пропарсить полгигабайта" уйдёт 30-60 сек (на типичном компьютере) — на обработку аутпута (пихать в БД?) времени наверняка уйдёт значительно больше. expat — произведение исскусства, но может показатся чересчур низкоуровневым.
С самоделками лучше не связыватся — ХМЛ парсер оттестировать — всем миром надо повозится, всякие энкодинги, всевозможные конструкции — даже в упомянутых парсерах кой-какие проблемы встречаются и кое-что не иплементировано. Кроме того, SAX для валидации инпута может пользоватся схемой.
Re[2]: Большой XML файл.
От:
Аноним
Дата:
29.10.06 21:52
Оценка:
Кстати, при написании SAX-клиента — удобно пользоватся стеком (в смысле структуры данных) — Sax start element -> stack push, Sax end element -> stack pop.
У меня даже есть генерический фреймворк для написания такого кода (задача легко генерализутся и позволяет большую часть имплементировать раз и навсегда). Выложил бы в опен соурс, но неудобно — код не "отточен", документации нет, кроме автора никто не разберётся, нынешний вариант работает только с майкрософтским SAX-ом (легко исправить). А на приведение в порядок времени, естественно, нет.
Здравствуйте, korzhik, Вы писали:
K>>К сожалению я не видел C++ версии для промышленного использования.
Есть ещё штука которая называется xmlbooster — генерирует XML парсеры. Для шарпа — даже бесплатно, для других языков — за деньги. В какую сторону это потом работает — не знаю, может и pull.
Leif — упоминаю для порядка из-за его несуразной дороговизны и runtime fee за каждый deployment (про fee — отдельный договор, за сколько-то (1500?) долларов уплаченных за лицензию вы можете только девелопить 1 год) — в нём раньше был XML Reader вроде нетовского. Потом он вроде исчезал — парсилось как в DOM-e, сразу в память и никаких вариантов — может обратно появился. Парсеры генерируемые им — С++ классы, репрезентирующие XML элементы. Какие-то странности — вроде как отдельный элемент из представления распарсенного файла вы можете получить только по значению (если в нем 100 000 и 100 МБ данных — немного неэффективно). Страшенные имена — читать никак. Часть парсера — в closed source DLL.
Мне раз пришлось заменять Leif на xerces-c DOM — код стал меньше (!), проще, легче и быстрее(!).
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, korzhik, Вы писали:
K>>>К сожалению я не видел C++ версии для промышленного использования.
А>Есть ещё штука которая называется xmlbooster — генерирует XML парсеры. Для шарпа — даже бесплатно, для других языков — за деньги. В какую сторону это потом работает — не знаю, может и pull.
Интересная штука, надо будет потестировать потом на наших задачах.
Здравствуйте, c-smile, Вы писали:
CS>Вот это http://www.codeproject.com/cpp/HTML_XML_Scanner.asp я делал как раз для таких целей. CS>Это т.н. push parser — теоретически это самый быстрый способ потоковой обработки XML.
А в чём причина того, что pull парсер быстрее push? В чём фишка?
В чём прикол организовывать цикл в пользовательском коде, в не в коде библиотеки?
Здравствуйте, remark, Вы писали:
R>Здравствуйте, c-smile, Вы писали:
CS>>Вот это http://www.codeproject.com/cpp/HTML_XML_Scanner.asp я делал как раз для таких целей. CS>>Это т.н. push parser — теоретически это самый быстрый способ потоковой обработки XML.
R>А в чём причина того, что pull парсер быстрее push? В чём фишка? R>В чём прикол организовывать цикл в пользовательском коде, в не в коде библиотеки?
Более естественный на мой взгляд интерфейс для работы с XML.
В принципе если прогнать SAX парсер и pull парсер впустую на каком нибудь большом файле, то разница будет мизерная, если вообще будет.
Выигрыш даётся засчёт более удобного интерфейса.
В моём приложении я использую expat, но было дело, тестировал c-smile pull parser.
Тестировал на 30Мб XML файле.
С expat парсинг и построение dom 3 сек
С pull почти 2 сек
То есть выигрыш приближался к 30%
Но, ещё раз замечу, это не сравнение скорости парсеров, а сравнение различных подходов, то есть для тестирования pull парсера пришлось менять всю обработку данных.
И в итоге получить выигрыш за счёт болле удобного интерфейса
Здравствуйте, korzhik, Вы писали:
K>Здравствуйте, remark, Вы писали:
R>>Здравствуйте, c-smile, Вы писали:
CS>>>Вот это http://www.codeproject.com/cpp/HTML_XML_Scanner.asp я делал как раз для таких целей. CS>>>Это т.н. push parser — теоретически это самый быстрый способ потоковой обработки XML.
R>>А в чём причина того, что pull парсер быстрее push? В чём фишка? R>>В чём прикол организовывать цикл в пользовательском коде, в не в коде библиотеки?
K>Более естественный на мой взгляд интерфейс для работы с XML. K>В принципе если прогнать SAX парсер и pull парсер впустую на каком нибудь большом файле, то разница будет мизерная, если вообще будет.
K>Выигрыш даётся засчёт более удобного интерфейса.
K>В моём приложении я использую expat, но было дело, тестировал c-smile pull parser. K>Тестировал на 30Мб XML файле.
K>С expat парсинг и построение dom 3 сек K>С pull почти 2 сек
K>То есть выигрыш приближался к 30%
K>Но, ещё раз замечу, это не сравнение скорости парсеров, а сравнение различных подходов, то есть для тестирования pull парсера пришлось менять всю обработку данных. K>И в итоге получить выигрыш за счёт болле удобного интерфейса
Но всё-таки суть в чём?
Удобный интерфейс не тянет на первопричину повышения производительности
Сходу приходит в голову следующее: pull-парсер за счёт ручного "управления" процессом позволяет делать меньше лишней работы. Т.е. например, не создавать объект с аттрибутами (копировать строку со значением аттрибута), если пользовательский код не будет анализировать и считывать аттрибуты. Т.о. часть лишней работы подавляется.
А в остальном, я пока не вижу какого принципиального отличия между моделями, которые могли бы как-то влиять на производительность.
Хотя вот сейчас я подумал, что Push-парсер тоже может не делать никакой лишней работы, пока пользователь не запросит. Например, если пользователь не обращается к какому-то аттрибуту, то его значение может не копироваться. Т.е. вся реальная работа только по запросу пользователя. Хотя наверное так не делают (точнее просто не сделано) в популярных парсерах.
Здравствуйте, remark, Вы писали:
R>Удобный интерфейс не тянет на первопричину повышения производительности
а почему нет
R>Сходу приходит в голову следующее: pull-парсер за счёт ручного "управления" процессом позволяет делать меньше лишней работы. Т.е. например, не создавать объект с аттрибутами (копировать строку со значением аттрибута), если пользовательский код не будет анализировать и считывать аттрибуты. Т.о. часть лишней работы подавляется. R>А в остальном, я пока не вижу какого принципиального отличия между моделями, которые могли бы как-то влиять на производительность.
и это тоже
R>Хотя вот сейчас я подумал, что Push-парсер тоже может не делать никакой лишней работы, пока пользователь не запросит. Например, если пользователь не обращается к какому-то аттрибуту, то его значение может не копироваться. Т.е. вся реальная работа только по запросу пользователя. Хотя наверное так не делают (точнее просто не сделано) в популярных парсерах.
Здравствуйте, korzhik, Вы писали:
R>>А в чём причина того, что pull парсер быстрее push? В чём фишка? R>>В чём прикол организовывать цикл в пользовательском коде, в не в коде библиотеки?
А вот тут тоже можно, пожалуйста, поподробнее.
Вот что я пока вижу.
1. Необходимость организовывать цикл вручную, вместо цикла один раз написанного и внесённого в библиотеку. Имхо это минус.
2. С полпинка можно попытаться, например, получить значение аттрибута у парсера, когда на самом деле парсим не аттрибут, а элемент. Имхо большой минус. В push модели отлов таких ошибок будет на стадии компиляции. Т.е. если мы попали в калбек elementStart(const String& elementName). Значит ни к каким аттрибутум доступ мы просто не получим.
Это относится по крайней мере к тому интерфейсы парсера, который я вижу сейчас.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, korzhik, Вы писали:
R>>>А в чём причина того, что pull парсер быстрее push? В чём фишка? R>>>В чём прикол организовывать цикл в пользовательском коде, в не в коде библиотеки?
R>А вот тут тоже можно, пожалуйста, поподробнее. R>Вот что я пока вижу. R>1. Необходимость организовывать цикл вручную, вместо цикла один раз написанного и внесённого в библиотеку. Имхо это минус. R>2. С полпинка можно попытаться, например, получить значение аттрибута у парсера, когда на самом деле парсим не аттрибут, а элемент. Имхо большой минус. В push модели отлов таких ошибок будет на стадии компиляции. Т.е. если мы попали в калбек elementStart(const String& elementName). Значит ни к каким аттрибутум доступ мы просто не получим. R>Это относится по крайней мере к тому интерфейсы парсера, который я вижу сейчас.
такие ошибки возможны, согласен.
pull парсер средство более низкоуровневое чем SAX. И наверняка SAX парсеры строятся на основе pull парсера. Более низкоуровневое средство требует более высокой дисциплины
Я, к сожалению не могу сейчас аргументированно доказать что вот прям pull парсинг крутая вещь.
Но на своей задаче я пробовал pull парсинг, это сделало код обработки проще и быстрее, вот всё что я могку сказать.
Наверно чтобы полностью разобраться, надо поставить какую то небольшую задачу и решить её с помощью двух подходов: SAX и pull
Re[4]: Большой XML файл.
От:
Аноним
Дата:
01.11.06 08:52
Оценка:
Здравствуйте, korzhik, Вы писали:
K>С expat парсинг и построение dom 3 сек K>С pull почти 2 сек
K>То есть выигрыш приближался к 30%
Мне такое сравнение кажется несовсем корректным: expat способен обрабатывать, мягко говоря, несколько больше ситуаций, чем упомянутый парсер. Доведите функционал этого парсера до того, что есть в expat-е (а меньше — это ещё не настоящий парсер) — и еще не известно, кто будет быстрее. Полноценный ХМЛ парсинг — больше чем разбор строки на элементы и аттрибуты, выудить же элемент или что-то в этом роде из файла (с известым заранее энкодингом) — можно и используя регулярные выражения, например — может и ещё быстрее получится. По моему вы разные вещи сравниваете.