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 能够以两种模式运行,用于小型或大型文档。你说它很大,所以你想要文档概要中列出的第二种方法。

处理大型文档的示例如下所示:

 # 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

是的,XML::Twig 没有魔法,如果你写$twig->parsefile( $file )->simplify();的话,它会将整个文档加载到内存中。恐怕您将不得不在其中投入一些工作才能获得您想要的部分并丢弃其余部分。查看文档顶部的 synopsys 或 XML::Twig 101 部分以获取更多信息。

这正在成为一个常见问题解答,因此我已将上面的简介添加到模块的文档中。

在这种特殊情况下,您可能希望在 上设置处理程序(使用twig_handlers选项)entity,处理每个实体,然后flush在更新文件或purge只想从中提取数据时使用丢弃它。

所以代码的架构应该是这样的:

#!/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 回答