由于没有其他方法可以获取数据,我处于需要解析RSS提要的不幸位置。我有一个以前用于解析XML文件的Perl脚本。我想我可以修改它以对RSS feed执行相同操作,这样我就可以将数据转换为更容易使用的格式。考虑到这一点,我修改了我的文件。但它实际上似乎并没有从Feed中找到任何数据。这是代码的核心。
foreach my $channel ($root->findnodes('channel')) {
foreach my $item ($root->findnodes('item')) {
my $guid = $item->findvalue('guid');
my $title = $item->findvalue('title');
my $link = $item->findvalue('link');
my $description = $item->findvalue('description');
my $pubdate = $item->findvalue('pubdate');
print DATA "INSERT INTO events VALUES ( \"$guid\", \"$title\", \"$link\",\"$description\", \"$pubdate\" ); \n";
}
}
有什么想法吗?
答案 0 :(得分:4)
暂时搁置Richard Simões使用XML :: RSS ...
的优秀建议我认为您遇到的主要问题是使用XML命名空间。考虑一下你的剧本这一行:
$root->findnodes('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,因此使用不同的RSS命名空间URI - 这只是使用RSS模块而不是尝试手动执行此操作的众多原因之一。
正如ikegami指出的那样,将值插入SQL实际上是一个糟糕的主意。在您的示例中,您使用双引号字符串文字生成SQL(您可能意味着使用单引号)。如果从RSS中提取的任何值包含双引号字符,则此操作将失败。单引号和双引号字符极有可能出现在RSS中。