Сортировка и объединение документов XML с помощью Perl / XML :: Twig - PullRequest
1 голос
/ 21 декабря 2011

У меня есть много XML-файлов в каталоге, которые нужно отсортировать и объединить в один файл.Файлы форматируются следующим образом:

File1.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypea>

File2.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>112</docnumber>
  </header>
</doctypea>

File3.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypeb>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypeb>

File4.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypeb>
  <header someattr="1">
    <docnumber>112</docnumber>
  </header>
</doctypeb>

Все файлы в этом каталоге должны быть отсортированы последующие критерии:

  1. номер документа
  2. doctype (a или b)

Затем их необходимо объединить, чтобы выходной файл выглядел следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypea>
<doctypeb>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypeb>
<doctypea>
  <header someattr="1">
    <docnumber>112</docnumber>
  </header>
</doctypea>
<doctypeb>
  <header someattr="1">
    <docnumber>112</docnumber>
  </header>
</doctypeb>

Для этого я пытаюсь использовать XML: Twig в Perl.Пока у меня есть следующий код:

use XML::Twig;

my $xmldir = "/xmlfiles";
my $parser = XML::Twig->new(pretty_print => 'indented');

opendir(DIR, "$xmldir");
my @FILES= readdir(DIR);
closedir(DIR);

foreach (@FILES) {
        if ($_ ne "." && $_ ne "..") {
                print "reading file: $xmldir/$_\n";
                $parser->parsefile("$xmldir/$_");
        }
}

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

1.Как получить значение корневого элемента («doctypea» или «doctypeb»)?

2.Я полагаю, что мне нужно это (1) для парсодирования до поля номера документа?

Мой план состоит в том, чтобы построить что-то вроде has с типом doctype% для сортировки, я не уверенСамый простой способ объединить их с этим.

Цените любые советы!

Ответы [ 2 ]

5 голосов
/ 21 декабря 2011

Ниже приведен небольшой пример, с которого следует начать.Он показывает, как получить данные из XML-файла, аналогичного вашему (я исправил теги, чтобы они соответствовали, и указал someattr значение, чтобы получить действительный XML).Вы можете использовать подобный подход для сбора необходимых данных и вывода.

use XML::Twig;

XML::Twig->new(twig_handlers => {
    '/*'        => sub { print $_->gi;           },     # doctypea
    'docnumber' => sub { print $_->trimmed_text; },     # 111
})->parse(\*DATA);    # use parsefile('xxx.xml') to parse a file

__DATA__
<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypea>
1 голос
/ 21 декабря 2011

Как заметил daxim, ваши файлы не являются допустимыми XML, но вы можете обрабатывать их с помощью регулярных выражений. Если файлы не слишком большие, вы можете разбить файлы на отдельные строки, которые вы сортируете по их содержанию.

use File::Slurp qw( read_dir ) ;
my $xmldir=".";
my %files = map {
        s/^.*$//m; 
        /<doctype([ab])>/; my $x=ord($1) - ord('a');
        /<docnumber>(\d+)</docnumber>/; $x += 10*$2;
        $x => $_
    } read_dir($xmldir);
print join("", map { $files{$_} } sort keys %files);

Я не отлаживал этот код. Также print join("", values %files); может работать.

...