Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Регулярные выражения > Поиск и разбор блока тегов в XML


Автор: dron000 17.11.2009, 16:03
Добрый день!
Подскажите со следующей задачей, необходимо в xml  искать блоки тегов выдергивать содержимое:
(насчет внешнего совпадающего имени тэга и внутреннего это не опечатка - так и есть)
Код

<name>

<name>...</name>
<name1>...</name1>
<name2>...</name2>
<name3>...</name3>
<name4>...</name4>
<name5>...</name5>
...
</name>


К примеру 
Код

$reg =~|<name>
<name>(.*)</name>
<name1>(.*)</name1>
<name2>(.*)</name2>
<name3>(.*)</name3>
<name4>(.*)</name4>
<name5>(.*)</name5>
</name>|$1,$2,$3,$4,$5|ig

Долго и не работает. Имена и количество полей известны и постоянны, порядок следования постоянен.Есть какие-то методы поиска целых кусков?

Автор: Bulat 17.11.2009, 16:42
Цитата(dron000 @  17.11.2009,  16:03 Найти цитируемый пост)
Долго и не работает. Имена и количество полей известны и постоянны, порядок следования постоянен.Есть какие-то методы поиска целых кусков


А почему бы не заюзать стандартный XML-parser ?? Допустим XML::Simple, ну или что "потяжелее" - если не достаточно функциональности. smile

Автор: dron000 17.11.2009, 16:50
Подкинешь нормальную ссылку с описанием?

Автор: Bulat 17.11.2009, 17:01
Цитата(dron000 @  17.11.2009,  16:50 Найти цитируемый пост)
Подкинешь нормальную ссылку с описанием? 


http://search.cpan.org/~pajas/XML-LibXML-1.70/LibXML.pod - лично я использую оный smile Правда он "тяжелый", для себя можешь чего полегче на cpan'e поискать smile

Автор: ginnie 17.11.2009, 20:02
dron000, советую попробовать XML::Parser. Меня очень порадовала скорость обработки 300Мб XML-файлов.

Автор: dron000 17.11.2009, 21:44
Спасибо.Нашел XML-Simple вроде вполне подойдет только интересует вопрос можно ли там получаемую структуру как-то посмотреть, потому как если xml'ник  'сложной' структуры то не очень удобно будет писать. У меня вроде бы о больших объемах речь пока не идет но все таки интересно parser намного быстрей?

Автор: sir_nuf_nuf 17.11.2009, 21:54
dron000, сооветую попробовать XML::LibXML и XML::LibXML::Simple - очень надежные и мощные библиотеки. от Gnome =)

Автор: dron000 18.11.2009, 11:00
Делаю следующее:
Код

use XML::Simple; 
use Data::Dumper;

#готовим $my_xml

 my $xs = XML::Simple->new(ForceArray => 1, KeepRoot => 1); 
 my $ref= $xs->XMLin($my_xml);
 my $my_xml= $xs->XMLout($ref);
 print Dumper($ref);
 
# например 
 $ref1=$ref->{name}->[1]; 



Возникает ошибка: junk after document element at line 1, column 456, byte 456 at C:/perl/lib/XML/Parser.pm line 187,
Открыл пакет XML Simple 2.18 это как раз тело sub XMLin{},блок 

Код


 elsif(my $type = ref($target)) {
    if($type eq 'SCALAR') {
      return $self->parse_string($target, @_);
    }
    else {
      return $self->parse_fh($target, @_);
    }
  }


Как я понял проблем в этой  строке return $self->parse_fh($target, @_);
Кто нибудь сталкиваля с подобным?

Автор: Bulat 18.11.2009, 12:33
Цитата(dron000 @  18.11.2009,  11:00 Найти цитируемый пост)
#готовим $my_xml


а вот на это можно взглянуть?? smile

Автор: dron000 18.11.2009, 13:43
Да собственно  переменная $my_xml получает строку состоящую из блоков вида:
Код

<name>

<name>...</name>
<name1>...</name1>
<name2>...</name2>
<name3>...</name3>
<name4>...</name4>
<name5>...</name5>
...
</name>


Синтаксис проверял и в валидаторе и сам - ошибок нет.Или там какой-то особый формат должен быть?

Автор: Bulat 18.11.2009, 15:44
Код

#!/usr/bin/perl

use strict;

use XML::Simple; 
use Data::Dumper;
my $my_xml = "
<name>
<name>123</name>
<name1>321</name1>
<name2>432</name2>
<name3>543</name3>
<name4>654</name4>
<name5>765</name5>
</name>
";

 my $xs = XML::Simple->new(ForceArray => 1, KeepRoot => 1); 
 my $ref= $xs->XMLin($my_xml);
 my $my_xml1= $xs->XMLout($ref);
 print Dumper($ref);
 

 print $ref->{name} -> [0] -> {name2} -> [0], "\n";


обрати внимание на свой вариант - 

Цитата(dron000 @  18.11.2009,  11:00 Найти цитируемый пост)
 my $ref= $xs->XMLin($my_xml);
 my $my_xml= $xs->XMLout($ref);


не хорошо так писать.

Автор: dron000 18.11.2009, 15:49
К примеру  при 

