Forum Webscript.Ru
Программирование => Perl => Тема начата: 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.
-
Первую проблему решил, возникла новая. Текст в строчку собираю с помощью:
open(XML,"xml.xml");
@XML = ;
close(XML);
chomp(@XML);
$strr = "@XML"; # А вот иначе эту строку можно написать? Покрасивше?
Следующая: каждая строчка XML, конечно, отформатирована табами. В начале строки Как их можно удалить? Тоже, вот, наверное, одной строкой делается... Плиз хэлп.
-
http://search.cpan.org/~msergeant/XML-Parser-2.34/
perldoc -f join
perldoc perlre
-
Сhs, спасибо. Наверное, в форум нужно бота дописать, который по ключевым словам сообщения будет отвечать про perldoc? :) А за join спасибо, что-то я про него не догадался вспомнить.
Так же гораздо интереснее: написать что-то самому. Я читал про XML, скачал книгу ОуРилли? ;) на эту тему. Сегодня оказалось, что для моих нужд требуется скрипт из всего лишь семнадцати строк...
Табы и пробелы после склейки массива в строку удаляются через:
$strr =~ s/\\t//g;
$strr =~ s/> />/g;
Ничего, нормально?
Теперь более сложный вопрос. Как можно посчитать количество одинаковых XML тегов и как вынуть содержимое, наример, именно третьего?
test1test2 и тд...
P.S. Забавно, как я тут сам с собой решаю проблемы. Надеюсь, хоть будующим читателям поможет, которым как обычно "рулит поиск". ;)
-
test1test2 и тд...
В такой постановке задачи все теги различны.:)
Так же гораздо интереснее: написать что-то самому.
Изобретение велосипеда не преследуется по закону.:)
-
Chs, вообще замучался немного. Если теги уникальны, т.е. каждый тег встречается не более раза, нужное значение можно вытащить регулярным. Зато при повторе тегов ничего лучше, чем приплюсовать поиск по подстроке, мне в голову не пришло. Но IMHO это совсем не красиво. Много кода и лишних действий.
Предположим, код:
text1text2
или же с закрытием через .
Ладно, спрошу сразу точно.
1. Ищем "2. Используем регулярный код из моих сообщений выше, подставляем в строку номер нужного повторяющегося тега, получаем кусок с уникальными тегами, которые тем же почти кодом нормально парсятся.
Красиво? ;)
IMHO не совсем.
Велосипеда не преследуется. А Кольт сделал людей равными. ;)
-
@snames = ("textname","textbody");
foreach(@snames){
while ($res =~ /<$_>(.+?)<\\/$_>/g) {
$t = $1;
Обработка...
};
};
Так?
-
Chs, огномные спасибы за while!!!
Наверное, последний вопрос.
Можно ли заменить код
while ($res =~ /<$_>(.+?)<\\/$_>/g) {
на ловящий следующие варианты (вытаскиваемые части отмечены жирным):
name="value">in tag
и
name="value"/>
То есть в первом варинате name="value" - одна строка, вплоть до первой >, in tag - другая строка, при этом любая строка может отсутствовать. При этом так как выше tag передаётся переменной.
Во втором вариатне ловится только строка параметров тега, до />.
В идеале, задумывается, что этот код должен выдирать и обрабатывать определенные теги xml, не завися от их полности.
-
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 работают, обрабатывают "свои" теги. Как их склеить вместе? Я пробовал, но что-то никак.
-
Help, товарищи! Остался последний рубеж - склеить два рега в один, либо ещё как-то что-то сделать. И в форуме останется неплохая ветка про парсинг XML.
-
Так бы и сказали - не знаем, здаёмсу. Решил я эту проблему, только совсем не так, как предполагал. Сначала определяется тип тега, потом уже разбирается.
Всем читавшим спасибы.
-
Ну ты маньяк. А если завтра на чуток формат файла поменяется??? Ты весь этот геморой будешь заново сочинять?
Есть либы для парсинга XML ими пользоваться и проще и приятней. Один раз разберешься, с разбегу не получится, функций много. Но зато потом разбор любого XML пишется за пару минут.
Лично я юзаю XML::LibXML
-
alm, ну была у меня мечта такая - XML парсить. Самому придумывать код лень, а в чужих работах разбираться - лень ещё большая. Одна из них победила. ;)
Теперь серьёзно. Была проблема хранения текстов и сопутствующей информации в файлах, так, чтобы можно было легко это всё оттуда вытащить. Написал примитивный парсер. То есть парсит, но ещё много чего придумать надо. Заодно разобрался в регулярных выражениях.
Формат никуда не поменяется, т.к. все теги пишу сам. ;)
Самое неприятное - бить тексты на страницы, встравлять в шаблоны, прописывать все ссылки. Вручную. Много ошибок, времени уходит. Поэтому если можно автоматизировать - то так, чтобы потом туда не возвращаться. ;)
Да и просто приятно. ;)
-
Плиз хэлп, новая проблема!
Есть содержимое файла:
con
(tab)tent
(tab)and
(tab)text
Можно ли пропарсить *, не удаляя \\n?, чтобы на выходе тоже было всё отформатировано?
-
Можно.
-
Chs, обромное спасибо, очень сильно помог!!! ;)
Теперь серьёзно. Где копать? Рыл везде, пока никак не понял. Если написать =~ m/, это вроде многострочка. Но IMHO это означает, что сама регулярная строка многострочно написана. Так? Как, как парсить? Понятно, что (.*?) не проходит, т.к. точка не может означать \\n. Менял на []*?, тоже не работает. А как ещё? Заменять \\n на [tutanovayastroka]? Это не красиво. Как, как правильно, Chs???
-
Chs, обромное спасибо, очень сильно помог!!!
Да не за что!:) Но согласись, что я дал четкий ответ на поставленный вопрос.:))
Где копать?
Копать в perldoc perlop в части Regexp Quote-Like Operators, perldoc perlre.
Понятно, что (.*?) не проходит, т.к. точка не может означать \\n.
Может. RTFM.
-
Chs, сдаюсь. Смотрел документацию, но ничего так и не выглядел. Кажется, что всё-таки /m указывает на многострочность строки (хорошо звучит ;). Но как прописать \\n я так и не нашел. Помоги конкретно, плиз.
-
Решил проблему.
\\n вместе с текстом получилось находить с помощью ([\\w\\W]*?)
Что-то я сразу не сообразил, что такие штуки можно писать внутри [].
И почему-то обходится без /m в регэкспе. Почему?
Почему, говоришь, можно точкой обозначать \\n?
-
#!/usr/bin/perl
$s = "<\\n>";
print "1st found\\n" if $s =~ /<.>/s;
print "2nd found\\n" if $s =~ /<.>/m;
Почувствуй силу, Люк.:)
-
Очередное спасибко! Тут опять такой случай, когда сначала заработало, а потом по документации лучше понял, почему. :)
Ещё в html доках по Perl кавычки странно оторбажаются, объяснение про точку содержит такую штуку: ``.". Как-то сразу не удалось понять, что они имели в виду. ;)
-
Предположим, обрабатываемые XML файлы не бывают больше кило 4, 5, 10. Не вредно ли их так же грузить в строчку и изменять внутренности с помощью регэкспов? Вроде наиболее простой и четкий путь. Или я что не знаю? ;)