2014-02-09 3 views
0

Я полностью потерял и вообще не разбираюсь в анализе RSS/XML. Это не имеет никакого смысла для меня вообще.Разбор RSS с Perl и XML :: XPath

Вот сценарий Perl я рубил с:

#!/usr/bin/perl -w 
use strict; 
use LWP::Simple; 
use XML::XPath; 
use Data::Dumper; 

my $rssurl  = "http://librivox.org/rss/4273"; 
my $xml = get($rssurl); 
my $xp = XML::XPath->new(xml => $xml); 
my $stories = $xp->find('/'); 

foreach my $story($stories->get_nodelist) { 
    print "----\n"; 
    my $title = $xp->find('title', $story)->string_value; 
    print "title is [$title]\n"; 
} 

Самая большая загадка для меня это то, что я перейти к $xp->find() Я просто предполагаю, что и ухватиться за соломинку. Разве нет способа я могу только find все и повторить все, что было found?

+0

Почему бы не использовать что-то RSS осведомленный? https://metacpan.org/pod/XML::Feed – Quentin

+0

, потому что он не будет установлен в моей системе. –

+0

Что значит «не будет устанавливать»? Какие у вас проблемы? –

ответ

1

XML::XPath::find принимает XPath в качестве входных данных и возвращает объект XML::XPath::Nodeset, который вы можете перебрать.

$stories = $xp->find('//channel/item'); # find all <channel><item> 
foreach my $story ($stories->get_nodelist) { 
    my $titles = $story->find('title'); # a set, even if there's only 1 elem 
    foreach my $title ($titles->get_nodelist) { 
     print "title is ", $title->string_value; 
    } 
} 
1

Я вижу, у вас есть ответ, используя XML::Feed, но я думал, что это стоило решения этого тоже.

Вам нужно привыкнуть к синтаксису XPath. Это 10-Minute XPath Tutorial - хорошее быстрое введение. Выражения XPath по существу похожи на пути файловой системы, с несколькими дополнениями.

Глядя на XML из вашего фида, корневой элемент равен rss, в котором находится channel, содержащий количество элементов item. Это они вы ищете, поэтому выражение XPath равно /rss/channel/item.

Вам не нужно использовать оригинальный XML::XPath объект для вызова find: каждый XML::XPath::Node::Element объекта, который пришел от предыдущего вызова find имеет свой собственный find метод, который делает именно то, что вы написали, так что вы можете просто написать $item->find('title') , который вернет XML::XPath::NodeSet.

Кроме того, XML::XPath::NodeSet имеет строгий переопределяемый как звонок to_literal, так что нет необходимости в вызове string_value.

Этот код делает то, что вы намеревались. Я надеюсь, что это помогает.

use strict; 
use warnings; 

use LWP::Simple; 
use XML::XPath; 

my $rssurl = "http://librivox.org/rss/4273"; 
my $xml = get($rssurl); 
my $xp  = XML::XPath->new(xml => $xml); 
my @items = $xp->findnodes('/rss/channel/item'); 

foreach my $item (@items) { 
    print "----\n"; 
    my $title = $item->find('title'); 
    print "title is <<$title>>\n"; 
} 

выход

---- 
title is <<1 - Section 1>> 
---- 
title is <<2 - Section 2>> 
---- 
title is <<3 - Section 3>> 
---- 
title is <<4 - Section 4>> 
Смежные вопросы