Пожалуйста, не используйте синтаксический анализ строк и регулярных выражений в XML. Это плохая идея. У вас может быть семантически идентичный XML с различным форматированием, и регулярное выражение и анализ на основе строк просто не справляются с этим.
Такие вещи, как унарные тэги и переменные переносы строк - эти фрагменты "говорят" одно и то же:
<root>
<sometag val1="fish" val2="carrot" val3="narf"></sometag>
</root>
<root>
<sometag
val1="fish"
val2="carrot"
val3="narf"></sometag>
</root>
<root
><sometag
val1="fish"
val2="carrot"
val3="narf"
></sometag></root>
<root><sometag val1="fish" val2="carrot" val3="narf"/></root>
Надеюсь, это прояснит, почему создание синтаксического анализатора на основе регулярных выражений / сложностей? К счастью, вам не нужно. Многие языки сценариев имеют по крайней мере один, иногда больше параметров синтаксического анализатора.
Как упоминалось в предыдущем постере - доступно xml_grep
. На самом деле это инструмент, основанный на Perl-библиотеке XML::Twig
. Однако он использует «выражения xpath», чтобы найти что-то, и проводит различие между структурой документа, атрибутами и «контентом».
например:.
xml_grep 'job' jobs.xml --text_only
Однако, в интересах лучшего ответа, вот пара примеров «накатить свои» на основе ваших исходных данных:
Первый способ:
Используйте twig handlers
, который ловит элементы определенного типа и воздействует на них. Преимущество такого способа заключается в том, что он анализирует XML «по ходу дела» и позволяет вам изменять его в полете, если это необходимо. Это особенно полезно для отбрасывания «обработанного» XML при работе с большими файлами, используя purge
или flush
:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new(
twig_handlers => {
'job' => sub { print $_ ->text }
}
)->parse( <> );
Который будет использовать <>
для получения ввода (переданного по каналу или указанного через командную строку ./myscript somefile.xml
) и его обработки - каждый элемент job
извлечет и напечатает любой связанный текст. (Возможно, вы захотите print $_ -> text,"\n"
вставить перевод строки).
Поскольку он соответствует элементам 'job', он также будет соответствовать вложенным элементам job:
<job>programming
<job>anotherjob</job>
</job>
Будет совпадать дважды, но вывести часть выходных данных также дважды. Тем не менее, вы можете выбрать /job
вместо этого, если хотите. Полезно - это позволяет вам, например, распечатайте и удалите элемент или скопируйте и вставьте элемент, модифицирующий структуру XML.
В качестве альтернативы - сначала выполнить синтаксический анализ, и 'print' на основе структуры:
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> root -> text;
Поскольку job
является вашим корневым элементом, все, что нам нужно сделать, это распечатать его текст.
Но мы можем быть немного более проницательными, ищем job
или /job
и печатаем это специально вместо:
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> findnodes('/job',0)->text;
Вы также можете использовать опцию XML::Twig
s pretty_print
для переформатирования вашего XML:
XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( <> ) -> print;
Существует множество вариантов формата вывода, но для более простого XML (такого как ваш) большинство будет выглядеть примерно одинаково.