Синтаксический анализ XML-файла в Perl - сохранение последовательности - PullRequest
2 голосов
/ 06 сентября 2010

Структура XML выглядит следующим образом:

<Entities>
    <Entity>
        <EntityName>.... </EntityName>
        <EntityType>.... </EntityType>
        <Tables>
            <DataTables>
                <DataTable>1</DataTable>
                <DataTable>2</DataTable>
                <DataTable>3</DataTable>
                <DataTable>4</DataTable>
            </DataTables>
            <OtherTables>
                <OtherTable>5</OtherTable>
                <OtherTable>6</OtherTable>
            </OtherTables>
        </Tables>
    </Entity>
.
.
.
</Entities>

Мне нужно проанализировать файл на основе выбранного имени объекта и извлечь все таблицы, в частности, в указанном порядке.Как мне это сделать в Perl и какой модуль следует использовать?

Ответы [ 4 ]

8 голосов
/ 06 сентября 2010

Мой любимый модуль для анализа XML в Perl: XML::Twig ( учебник ).

Пример кода:

use XML::Twig;

my $twig = XML::Twig->new(
    twig_handlers => {
        #calls the get_tables method for each Entity element
        Entity    => sub {get_tables($_);},
    },
    pretty_print  => 'indented',                # output will be nicely formatted
    empty_tags    => 'html',                    # outputs <empty_tag />
    keep_encoding => 1,
);

$twig->parsefile(xml-file);
$twig->flush;

sub get_tables {
    my $entity = shift;

    #Retrieves the sub-elements of DataTables
    my @data_tables = $entity->first_child("Tables")->children("DataTables");
    #Do stuff with the DataTables

    #Retrieves the sub-elements of OtherTables
    my @other_tables = $entity->first_child("Tables")->children("OtherTables");
    #Do stuff with the OtherTables

    #Flushes the XML element from memory
    $entity->purge;
}
2 голосов
/ 06 сентября 2010

Порядок документов равен , определен как

Существует порядок, порядок документов , определенный на всех узлах вдокумент, соответствующий порядку, в котором первый символ представления XML каждого узла встречается в представлении XML документа после раскрытия общих сущностей.Таким образом, корневой узел будет первым узлом.Элемент узлов встречается раньше своих детей.Таким образом, порядок документов упорядочивает узлы элементов в порядке появления их начального тега в XML (после раскрытия сущностей).

Другими словами, порядок, в котором вещи встречаются в документе XML,Модуль XML :: XPath выдает результаты в порядке документа.Например:

#! /usr/bin/perl

use warnings;
use strict;

use XML::XPath;

my $entity_template = "/Entities"
                    . "/Entity"
                    .   "[EntityName='!!NAME!!']"
                    ;

my $tables_path = join "|" =>
                  qw( ./Tables/DataTables/DataTable
                      ./Tables/OtherTables/OtherTable );

my $xp = XML::XPath->new(ioref => *DATA);

foreach my $ename (qw/ foo bar /) {
  print "$ename:\n";
  (my $path = $entity_template) =~ s/!!NAME!!/$ename/g;
  foreach my $n ($xp->findnodes($path)) {
    foreach my $t ($xp->findnodes($tables_path, $n)) {
      print $t->toString, "\n";
    }
  }
}

__DATA__

Первое выражение ищет элементы <Entity>, каждый из которых имеет дочернего элемента <ElementName>, чье строковое значение является выбранным именем объекта.Оттуда мы ищем <DataTable> или <OtherTable>.

При заданном вводе

<Entities>
    <Entity>
        <EntityName>foo</EntityName>
        <EntityType>type1</EntityType>
        <Tables>
            <DataTables>
                <DataTable>1</DataTable>
                <DataTable>2</DataTable>
            </DataTables>
            <OtherTables>
                <OtherTable>3</OtherTable>
                <OtherTable>4</OtherTable>
            </OtherTables>
        </Tables>
    </Entity>
    <Entity>
        <EntityName>bar</EntityName>
        <EntityType>type2</EntityType>
        <Tables>
            <DataTables>
                <DataTable>5</DataTable>
                <DataTable>6</DataTable>
            </DataTables>
            <OtherTables>
                <OtherTable>7</OtherTable>
                <OtherTable>8</OtherTable>
            </OtherTables>
        </Tables>
    </Entity>
</Entities>

на выходе получается

foo:
<DataTable>1</DataTable>
<DataTable>2</DataTable>
<OtherTable>3</OtherTable>
<OtherTable>4</OtherTable>
bar:
<DataTable>5</DataTable>
<DataTable>6</DataTable>
<OtherTable>7</OtherTable>
<OtherTable>8</OtherTable>

Для извлечения строковых значений(«внутренний текст»), измените $tables_path на

my $tables_path = ". / Tables / DataTables  / DataTable  / text() |
                   . / Tables / OtherTables / OtherTable / text()";

Да, это повторяется, потому что XML :: XPath реализует XPath 1.0 .

Вывод:

foo:
1
2
3
4
bar:
5
6
7
8
0 голосов
/ 15 сентября 2010

Я предпочитаю XML :: LibXML , что позволяет вам (и мне) использовать XPath для выбора элементов.

Возможно, вы захотите взглянуть на сценарий , с которым я написалэто .

0 голосов
/ 06 сентября 2010

См. : xml-simple

, прежде чем использовать его, имейте в виду, некоторые моменты, такие как

XML :: Simple может представить простой API, потому что он делает некоторые предположения от вашего имени. К ним относятся:

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

Для анализа на основе событий используйте SAX (не пытайтесь писать новый код для API обработчика XML :: Parser - он устарел).

Для синтаксического анализа на основе дерева вы можете выбирать между подходом «Perlish» XML :: Twig и несколькими реализациями DOM на основе стандартов - желательно с поддержкой XPath.

источник : XML-Simple

Подробнее о Perl-XML см. Perl-XML

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...