【问题标题】:How to parse <rss> tag with XML::LibXML to find xmlns defintions如何使用 XML::LibXML 解析 <rss> 标记以查找 xmlns 定义
【发布时间】:2019-02-13 00:40:17
【问题描述】:

播客定义其 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 时,可以跟踪适当的字段名称。

还不确定那会是什么样子,因为我不确定这个模块是否有能力执行我想要的 &lt;rss&gt; 标签属性原子化。

【问题讨论】:

    标签: perl rss


    【解决方案1】:

    我不确定我是否完全理解您要查找的输出类型,但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/
    

    【讨论】:

    • 谢谢。那很完美。我只是需要一个开始。我正在浏览文档,但没有看到我需要的东西。可能是压力太大,一直忽略答案。
    • XML::LibXML 文档非常广泛和密集(它们基本上是整个 XML 规范),所以我不会因为忽视这样的事情而责怪任何人。
    • 有趣的是你必须使用-&gt;documentElement,因为XML::LibXML::Document 是一个XML::LibXML::Node,但它的getNamespaces 返回一个空列表...
    • @StefanBecker 是的,在DOM 中,“文档”和“文档元素”是不同的东西。
    【解决方案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...
    

    【讨论】:

    • 实际上在查看了您的示例之后。弹性是很重要的东西。这是我编写好代码的方法的重要组成部分。
    • 我可能会构建一个模块来说明已知的命名空间 DTD 并遵循您的弹性模式。我会牢记这一点,以便为我正在做的事情提供更强大的版本。
    猜你喜欢
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    相关资源
    最近更新 更多