Как я могу создать структуру данных XML :: Simple, используя парсер Perl XML SAX? - PullRequest
3 голосов
/ 26 мая 2010

Сводка : Я ищу быстрый синтаксический анализатор XML (скорее всего, оболочку вокруг некоторого стандартного синтаксического анализатора SAX), который будет создавать структуру данных для каждой записи на 100% идентичную структуре, создаваемой XML :: Простой .

подробности :

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

Пример простого XML:

<root>
    <rec><f1>v1</f1><f2>v2</f2></rec>
    <rec><f1>v1b</f1><f2>v2b</f2></rec>
    <rec><f1>v1c</f1><f2>v2c</f2></rec>
</root>

И примерный код:

sub process_record { my ($obj, $record_hash) = @_; # do_stuff }
my $records = XML::Simple->XMLin(@args)->{root};
foreach my $record (@$records) { $obj->process_record($record) };

Поскольку все знают XML: Simple, ну, в общем, просто. И что еще более важно, он очень медленный и занимает много места в памяти - из-за того, что он является DOM-парсером и ему необходимо создавать / хранить 100% данных в памяти. Таким образом, это не лучший инструмент для анализа XML-файла, состоящего из большого количества небольших записей запись за записью.

Однако переписать весь код (который состоит из большого количества методов, похожих на «process_record») для работы со стандартным парсером SAX кажется большой задачей, не стоящей ресурсов, даже ценой жизни с XML: :. Простой

Я ищу существующий модуль, который, вероятно, будет основан на синтаксическом анализаторе SAX (или любом быстром с небольшим объемом памяти), который можно использовать для создания $record хеш-ссылок по одному на основе приведенного выше XML-кода, который может будет передан в $obj->process_record($record) и будет на 100% идентичен тому, что было бы в хеш-кодах XML :: Simple.

Мне все равно, какой интерфейс у нового модуля; например, нужно ли мне позвонить next_record() или дать ему код обратного вызова, принимающий запись.

Ответы [ 3 ]

7 голосов
/ 26 мая 2010

XML::Twig имеет метод упрощения , который можно вызвать для элемента XML, который согласно документам гласит:

Возвращает структуру данных, подозрительно похожую на XML :: Simple's

Вот пример:

use XML::Twig;
use Data::Dumper;

my $twig = XML::Twig->new(
    twig_handlers => {
        rec => \&rec,
    }
)->parsefile( 'data.xml' );


sub rec {
    my ($twig, $rec) = @_;
    my $data = $rec->simplify;
    say Dumper $data;
    $rec->purge;
}

NB. $ rec-> purge немедленно удаляет запись из памяти.

Выполнение этого с вашим примером XML дает следующее:

$VAR1 = {
          'f1' => 'v1',
          'f2' => 'v2'
        };

$VAR1 = {
          'f1' => 'v1b',
          'f2' => 'v2b'
        };

$VAR1 = {
          'f1' => 'v1c',
          'f2' => 'v2c'
        };

Что, я надеюсь, подозрительно похоже на то, что получается из XML :: Simple:)

/ I3az /

6 голосов
/ 27 мая 2010

Как автор XML :: Simple, я просто хотел бы исправить некоторые неправильные представления в вашем вопросе.

XML :: Simple не является синтаксическим анализатором DOM, фактически он вообще не является анализатором. Он делегирует все обязанности по синтаксическому анализу либо синтаксическому анализатору SAX, либо XML :: Parser. Скорость синтаксического анализа будет зависеть от того, какой модуль парсера используется по умолчанию в вашей системе. Когда вы запустите 'make test' для дистрибутива XML :: Simple, в выводе будет показан парсер по умолчанию.

Если в вашей системе по умолчанию используется синтаксический анализатор XML :: SAX :: PurePerl, то он будет медленным и, что еще более важно, с ошибками. В таком случае я бы порекомендовал установить либо XML :: Expat, либо XML :: ExpatXS для немедленного ускорения. (Какой бы парсер SAX ни устанавливался последним, с этого момента он будет использоваться по умолчанию).

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

Я понимаю ваши краткосрочные цели, но в качестве более долгосрочного решения я бы порекомендовал перенести ваш код в XML :: LibXML. Это DOM-парсер, но он очень быстрый, потому что вся основная работа выполняется на C. Лучшая из всех встроенных функций поддержки XPath делает его еще проще, чем XML :: Simple - см. эту статью .

0 голосов
/ 28 июня 2010

Взгляните на XML :: LibXML :: Reader .

...