解析大(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 …Run Code Online (Sandbox Code Playgroud) 我正在使用XML :: Twig解析大型XML文件(60GB +)并在OO(Moose)脚本中使用它.我正在使用该twig_handlers选项在读入内存后立即解析元素.但是,我不确定如何处理Element和Twig.
在我使用Moose(和OO)之前,我的脚本看起来如下(和工作):
my $twig = XML::Twig->new(
twig_handlers => {
$outer_tag => \&_process_tree,
}
);
$twig->parsefile($input_file);
sub _process_tree {
my ($fulltwig, $twig) = @_;
$twig->cut;
$fulltwig->purge;
# Do stuff with twig
}
Run Code Online (Sandbox Code Playgroud)
现在我就这样做了.
my $twig = XML::Twig->new(
twig_handlers => {
$self->outer_tag => sub {
$self->_process_tree($_);
}
}
);
$twig->parsefile($self->input_file);
sub _process_tree {
my ($self, $twig) = @_;
$twig->cut;
# Do stuff with twig
# But now the 'full twig' is not purged
}
Run Code Online (Sandbox Code Playgroud)
问题是,我现在看到我错过了清除 …
我的目标是start_tag_handler(见下文)在找到/ tag 时获取apps/ titlecontent (请参阅下面的示例XML).appstitle
并
end_tag_handler在找到/ tag 时获取apps/ logscontent .appslogs
但相反,此代码返回null并退出.
#!/usr/local/bin/perl -w
use XML::Twig;
my $twig = XML::Twig->new(
start_tag_handlers =>
{ 'apps/title' => \&kicks
},
twig_roots =>
{ 'apps' => \&app
},
end_tag_handlers =>
{ 'apps/logs' => \&bye
}
);
$twig -> parsefile( "doc.xml");
sub kicks {
my ($twig, $elt) = @_;
print "---kicks--- \n";
print $elt -> text;
print …Run Code Online (Sandbox Code Playgroud) 我正在处理从合作伙伴处收到的XML文件.我对更改此xml文件的构成没有任何影响.XML的摘录是:
<?xml version="1.0" encoding="UTF-8"?>
<objects>
<object>
<id>VW-XJC9</id>
<name>Name</name>
<type>House</type>
<description>
<![CDATA[<p>some descrioption of the house</p>]]> </description>
<localcosts>
<localcost>
<type>mandatory</type>
<name>What kind of cost</name>
<description>
<![CDATA[Some text again, different than the first tag]]>
</description>
</localcost>
</localcosts>
</object>
</objects>
Run Code Online (Sandbox Code Playgroud)
我使用Twig的原因是这个XML大约11GB,大约有100000个不同的对象).问题是当我到达localcosts部分时,会跳过3个字段(类型,名称和描述),可能是因为之前已经使用过这些名称.
我用来浏览xml文件的代码如下:
my $twig= new XML::Twig( twig_handlers => {
id => \&get_ID,
name => \&get_Name,
type => \&get_Type,
description => \&get_Description,
localcosts => \&get_Localcosts
});
$lokaal="c:\\temp\\data3.xml";
getstore($xml, $lokaal);
$twig->parsefile("$lokaal");
sub get_ID { my( $twig, $data)= @_; $field[0]=$data->text; $twig->purge; }
sub get_Name { my( …Run Code Online (Sandbox Code Playgroud) 这是一个非常奇怪的问题.我几乎整天都把它简化为一个小的可执行脚本,完全展示了这个问题.
问题摘要:我正在使用XML :: Twig从XML文件中提取数据片段,然后我将该数据片段放在另一段数据的中间,让我们将其称为父数据.当我开始时,父数据在其开头具有这种奇怪的不可打印字符.它是供应商提供的数据,所以我无法控制它.我的问题是,在我将数据片段粘贴到父数据的中间之后,最终产品除了最初开始的字符之外还有一个新的非可打印字符.这个新的不可打印字符不在父数据中,也不在子数据片段中.我不知道它来自何处,也不知道它是如何进入我的数据的.
我怀疑它是一个XML :: Twig错误,因为在while循环中从文件句柄读取一行时发生字符串损坏,但是当我删除XML :: Twig代码时,我一直没有成功地重新创建我的问题我的脚本所以我不得不留下它.
这是我第一次体验我正在尝试处理的字符串中的不可打印字符.我需要做一些特别的事情而不是像普通的字符串那样对待它们吗?
我在Windows XP上使用ActiveState Perl 5.10.1和XML :: Twig 3.32(最新)和Eclipse 3.5.1 IDE.
这是一个演示问题的脚本:
use strict;
use warnings;
use XML::Twig;
my $FALSE = 0;
my $TRUE = 1;
my $name = 'KurtsProgram';
my $task = 'MainTask';
my $hidden_char = "\xBF";
my $data = $hidden_char .
'(*********************************************
Data-File-Header-Junk
**********************************************)
PROGRAM MainProgram ()
END_PROGRAM
TASK SecondaryTask ()
END_TASK
TASK MainTask ()
MainProgram;
END_TASK
';
my $new_data = insertProgram( $name, $task, $data …Run Code Online (Sandbox Code Playgroud) 我的问题是:如何将一些参数传递给XML:Twig的处理程序,以及如何从处理程序返回结果.
这是我的代码,硬编码:
<counter name = "music", report type = "month", stringSet index = 4>.
如何通过使用参数来实现这个$counter_name,$type,$id?以及如何返回string_list的结果?谢谢(抱歉,我没有在这里发布xml文件,因为我有一些麻烦.<和>中的任何内容都被忽略).
use XML::Twig;
sub parse_a_counter {
my ($twig, $counter) = @_;
my @report = $counter->children('report[@type="month"]');
for my $report (@report){
my @stringSet = $report->children('stringSet[@index=”4”]');
for my $stringSet (@stringSet){
my @string_list = $stringSet->children_text('string');
print @string_list; # in fact I want to return this string_list,
# not just print it.
}
}
$counter->flush; # free the memory of $counter
}
my $roots …Run Code Online (Sandbox Code Playgroud) 我正在解析XML文件并尝试访问XML文件中的值.
#!/usr/bin/perl -w
use strict;
use XML::Twig;
my $file = 'files/camelids.xml';
print "File :: $file\n";
my $twig = XML::Twig->new();
$twig->parsefile($file);
# print "twig :: $twig\n";
my $root = $twig->root;
# print "root :: $root\n";
my $num = $root->children('species');
print "num :: $num\n\n\n";
print $root->children('species')->first_child_text('common-name');
Run Code Online (Sandbox Code Playgroud)
示例XML文件是:
<?xml version="1.0"?>
<camelids>
<species name="Camelus bactrianus">
<common-name>Bactrian Camel</common-name>
<physical-characteristics>
<mass>450 to 500 kg.</mass>
<appearance>
<in-appearance>
<inside-appearance>This is in inside appearance</inside-appearance>
</in-appearance>
</appearance>
</physical-characteristics>
</species>
</camelids>
Run Code Online (Sandbox Code Playgroud)
输出是:
File :: files/camelids.xml
num :: 1
Can't call method …Run Code Online (Sandbox Code Playgroud) 我XML::Twig用来解析一个非常大的XML文档.我想根据<change></change>标签将其拆分为块.
现在我有:
my $xml = XML::Twig->new(twig_handlers => { 'change' => \&parseChange, });
$xml->parsefile($LOGFILE);
sub parseChange {
my ($xml, $change) = @_;
my $message = $change->first_child('message');
my @lines = $message->children_text('line');
foreach (@lines) {
if ($_ =~ /[^a-zA-Z0-9](?i)bug(?-i)[^a-zA-Z0-9]/) {
print outputData "$_\n";
}
}
outputData->flush();
$change->purge;
}
Run Code Online (Sandbox Code Playgroud)
现在,parseChange当它从XML中提取该块时,它正在运行该方法.它变得非常缓慢.我测试它反对从一个文件中读取XML $/=</change>并编写一个函数来返回XML标记的内容,它的速度要快得多.
有什么东西我缺少或我使用XML::Twig不正确吗?我是Perl的新手.
编辑:以下是更改文件的示例更改.该文件由很多这些文件一个接一个地组成,它们之间不应该有任何东西:
<change>
<project>device_common</project>
<commit_hash>523e077fb8fe899680c33539155d935e0624e40a</commit_hash>
<tree_hash>598e7a1bd070f33b1f1f8c926047edde055094cf</tree_hash>
<parent_hashes>71b1f9be815b72f925e66e866cb7afe9c5cd3239</parent_hashes>
<author_name>Jean-Baptiste Queru</author_name>
<author_e-mail>jbq@google.com</author_e-mail>
<author_date>Fri Apr 22 08:32:04 2011 -0700</author_date>
<commiter_name>Jean-Baptiste Queru</commiter_name>
<commiter_email>jbq@google.com</commiter_email>
<committer_date>Fri Apr 22 08:32:04 2011 …Run Code Online (Sandbox Code Playgroud) 我正在使用XML::Twig以下代码编辑一些 XML 文件:
my $twig = XML::Twig->new(
pretty_print => 'indented',
twig_handlers => {
Vendor => sub {
$_->set_att( 'ID' => $_->{'att'}->{'att1'} );
$_->set_att( 'ID' => $_->{'att'}->{'att2'} );
$_->set_att( 'ID' => $_->{'att'}->{'att3'} );
$_->set_att( 'ID' => $_->{'att'}->{'att4'} );
},
},
);
$twig->parsefile('myfile');
$twig->flush;
Run Code Online (Sandbox Code Playgroud)
问题是这段代码没有在编辑过的文件中以相同的顺序保存 xml 属性。
例如来自输入 xml 的这一行:
<DEVICE OVERWRITE="TRUE" STRING="TRUE" BLOCK="FALSE">
Run Code Online (Sandbox Code Playgroud)
被输出 xml 中的这一行替换:
<DEVICE BLOCK="FALSE" STRING="TRUE" OVERWRITE="TRUE">
Run Code Online (Sandbox Code Playgroud)
如何以与原始文件相同的顺序保存属性,以便在将两个文件与修订系统进行比较时,只能看到我所做的更改?
我想清除放在<loot> </loot>目录树中XML文件中元素内的整个内容.我正在使用Strawberry Perl for Windows 64 bit.
例如,这个XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon"/>
<health="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
<item id="1"/>
<item id="3"/>
<inside>
<item id="6"/>
</inside>
</item>
</loot>
Run Code Online (Sandbox Code Playgroud)
更改的文件应该是:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon"/>
<health="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
</loot>
Run Code Online (Sandbox Code Playgroud)
我有这个代码:
#!/usr/bin/perl
use warnings;
use strict;
use File::Find::Rule;
use XML::Twig;
sub delete_loot {
my ( $twig, $loot ) = @_;
foreach my $loot_entry ( $loot -> children ) {
$loot_entry -> delete;
}
$twig -> flush; …Run Code Online (Sandbox Code Playgroud)