使用 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
我想解析 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