如何让XML::RSS读取不同命名空间的XML元素?(torznab示例)
解决方案
XML::RSS默认不会自动解析自定义命名空间下的元素,仅注册命名空间不足以让它识别并处理torznab:attr,需要额外配置处理规则,或改用更灵活的解析库:
方法1:为XML::RSS添加自定义元素处理逻辑
通过add_handler方法指定torznab:attr的处理方式,将元素的属性值存入item的结构中:
use XML::RSS; use Data::Dumper; # 初始化时直接指定命名空间 my $rss = XML::RSS->new( xmlns => { torznab => 'http://torznab.com/schemas/2015/feed' } ); # 注册torznab:attr的处理钩子 $rss->add_handler('torznab:attr', sub { my ($tag_name, $attrs, $rss_obj) = @_; # 将属性数据存入当前item的torznab_attrs数组 push @{$rss_obj->{current_item}->{torznab_attrs}}, { name => $attrs->{name}, value => $attrs->{value} }; }); $rss->parsefile("torznab.xml"); # 现在可以获取到torznab属性数据 say Dumper($rss->{items}->[0]->{torznab_attrs});
方法2:改用XML::LibXML直接解析
如果XML::RSS的限制过多,推荐使用XML::LibXML,通过XPath直接查询命名空间下的元素,更灵活:
use XML::LibXML; use Data::Dumper; my $parser = XML::LibXML->new(); my $doc = $parser->parse_file("torznab.xml"); # 创建XPath上下文并注册torznab命名空间 my $xpc = XML::LibXML::XPathContext->new($doc); $xpc->registerNs('torznab', 'http://torznab.com/schemas/2015/feed'); # 查询所有item下的torznab:attr元素 my @attr_nodes = $xpc->findnodes('//rss/channel/item/torznab:attr'); my $torznab_data = []; foreach my $node (@attr_nodes) { push @$torznab_data, { name => $node->getAttribute('name'), value => $node->getAttribute('value') }; } say Dumper($torznab_data);
原因说明
XML::RSS的设计初衷是处理标准RSS格式,仅对部分预定义的命名空间(如atom)有内置支持。对于自定义命名空间的元素,必须通过add_handler显式指定处理逻辑,否则解析时会直接忽略这些元素。
内容的提问来源于stack exchange,提问作者AmbroseChapel
相关产品推荐
相关产品推荐

