如何使用XML :: LibXML解析<rss>标记以找到xmlns定义

时间:2019-02-09 20:39:46

标签: perl rss

似乎没有一种一致的方法来使播客定义其rss feed。 碰到一个对RSS使用不同架构定义的网站。

使用XML :: LibXML在RSS网址中扫描xmlnamespace的最佳方法是什么

例如

一个提要可能是

<rss 
    xmlns:content="http://purl.org/rss/1.0/modules/content/" 
    xmlns:wfw="http://wellformedweb.org/CommentAPI/" 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" 
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

另一个可能是

<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom">

我想在我的脚本中包含所有正在使用的命名空间的评估,以便在解析rss时可以跟踪适当的字段名称。

不确定当前的状态,因为我不确定此模块是否具有执行我想要的<rss>标签属性雾化的功能。

2 个答案:

答案 0 :(得分:5)

我不确定我确切地知道您要寻找哪种输出,但是XML::LibXML确实能够列出名称空间:

use warnings;
use strict;
use XML::LibXML;

my $dom = XML::LibXML->load_xml(string => <<'EOT');
<rss 
    xmlns:content="http://purl.org/rss/1.0/modules/content/" 
    xmlns:wfw="http://wellformedweb.org/CommentAPI/" 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" 
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
</rss>
EOT
for my $ns ($dom->documentElement->getNamespaces) {
    print $ns->getLocalName(), " / ", $ns->getData(), "\n";
}

输出:

content / http://purl.org/rss/1.0/modules/content/
wfw / http://wellformedweb.org/CommentAPI/
dc / http://purl.org/dc/elements/1.1/
atom / http://www.w3.org/2005/Atom
sy / http://purl.org/rss/1.0/modules/syndication/
slash / http://purl.org/rss/1.0/modules/slash/

答案 1 :(得分:2)

我知道OP已经接受了答案。但是为了完整起见,应该提到的是,建议在DOM上进行弹性搜索的方法是使用XML::LibXML::XPathContext

#!/usr/bin/perl
use strict;
use warnings;

use XML::LibXML;

my @examples = (
    <<EOT
<rss xmlns:atom="http://www.w3.org/2005/Atom">
  <atom:test>One Ring to rule them all,</atom:test>
</rss>
EOT
    ,
    <<EOT
<rss xmlns:a="http://www.w3.org/2005/Atom">
  <a:test>One Ring to find them,</a:test>
</rss>
EOT
    ,
    <<EOT
<rss xmlns="http://www.w3.org/2005/Atom">
  <test>The end...</test>
</rss>
EOT
    ,
);

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs('atom', 'http://www.w3.org/2005/Atom');

for my $example (@examples) {
    my $dom = XML::LibXML->load_xml(string => $example)
        or die "XML: $!\n";

    for my $node ($xpc->findnodes("//atom:test", $dom)) {
        printf("%-10s: %s\n", $node->nodeName, $node->textContent);
    }
}

exit 0;

即您为感兴趣的那些名称空间分配一个本地名称空间前缀。

输出:

$ perl dummy.pl
atom:test : One Ring to rule them all,
a:test    : One Ring to find them,
test      : The end...