为什么我用Perl的XML :: Simple会出现“Out of memory”错误?

时间:2010-09-16 11:30:54

标签: xml perl parsing

编辑::

大家好,

我有一个像这样的XML文件,

        <message>
            <c1>
                <rrcConnectionSetupComplete>
                    <rrc-TransactionIdentifier>2</rrc-TransactionIdentifier>
                    <criticalExtensions>
                        <c1>
                            <rrcConnectionSetupComplete-r8>
                                <selectedPLMN-Identity> 1 </selectedPLMN-Identity>
                                <dedicatedInfoNAS> 07410109014290112345671000028020000f0 </dedicatedInfoNAS>
                            </rrcConnectionSetupComplete-r8>
                        </c1>
                    </criticalExtensions>
                </rrcConnectionSetupComplete>
            </c1>
        </message>

我使用这样的Perl代码访问xml文件中的数据(我应该坚持这种访问格式)

#!/usr/bin/perl

use strict;

use XML::Simple;

my $xml = new XML::Simple;

my $data = $xml->XMLin("uL-DCCH-Message.xml");

my $rrc_trans_identifier = $data->{'c1'}->{'rrcConnectionSetupComplete'}->{'rrc-TransactionIdentifier'};
print "rrc_trans_id :: $rrc_trans_identifier\n";

my $selected_plmn_id = $data->{c1}->{rrcConnectionSetupComplete}->{criticalExtensions}->{c1}->{'rrcConnectionSetupComplete-r8'}->{'selectedPLMN-Identity'};
print "plmn identity :: $selected_plmn_id\n";

my $rrc_dedicated_info_nas = $data->{c1}->{rrcConnectionSetupComplete}->{criticalExtensions}->{c1}->{'rrcConnectionSetupComplete-r8'}->{dedicatedInfoNAS};
print "dedicated info nas :: $rrc_dedicated_info_nas\n";

产生的输出是,

rrc_trans_id :: 2
plmn identity ::  1
dedicated info nas ::  07410109014290112345671000028020000f0

使用XML :: Simple的Perl代码适用于较小的XML文件(如上面的输出所示)。

但是如果XML文件很大,则XML :: Simple无法处理,并且显示错误消息Ran out of memory。

我的问题是,我是否可以使用任何其他XML解析器,以便我可以按照上面显示的类似方式访问XML文件中的元素???

如果有任何其他解析器可用,可以通过遵循我遵循的XML :: Simple的相同约定来提供示例。

请帮助我,我正在努力解决这个问题

4 个答案:

答案 0 :(得分:11)

如果没有能够看到代码或代表性的例子,我就会减少猜测。我敢打赌,XML文件非常庞大,而且你在尝试存储数据结构时内存不足。切换到流式样XML解析器,如XML::Twig

通常,巨大的XML文件将是一组记录,您最终只是循环遍历您构建的数据结构。更好,更快的方法是在你去的时候处理文件:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

sub process_record {
    my $rec = shift;
    print "@{$rec}{qw/field1 field2 field3/}\n";
}

my $t = XML::Twig->new(
    twig_handlers => {
        record => sub {
            my ($t, $elt) = @_;

            my %record = map {
                $_ => $elt->first_child($_)->text
            } qw/field1 field2 field3/;

            process_record(\%record);

            #get rid of any memory that is being held
            $t->purge;
        },
    }
);

$t->parse(\*DATA);

__DATA__
<root>
    <record>
        <field1>1</field1>
        <field2>a</field2>
        <field3>foo</field3>
    </record>
    <record>
        <field1>2</field1>
        <field2>b</field2>
        <field3>bar</field3>
    </record>
    <record>
        <field1>3</field1>
        <field2>c</field2>
        <field3>baz</field3>
    </record>
</root>

答案 1 :(得分:3)

每当XML :: Simple没有按照你想要的那样做时,就应该更好地使用它了。它旨在处理小哈希,而不是解决所有XML需求。除此之外,在我们甚至可以猜出问题之前,你必须先告诉我们你的情况。

当您遇到问题时,请尝试在小型测试用例中重现它。这可能就像读取文件并访问它的程序一样简单。请记住,您是负责解决问题的主要人物。 :)

答案 2 :(得分:2)

对于大型XML文件,您可以使用SAX解析器,例如XML::SAX。见perldoc XML::SAX::Intro XML::Simple更适合解析小文件,例如CONFIGS。

答案 3 :(得分:2)

XML::Twig

中为您提供最新的示例
use strict;
use warnings;
use XML::Twig;

XML::Twig->new(
    twig_handlers => {
        'c1/rrcConnectionSetupComplete' => \&my_stuff,
    }
)->parsefile( 'uL-DCCH-Message.xml' );

sub my_stuff {
    my ($twig, $elt) = @_;

    my $rrc_trans_identifier = $elt->field( 'rrc-TransactionIdentifier' );
    print "rrc_trans_id :: $rrc_trans_identifier\n";

    my $twiglet = $elt->first_child('criticalExtensions')
                      ->first_child('c1')
                      ->first_child('rrcConnectionSetupComplete-r8');


    my $selected_plmn_id = $twiglet->first_child_text('selectedPLMN-Identity');
    print "plmn identity :: $selected_plmn_id\n";    

    my $rrc_dedicated_info_nas = $twiglet->first_child_text('dedicatedInfoNAS');
    print "dedicated info nas :: $rrc_dedicated_info_nas\n";

    $twig->purge;
}

这完全符合您的要求:

rrc_trans_id :: 2
plmn identity ::  1 
dedicated info nas ::  07410109014290112345671000028020000f0 


重要

  • 以上适用于您提供的示例,但根据您的具体要求,您可以通过几种不同的方式在XML::Twig中获得相同的结果。

  • 请不要给我这个问题的答案! Chas&amp; eugene首先出现在你的问题的正确答案上,而brian跟进了无处不在的答案。

/ I3az /