使用 XML::LibXML::Reader 而不是 XML::LibXML 时额外的空元素

Extra empty elements when using XML::LibXML::Reader instead of XML::LibXML

我想解析 Wordpress 博客导出 - 我已经在 3 个博客条目的示例输出中成功使用了一些 XML::LibXML 代码,但是我决定尝试使用 XML:LibXML:Reader,因为我我预计必须解析一个非常大的文件,我担心 运行 内存不足。

但是,我得到了一些额外的空白节点。

可以使用以下代码和 XML 文档演示问题:

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

use XML::LibXML::Reader;

my $filename = $ARGV[0];

my $reader = XML::LibXML::Reader->new(location => $filename) or die;

my $entry_pattern = 'XML::LibXML::Pattern'->new('/rss/channel/item');

while ($reader->nextPatternMatch($entry_pattern)) {
    say "MATCH";
    my $item = $reader->copyCurrentNode(1);
    say $item;
    say 'Title: ', $item->findvalue('./title');
    say "";
}
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
   <channel>
      <title>Blog</title>
      <item><title>Title 1</title></item>
      <item><title>Title 2</title></item>
   </channel>
</rss>

得到的输出:

MATCH
<item><title>Title 1</title></item>
Title: Title 1

MATCH
<item/>
Title:

MATCH
<item><title>Title 2</title></item>
Title: Title 2

MATCH
<item/>
Title:

注意额外的 <item/> 匹配项。这些是从哪里来的?我怎样才能避免它们?

似乎正在发生的事情是匹配结束标记。像 ::Reader 这样的 pull/stream 解析器需要标记元素的开始和结束,所以这是有道理的。想象一下,如果我们 ->copyCurrentNode 没有被使用。

但是,我们确实使用 ->copyCurrentNode,所以我们不关心它们,也不想要它们。所以我们只需使用以下内容跳过它们:

next if $reader->nodeType != XML_READER_TYPE_ELEMENT;

next if $reader->nodeType == XML_READER_TYPE_END_ELEMENT;

演示:

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

use XML::LibXML::Reader qw( XML_READER_TYPE_ELEMENT);

my $filename = $ARGV[0];

my $reader = XML::LibXML::Reader->new( location => $filename );

my $entry_pattern = 'XML::LibXML::Pattern'->new( '/rss/channel/item' );

while ( $reader->nextPatternMatch($entry_pattern) ) {
    next if $reader->nodeType != XML_READER_TYPE_ELEMENT;

    say "MATCH";
    my $item = $reader->copyCurrentNode(1);
    say $item;
    say 'Title: ', $item->findvalue( './title' );
    say "";
}
MATCH
<item><title>Title 1</title></item>
Title: Title 1

MATCH
<item><title>Title 2</title></item>
Title: Title 2