使用XML解析使用PERL的RSS提要:LibXML

时间:2011-09-15 17:00:36

标签: xml perl parsing rss

由于没有其他方法可以获取数据,我处于需要解析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";
  }
}

有什么想法吗?

1 个答案:

答案 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中。