Пожалуйста, не используйте синтаксический анализ на основе строк и регулярных выражений в XML. Это плохая идея. Вы можете иметь семантически идентичный XML с различным форматированием, а регулярное выражение и анализ на основе строк просто не могут справиться с ним.
Такие вещи, как унарные теги и перенос переменных строк - эти фрагменты «говорят» одно и то же:
Надеюсь, это дает понять, почему создание парсера с регулярным выражением / линией затруднено ? К счастью, вам не нужно. Многие языки сценариев имеют как минимум один, а иногда и более синтаксический анализ.
Как уже упоминался предыдущий плакат - xml_grep
. Это инструмент, основанный на библиотеке XML::Twig
perl. Однако то, что он делает, это использовать выражения «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"
вставить строку перевода).
Поскольку он совпадает с элементами «задания», он также будет соответствовать на вложенных элементах задания:
programming
anotherjob
будет совпадать дважды, но дважды напечатать часть вывода. Однако, если вы предпочитаете, вы можете выбрать /job
. Использование - это позволяет вам, например. распечатать и удалить элемент или скопировать и вставить одно изменение структуры XML.
Альтернативно - сначала проанализируйте и «напечатайте» на основе структуры:
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 (например, вашего) большинство будет выглядеть очень похоже.
Вы можете использовать списочное понимание для этого:
karak = [['INFO100','C'],['INFO132','B'],['INFO233','C'],['ECON218','A']]
info_items = [item for item in karak if item[0].startswith("INFO")]
econ_items = [item for item in karak if item[0].startswith("ECON")]
print(info_items)
print(econ_items)
Относительно второй части: Что предполагается вернуть, если emnenivå меньше 100? У вас есть пункты INFO с двузначными числами?
РЕДАКТИРОВАТЬ: Чтобы сопоставить INFO только с уровнем 100 или 200, вы можете использовать первую цифру из emnenivå
в качестве отличительного фактора. И вы получите первую emnenivå
цифру, преобразовав ее в строку и используя index = 0, например: str(emnenivå)[0]
. Пример кода:
emnenivå = 123
print("\nExact match for emnenivå={}:".format(emnenivå))
info_items_exact = [item for item in karak if item[0].startswith("INFO{}".format(str(emnenivå)[0]))]
print(info_items_exact)
emnenivå = 200
print("\nExact match for emnenivå={}:".format(emnenivå))
info_items_exact = [item for item in karak if item[0].startswith("INFO{}".format(str(emnenivå)[0]))]
print(info_items_exact)