Forum Webscript.Ru

Программирование => Perl => Тема начата: GrAfF от 24 Января 2004, 15:58:21

Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 24 Января 2004, 15:58:21
Hi!
Задача такенная: нужно парсить XML. По идее, можно обойтись без модулей, скрипт-то всего на строк десять. Но уперся в большие глюки, руки, видимо, на NFS чуть покривил. Об джойстик. ;)

Есть типа XML:

   NaME
   BODY
   Боди
текста.

   
      AUTORNAME
      MAIL
   

   
      22.11.2003
      22.11.2004
   



Хотя text, autor и date не нужны совсем, незачем делать вложенность.

Теперь проблемы:
1. Прочитать надо бы из файла. Никак не получается прочитать в одну строчку, убрав \\n.
Пробовал так:

open(XML,"xml.xml");
   @XML = ;
close(XML);
foreach(@XML){
   $res = $res . chomp($_);
}

Какая-то ерунда получается. Подскажите плиз правильный способ привода этого XML в одну строку.

2. Вытаскивание значений тегов. Или как правильно сказать? Нашел тут на форуме, чуть подправил под свои нужны. Работает.

@snames = ("textname","textbody");

foreach(@snames){
   if ($res =~ /<$_>(.+?)<\\/$_>.*/) {
      $t = $1;
      Обработка...
   };
};

Так нормально?

3. Можно ли найти все XML теги, которые используются в документе? То есть всё, что бывает между <> и забить в отдельный массив? Точнее, как? Наверное, тоже тройка строк.

Antilamer FAQ: книги по Perl у меня есть, что такое perldoc тоже знаю. Просто уже несколько часов что-то ничего не получается, плюс голова забита кучей других мыслей (Как понятно, пишу движок сайта. Готова только обработка cookie.). Времени очень мало. Пока остановился на этих проблемах, не могу писать (ударение ставьте как нравится) дальше.

WBR, GrAfF.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 24 Января 2004, 21:26:40
Первую проблему решил, возникла новая. Текст в строчку собираю с помощью:
open(XML,"xml.xml");
@XML = ;
close(XML);
chomp(@XML);
$strr = "@XML"; # А вот иначе эту строку можно написать? Покрасивше?


Следующая: каждая строчка XML, конечно, отформатирована табами. В начале строки Как их можно удалить? Тоже, вот, наверное, одной строкой делается... Плиз хэлп.
Название: Парсинг XML + много других вопросов.
Отправлено: Chs от 24 Января 2004, 22:17:57
http://search.cpan.org/~msergeant/XML-Parser-2.34/
perldoc -f join
perldoc perlre
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 24 Января 2004, 22:49:42
Сhs, спасибо. Наверное, в форум нужно бота дописать, который по ключевым словам сообщения будет отвечать про perldoc? :) А за join спасибо, что-то я про него не догадался вспомнить.

Так же гораздо интереснее: написать что-то самому. Я читал про XML, скачал книгу ОуРилли? ;) на эту тему. Сегодня оказалось, что для моих нужд требуется скрипт из всего лишь семнадцати строк...

Табы и пробелы после склейки массива в строку удаляются через:
$strr =~ s/\\t//g;
$strr =~ s/> />/g;
Ничего, нормально?

Теперь более сложный вопрос. Как можно посчитать количество одинаковых XML тегов и как вынуть содержимое, наример, именно третьего?
test1test2 и тд...

P.S. Забавно, как я тут сам с собой решаю проблемы. Надеюсь, хоть будующим читателям поможет, которым как обычно "рулит поиск". ;)
Название: Парсинг XML + много других вопросов.
Отправлено: Chs от 25 Января 2004, 00:45:07
Цитировать
test1test2 и тд...

В такой постановке задачи все теги различны.:)
Цитировать
Так же гораздо интереснее: написать что-то самому.

Изобретение велосипеда не преследуется по закону.:)
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 25 Января 2004, 02:38:57
Chs, вообще замучался немного. Если теги уникальны, т.е. каждый тег встречается не более раза, нужное значение можно вытащить регулярным. Зато при повторе тегов ничего лучше, чем приплюсовать поиск по подстроке, мне в голову не пришло. Но IMHO это совсем не красиво. Много кода и лишних действий.

Предположим, код:
text1text2
или же с закрытием через .

Ладно, спрошу сразу точно.
1. Ищем "2. Используем регулярный код из моих сообщений выше, подставляем в строку номер нужного повторяющегося тега, получаем кусок с уникальными тегами, которые тем же почти кодом нормально парсятся.
Красиво? ;)
IMHO не совсем.

Велосипеда не преследуется. А Кольт сделал людей равными. ;)
Название: Парсинг XML + много других вопросов.
Отправлено: Chs от 25 Января 2004, 13:28:40
@snames = ("textname","textbody");

foreach(@snames){
while ($res =~ /<$_>(.+?)<\\/$_>/g) {
$t = $1;
Обработка...
};
};

Так?
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 25 Января 2004, 18:51:57
Chs, огномные спасибы за while!!!
Наверное, последний вопрос.
Можно ли заменить код
while ($res =~ /<$_>(.+?)<\\/$_>/g) {
на ловящий следующие варианты (вытаскиваемые части отмечены жирным):
name="value">in tag
и
name="value"/>
То есть в первом варинате name="value" - одна строка, вплоть до первой >, in tag - другая строка, при этом любая строка может отсутствовать. При этом так как выше tag передаётся переменной.

Во втором вариатне ловится только строка параметров тега, до />.

В идеале, задумывается, что этот код должен выдирать и обрабатывать определенные теги xml, не завися от их полности.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 25 Января 2004, 20:32:08
Chs, попробовал сам сделать (смешно, да? ;).

$strr = \'in tag1in tag3\';

#in tag1
#
#in tag3
#
#
#

@snames = ("tag");

foreach(@snames){
#   while ($strr =~ /<$_(.*?)>(.*?)<\\/$_>/g) { #работает
#   while ($strr =~ /<$_([^>]*?) \\/>/g) { #работает
      $t = $1;
      $u = $2;
      $t =~ s/ //;
      print ("\\n" . "TAGPARAMS:" . "$t" . " TAGCONTENT:" . "$u");
   };
};

