代码之家  ›  专栏  ›  技术社区  ›  Ken Ingram

如何用xml::libxml解析<rss>标记以查找xmlns定义

  •  3
  • Ken Ingram  · 技术社区  · 6 年前

    似乎没有一致的方式来定义播客的RSS源。 遇到一个正在为RSS使用不同的模式定义的。

    使用xml::libxml扫描RSS URL中的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 回复  |  直到 6 年前
        1
  •  5
  •   haukex    6 年前

    我不确定我是否确切了解你想要什么样的输出,但是 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/
    
        2
  •  2
  •   Stefan Becker    6 年前

    我知道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...