0

私は以下の形式のエンティティを含む次の大きなxmlファイルを持っています:誰かがxml :: twigでそれを処理する方法を手伝ってもらえますか?

 <root >
      <entity id="1" last_modified="2011-10-1">
        <entity_title> title</entity_title>
        <entity_description>description  </entity_description>
        <entity_x>  x </entity_x>
        <entity_y>  x </entity_y>
        <entity_childs>
          <child flag="1">
            <child_name>name<child_name>
            <child_type>type1</child_type>
            <child_x> some_text</child__x>
          </child>
          <child flag="1">
            <child_name>name1<child_name>
            <child_type>type2</child_type>
            <child_x> some_text</child__x>
          </child>
         <entity_sibling>
          <family value="1" name="xc">fed</ext_ref>
          <family value="1" name="df">ff</ext_ref> 
         </entity_sibling>
    <\root>


 ;

以下のコードを実行してメモリを使い果たしました!

my $file = shift ||die $!;

my $twig = XML::Twig->new();

my $config = $twig->parsefile( $file )->simplify();

print Dumper( $config );
4

2 に答える 2

4

XML :: Twigは、小さいドキュメント用と大きいドキュメント用の2つのモードで実行できます。あなたはそれが大きいと言うので、ドキュメントの概要にリストされている2番目のアプローチが必要です。

巨大なドキュメントを処理する例は次のようになります。

 # at most one div will be loaded in memory
  my $twig=XML::Twig->new(   
    twig_handlers => 
      { title   => sub { $_->set_tag( 'h2') }, # change title tags to h2
        para    => sub { $_->set_tag( 'p')  }, # change para to p
        hidden  => sub { $_->delete;       },  # remove hidden elements
        list    => \&my_list_process,          # process list elements
        div     => sub { $_[0]->flush;     },  # output and free memory
      },
    pretty_print => 'indented',                # output will be nicely formatted
    empty_tags   => 'html',                    # outputs <empty_tag />
                         );
    $twig->flush;                              # flush the end of the document

ですから、あなたはその方法を使いたいと思います。あなたが現在使っている方法ではなく、小さな文書のためだけに記されています。

于 2011-10-05T22:06:15.577 に答える
2

Yep, there is no magic in XML::Twig, if you write $twig->parsefile( $file )->simplify(); then it will load the entire document in memory. I am afraid you will have to put some work into it to get just the bits you want and discard the rest. Look at the synopsys or the XML::Twig 101 section at the top of the docs for more information.

This is becoming a FAQ, so I have added the blurb above to the docs of the module.

In this particular case you probably want to set a handler (using the twig_handlers option) on entity, process each entity and then discard it by using flush if you are updating the file, or purge if you just want to extract data from it.

So the architecture of the code should look like this:

#!/usr/bin/perl
use strict;
use warnings;

use XML::Twig;

my $file = shift;    

my $twig=XML::Twig->new( twig_handlers => { entity => \&process_entity },)
                  ->parsefile( $file);

exit;

sub process_entity
  { my( $t, $entity)= @_;

    # do what you have to do with $entity

   $t->purge;
  }    
于 2011-10-06T08:29:47.297 に答える