Код

$my_xml=
'<name1>35434</name1>
<name2>dfdfdf</name2>';



происходит таже ошибка, если оставить только  '<name1>35434</name1> то можно обратиться $ref->{name1}->[0];  и работает без ошибок.

Добавлено через 8 минут и 26 секунд
Гы... smile  Вижу....совсем окасел тут... smile 

Автор: dron000 18.11.2009, 16:35
Заранее извиняюсь если вопрос тупой.А как обратиться если таких блоков несколько например два

Код

my $my_xml = "
<name>
<name>123</name>
<name1>321</name1>
<name2>432</name2>
<name3>543</name3>
<name4>654</name4>
<name5>765</name5>
</name>
<name>
<name>123</name>
<name1>321</name1>
<name2>432</name2>
<name3>543</name3>
<name4>654</name4>
<name5>765</name5>
</name>
";


Потому как такое обращение уже не прокатывает  print $ref->{name} -> [0] -> {name2} -> [0] -выдает аналогичную ошибку пакета...
Не понятно почему, ведь даж относительный адрес указанного элемента не меняется...или я чего-то не понимаю?

Автор: sir_nuf_nuf 18.11.2009, 19:27
Цитата(dron000 @  18.11.2009,  16:35 Найти цитируемый пост)
А как обратиться если таких блоков несколько например два

Никак. То что вы написали не является XML.

Изучите какой-нть простой мануал по XML - исчезнут такие вопросы.
Кстати как я помню,  в начале XML не допускаются никакие символы до первого тэга.

P.S.
Можно использовать XML::LibXML::Simple за место XML::Simple - интерфейс тот же, но более надежна.

Автор: dron000 18.11.2009, 22:20
Ну да, вот так лучше будет:

Код

my $my_xml = "
<name_all>
<name>
<name>123</name>
<name1>321</name1>
<name2>432</name2>
<name3>543</name3>
<name4>654</name4>
<name5>765</name5>
</name>
<name>
<name>123</name>
<name1>321</name1>
<name2>432</name2>
<name3>543</name3>
<name4>654</name4>
<name5>765</name5>
</name>
</name_all>
";


Автор: krypt3r 19.11.2009, 06:53
Ошибаетесь, ничем не лучше

Автор: Bulat 19.11.2009, 09:08
dron000, 

на самом деле, составление xml-файлов - некое правило...

во-первых у любого xml-файла в самом начале должно быть <?xml version="1.0" encoding="UTF-8"?>

"encoding="UTF-8"" - опционально.

Во-вторых любой xml-файл должен иметь root-узел.

Т.е. некий начальный тег, отличный от остальных

my $my_xml = qq{<?xml version="1.0" encoding="UTF-8"?>}.
qq{<root>}.
qq{<name>123</name>}.
qq{<name1>321</name1>}.
qq{<name2>432</name2>}.
qq{<name3>543</name3>}.
qq{<name4>654</name4>}.
qq{<name5>765</name5>}.
qq{</name>}.
qq{<name>}.
qq{<name>123</name>}.
qq{<name1>321</name1>}.
qq{<name2>432</name2>}.
qq{<name3>543</name3>}.
qq{<name4>654</name4>}.
qq{<name5>765</name5>}.
qq{</root>}
};

вот что-то подобное smile

Автор: dron000 19.11.2009, 09:32
Мне просто не хочется засовывать весь xml'ник там большая часть мне просто не нужна, вот и решил отрезать кусочек). Как я понимаю так работать тоже будет если просто оставить root-узел.

Автор: Bulat 19.11.2009, 11:58
Цитата(dron000 @  19.11.2009,  09:32 Найти цитируемый пост)
Мне просто не хочется засовывать весь xml'ник там большая часть мне просто не нужна, вот и решил отрезать кусочек). Как я понимаю так работать тоже будет если просто оставить root-узел. 


В том-то и дело, что все подобные библиотеки рассчитаны на то, что на входе абсолютно верные и цельные параметры.. Т.е. у всех вещей есть "обязательные" части.

Вообще, я просто написал пример, отразив в нем обязательные части любого xml-файла. Если не сработает - будем разбираться дальше. smile

Автор: dron000 19.11.2009, 14:32
Все ок, работает.Те части которые мне нужны и не совсем подходят под формат просто дополняю 'ручками'. Жаль в этих пакетах обработки ошибок толковой нет.

Автор: Bulat 19.11.2009, 17:06
Цитата(dron000 @  19.11.2009,  14:32 Найти цитируемый пост)
Жаль в этих пакетах обработки ошибок толковой нет. 


Если ты имеешь ввиду, обработки ошибок на отсутствие 
Код

<?xml version="1.0" encoding="UTF-8"?>
<root>
...
</root>


то совсем и не обязательно, чтобы они присутствовали... Если в твоем документе(файле и т.п.) отсутствуют эти части - значит на входе у тебя все что угодно, но не xml-данные(xml-файл)

В конце концов, без этих частей, твой файл может быть html-разметкой
Код

<name></name>
<table></table>


или мож вообще каким-нить конфигом апача  smile 

А мож еще что-то. smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)