Perl:如何在没有根节点的情况下处理XML对象流

lex*_*exu 4 xml perl merge stream

我需要用Perl解析一个巨大的文件.(所以我将使用流解析器..)该文件包含多个XML文档(对象),但没有根节点.这会导致XML解析器在第一个Object之后中止,就像它应该的那样.答案可能是修复假根节点之前/之后.

<FAKE_ROOT_TAG>Original Stream</FAKE_ROOT_TAG>
Run Code Online (Sandbox Code Playgroud)

由于文件很大(> 1GByte),我不想复制/重写它,而是宁愿使用透明的类/模块(对于XML Parser)"合并"或"合并"多个流.

stream1 : <FAKE_ROOT_TAG>                 \
stream2 : Original Stream from file        >   merged stream
stream3 : </FAKE_ROOT_TAG>                / 
Run Code Online (Sandbox Code Playgroud)

你能指点我这个问题的模块或示例代码吗?

fri*_*edo 5

这是一个简单的例子,说明如何通过将伪文件句柄传递给XML解析器来实现它.此对象重载readlineoperator(<>)以返回假根标记,其中包含文件中的行.

package FakeFile;

use strict;
use warnings;

use overload '<>' => \&my_readline;

sub new {
    my $class = shift;
    my $filename  = shift;

    open my $fh, '<', $filename or die "open $filename: $!";

    return bless { fh => $fh }, $class;
}

sub my_readline {
    my $self = shift;
    return if $self->{done};

    if ( not $self->{started} ) {
        $self->{started} = 1;
        return '<fake_root_tag>';
    }

    if ( eof $self->{fh} ) {
        $self->{done} = 1;
        return '</fake_root_tag>';
    }

    return readline $self->{fh};
}


1;
Run Code Online (Sandbox Code Playgroud)

如果你的解析器需要一个真正的文件句柄(例如使用类似的东西sysread),这将无法工作,但也许你会发现它是鼓舞人心的.

用法示例:

echo "one
two
three" > myfile
perl -MFakeFile -E 'my $f = FakeFile->new( "myfile" ); print while <$f>' 
Run Code Online (Sandbox Code Playgroud)