簡體   English   中英

Perl:如何在沒有根節點的情況下處理XML對象流

[英]Perl: How to handle a stream of XML Objects without a root node

我需要用Perl解析一個巨大的文件。 (所以我將使用流解析器..)該文件包含多個XML文檔(對象),但沒有根節點。 這會導致XML解析器在第一個Object之后中止,就像它應該的那樣。 答案可能是修復假根節點之前/之后。

<FAKE_ROOT_TAG>Original Stream</FAKE_ROOT_TAG>

由於文件很大(> 1GByte),我不想復制/重寫它,而是寧願使用透明的類/模塊(對於XML Parser)“合並”或“合並”多個流。

stream1 : <FAKE_ROOT_TAG>                 \
stream2 : Original Stream from file        >   merged stream
stream3 : </FAKE_ROOT_TAG>                / 

你能指點我這個問題的模塊或示例代碼嗎?

這是一個簡單的例子,說明如何通過將偽文件句柄傳遞給XML解析器來實現它。 此對象重載readline操作符( <> )以返回假根標記,其中包含文件中的行。

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;

如果您的解析器需要一個真正的文件句柄(例如使用像sysread這樣的東西),這將無法工作,但也許您會發現它是鼓舞人心的。

用法示例:

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

這是PerlMonks提取的一個技巧:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Parser;
use XML::LibXML;

my $doc_file= shift @ARGV;

my $xml=qq{
     <!DOCTYPE doc 
           [<!ENTITY real_doc SYSTEM "$doc_file">]
     >
     <doc>
         &real_doc;
     </doc>
};

{ print "XML::Parser:\n";
  my $t= XML::Parser->new( Style => 'Stream')->parse( $xml);
}

{ print "XML::LibXML:\n";
  my $parser = XML::LibXML->new();
  my $doc = $parser->parse_string($xml);
  print $doc->toString;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM