解析大(100 Mb)XML文件时出现" Out of memory " 错误
use strict;
use warnings;
use XML::Twig;
my $twig=XML::Twig->new();
my $data = XML::Twig->new
->parsefile("divisionhouserooms-v3.xml")
->simplify( keyattr => []);
my @good_division_numbers = qw( 30 31 32 35 38 );
foreach my $property ( @{ $data->{DivisionHouseRoom}}) {
my $house_code = $property->{HouseCode};
print $house_code, "\n";
my $amount_of_bedrooms = 0;
foreach my $division ( @{ $property->{Divisions}->{Division} } ) {
next unless grep { $_ eq $division->{DivisionNumber} } @good_division_numbers;
$amount_of_bedrooms += $division->{DivisionQuantity};
}
open my $fh, ">>", "Result.csv" or die $!;
print $fh join("\t", $house_code, $amount_of_bedrooms), "\n";
close $fh;
}
Run Code Online (Sandbox Code Playgroud)
我能做些什么来解决这个错误问题?
Zai*_*aid 18
处理不适合内存的大型XML文件是一种广告:XML::Twig
其中一个优点
XML::Twig是它可以让你处理不适合内存的文件(BTW将XML文档存储在内存中,因为树的内存非常昂贵,扩展因子通常在10左右).为此,您可以定义处理程序,一旦完全解析了特定元素,就会调用这些处理程序.在这些处理程序中,您可以访问元素并按照您认为合适的方式处理它(...)
问题中发布的代码并没有充分利用它的强度XML::Twig(使用该simplify方法并没有比它好得多XML::Simple).
代码中缺少的是' twig_handlers'或' twig_roots',这实际上导致解析器有效地关注XML文档内存的相关部分.
如果没有看到XML,很难说是逐块处理文档还是只选择部分是可行的,但是任何一个都应该解决这个问题.
所以代码应该类似于以下内容(chunk-by-chunk演示):
use strict;
use warnings;
use XML::Twig;
use List::Util 'sum'; # To make life easier
use Data::Dump 'dump'; # To see what's going on
my %bedrooms; # Data structure to store the wanted info
my $xml = XML::Twig->new (
twig_roots => {
DivisionHouseRoom => \&count_bedrooms,
}
);
$xml->parsefile( 'divisionhouserooms-v3.xml');
sub count_bedrooms {
my ( $twig, $element ) = @_;
my @divParents = $element->children( 'Divisions' );
my $id = $element->first_child_text( 'HouseCode' );
for my $divParent ( @divParents ) {
my @divisions = $divParent->children( 'Division' );
my $total = sum map { $_->text } @divisions;
$bedrooms{$id} = $total;
}
$element->purge; # Free up memory
}
dump \%bedrooms;
Run Code Online (Sandbox Code Playgroud)