2

いくつかの大きなサイズの XML ファイル (1 つは ~8GB、他は ~4MB) を解析し、それらをマージする必要があります。SAX と 両方ともTie::Fileメモリと時間の問題で適していないため、Twig を試すことにしました。

各 XML ファイルが次のようないくつかの要素で構成されているとします。

<class name=math>
     <student>luke1</student>
     ... (a very very long list of student)
   <student>luke8000000</student>
</class>
<class name=english>
   <student>mary1</student>
     ...
   <student>mary1000000</student>
</class>

ご覧のとおり、使用しても、最初の各行を処理する必要があるためTwigRoots => {"class[\@name='english']" => \&counter}、Twig が解析を開始するまで長い間待つ必要があります (各行を処理する必要がない場合は修正してください)。class=englishclass=math

ファイルの先頭ではなく、行番号から Twig に解析を開始させる方法はありますか? <class name = english>grepを使用すると、はるかに高速な行番号を取得できます。

前もって感謝します。

4

2 に答える 2

3

おそらく、この例から代替戦略のアイデアが得られるでしょう。index_file特に、 のアイデアを、ファイル ハンドルを に渡す前に場所を検索するという Zoul の提案と組み合わせることができる場合がありますXML::Twig

use strict;
use warnings;

# Index the XML file, storing start and end positions
# for each class in the document. You pay this cost only once.
sub index_file {
    local @ARGV = (shift);
    my (%index, $prev);
    while (<>){
        if ( /^<class name=(\w+)>/ ) {
            my $start = tell() - length();
            $index{$1} = { start => $start, end => undef };

            $index{$prev}{end} = $start - 1 if defined $prev;
            $prev = $1;
        }        
        $index{$prev}{end} = tell if eof;
    }
    return \%index;
}

# Use the index to retrieve the XML for a particular class.
# This allows you to jump quickly to any section of interest.
# It assumes that the sections of the XML document are small enough
# to be held in memory.
sub get_section {
    my ($file_name, $class_name, $index) = @_;
    my $ind = $index->{$class_name};

    open(my $fh, '<', $file_name) or die $!;    
    seek $fh, $ind->{start}, 0;
    read( $fh, my $xml_section, $ind->{end} - $ind->{start} );

    return $xml_section;
}

# Example usage.
sub main {
    my ($file_name) = @_;
    my $index = index_file($file_name);
    for my $cn (keys %$index){
        # Process only sections of interest.
        next unless $cn eq 'math' or $cn eq 'english';
        my $xml = get_section($file_name, $cn, $index);

        # Pass off to XML::Twig or whatever.
        print $xml;
    }
}

main(@ARGV);
于 2010-08-02T13:17:15.793 に答える
1

parseメソッドは を受け入れるXML::TwigのでIO::Handle、おそらく自分で正しい行を探すことができますか? また、最初の不要な行をスキップできるコンストラクターinput_filterへのパラメーターもあります。XML::Twig

于 2010-08-02T16:37:12.913 に答える