Отложив на мгновение отличное предложение от Ричарда Симойса , чтобы использовать XML :: RSS ...
Я думаю, что основная проблема, с которой вы сталкиваетесь, связана с пространствами имен XML. Рассмотрим следующую строку вашего скрипта:
$root->findnodes('channel')
Он ищет элемент типа 'channel' , но ваш исходный документ, вероятно, не содержит такого элемента. То, что вы должны искать, это что-то вроде: элемент типа 'channel' в пространстве имен, идентифицируемый URI 'http://purl.org/rss/1.0/'.
Работать с пространствами имен нелегко. Существует два типа: пространство имен по умолчанию (например: xmlns = "http://purl.org/rss/1.0/"); и пространства имен, объявленные с префиксом (например: xmlns: rss =" http://purl.org/rss/1.0/"). В любом случае единственное, что имеет значение, это URI пространства имен. Префикс объявленный в документе (например, 'rss:') не имеет отношения к вашему сценарию.
Чтобы использовать пространства имен с libxml, вам нужно объявить свой собственный префикс для каждого URI пространства имен, а затем использовать этот префикс в своих вызовах для findnodes. Вы можете выбрать префикс, который совпадает с префиксом в документе или отличается - он не имеет значения, если URI одинаков. Вам необходимо использовать объект XML :: LibXML :: XPathContext, чтобы связать URI пространства имен с префиксами, а затем направить запросы через этот объект контекста.
Это версия вашего скрипта, которая, вероятно, ближе к тому, что вы хотите.
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
use XML::LibXML::XPathContext;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('slashdot.rss');
my $root = $doc->documentElement();
my $xc = XML::LibXML::XPathContext->new( $root );
$xc->registerNs( rss => 'http://purl.org/rss/1.0/' );
foreach my $channel ($xc->findnodes('rss:channel')) {
foreach my $item ($xc->findnodes('rss:item')) {
my $guid = $xc->findvalue('rss:guid', $item);
my $title = $xc->findvalue('rss:title', $item);
my $link = $xc->findvalue('rss:link', $item);
my $description = $xc->findvalue('rss:description', $item);
my $pubdate = $xc->findvalue('rss:pubDate', $item);
print "INSERT INTO events VALUES ( \"$guid\", \"$title\", \"$link\",\"$description\", \"$pubdate\" ); \n";
}
}
В документе, который вы пытаетесь проанализировать, возможно, используется другая версия RSS и, следовательно, другой URI пространства имен RSS - это лишь одна из многих причин использовать модуль RSS, а не пытаться делать это вручную.
Как указывало ikegami , интерполяция значений в SQL - плохая идея. В вашем примере вы генерируете SQL со строковыми литералами в двойных кавычках (вы, вероятно, хотели использовать одинарные кавычки). Это не удастся, если любое из значений, извлеченных из RSS, содержит символ двойной кавычки. Одиночные и двойные кавычки очень часто встречаются в RSS.