Сами по себе закомментированные while работают, обрабатывают "свои" теги. Как их склеить вместе? Я пробовал, но что-то никак.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 26 Января 2004, 13:07:17
Help, товарищи! Остался последний рубеж - склеить два рега в один, либо ещё как-то что-то сделать. И в форуме останется неплохая ветка про парсинг XML.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 28 Января 2004, 02:27:40
Так бы и сказали - не знаем, здаёмсу. Решил я эту проблему, только совсем не так, как предполагал. Сначала определяется тип тега, потом уже разбирается.
Всем читавшим спасибы.
Название: Парсинг XML + много других вопросов.
Отправлено: alm от 30 Января 2004, 10:00:51
Ну ты маньяк. А если завтра на чуток формат файла поменяется??? Ты весь этот геморой будешь заново сочинять?

Есть либы для парсинга XML ими пользоваться и проще и приятней. Один раз разберешься, с разбегу не получится, функций много. Но зато потом разбор любого XML пишется за пару минут.

Лично я юзаю XML::LibXML
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 30 Января 2004, 11:01:12
alm, ну была у меня мечта такая - XML парсить. Самому придумывать код лень, а в чужих работах разбираться - лень ещё большая. Одна из них победила. ;)

Теперь серьёзно. Была проблема хранения текстов и сопутствующей информации в файлах, так, чтобы можно было легко это всё оттуда вытащить. Написал примитивный парсер. То есть парсит, но ещё много чего придумать надо. Заодно разобрался в регулярных выражениях.

Формат никуда не поменяется, т.к. все теги пишу сам. ;)

Самое неприятное - бить тексты на страницы, встравлять в шаблоны, прописывать все ссылки. Вручную. Много ошибок, времени уходит. Поэтому если можно автоматизировать - то так, чтобы потом туда не возвращаться. ;)

Да и просто приятно. ;)
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 02 Февраля 2004, 07:17:13
Плиз хэлп, новая проблема!
Есть содержимое файла:
con


(tab)tent


(tab)and
(tab)text


Можно ли пропарсить *, не удаляя \\n?, чтобы на выходе тоже было всё отформатировано?
Название: Парсинг XML + много других вопросов.
Отправлено: Chs от 02 Февраля 2004, 10:00:47
Можно.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 02 Февраля 2004, 16:07:14
Chs, обромное спасибо, очень сильно помог!!! ;)

Теперь серьёзно. Где копать? Рыл везде, пока никак не понял. Если написать =~ m/, это вроде многострочка. Но IMHO это означает, что сама регулярная строка многострочно написана. Так? Как, как парсить? Понятно, что (.*?) не проходит, т.к. точка не может означать \\n. Менял на []*?, тоже не работает. А как ещё? Заменять \\n на [tutanovayastroka]? Это не красиво. Как, как правильно, Chs???
Название: Парсинг XML + много других вопросов.
Отправлено: Chs от 02 Февраля 2004, 16:38:16
Цитировать
Chs, обромное спасибо, очень сильно помог!!!

Да не за что!:) Но согласись, что я дал четкий ответ на поставленный вопрос.:))
Цитировать
Где копать?

Копать в perldoc perlop в части Regexp Quote-Like Operators, perldoc perlre.
Цитировать
Понятно, что (.*?) не проходит, т.к. точка не может означать \\n.

Может. RTFM.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 02 Февраля 2004, 23:31:15
Chs, сдаюсь. Смотрел документацию, но ничего так и не выглядел. Кажется, что всё-таки /m указывает на многострочность строки (хорошо звучит ;). Но как прописать \\n я так и не нашел. Помоги конкретно, плиз.
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 02 Февраля 2004, 23:43:02
Решил проблему.
\\n вместе с текстом получилось находить с помощью ([\\w\\W]*?)
Что-то я сразу не сообразил, что такие штуки можно писать внутри [].
И почему-то обходится без /m в регэкспе. Почему?
Почему, говоришь, можно точкой обозначать \\n?
Название: Парсинг XML + много других вопросов.
Отправлено: Chs от 03 Февраля 2004, 09:44:06

#!/usr/bin/perl
$s = "<\\n>";
print "1st found\\n" if $s =~ /<.>/s;
print "2nd found\\n" if $s =~ /<.>/m;

Почувствуй силу, Люк.:)
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 03 Февраля 2004, 15:52:57
Очередное спасибко! Тут опять такой случай, когда сначала заработало, а потом по документации лучше понял, почему. :)
Ещё в html доках по Perl кавычки странно оторбажаются, объяснение про точку содержит такую штуку: ``.". Как-то сразу не удалось понять, что они имели в виду. ;)
Название: Парсинг XML + много других вопросов.
Отправлено: GrAfF от 03 Февраля 2004, 18:58:08
Предположим, обрабатываемые XML файлы не бывают больше кило 4, 5, 10. Не вредно ли их так же грузить в строчку и изменять внутренности с помощью регэкспов? Вроде наиболее простой и четкий путь. Или я что не знаю? ;)