代码之家  ›  专栏  ›  技术社区  ›  Paul Tomblin

在Perl中,如何解析一个太大而无法放入可用内存的XML文件?

  •  1
  • Paul Tomblin  · 技术社区  · 14 年前

    我有一个非常大的XML文件(如果您愿意,它是EAD的一个AIXM文件,但这并不重要)。为了弄清楚它是如何被使用的,我想写一个简单的脚本来遍历每个节点,记录它下面发生了什么子节点以及发生了多少次,这样我就可以看到哪些节点包含 <AptUid> 以及是否大多数 <Rdn> 节点具有 <GeoLat> 不管是不是节点之类的。

    我试着用 XML::Simple 但它太大了,无法记忆。是否有一个XML解析器允许我一次只查看一个文件?

    6 回复  |  直到 14 年前
        1
  •  1
  •   Community CDub    9 年前

    试试 XML::Parser 模块。应该是你需要的。

    another link

        2
  •  8
  •   Sinan Ünür    14 年前
        3
  •  2
  •   falconcreek    14 年前

    您想使用SAX解析器 XML::SAX 实现start-element和end-element方法来构建节点树

        4
  •  1
  •   Yann Ramin    14 年前

    您应该使用流分析程序,例如 XML::Parser (依次是上面的一层 expat )您必须为您感兴趣的标签注册处理程序,并自己做簿记。与其他流模型(如SAX)一样,您不会同时获得文件的整个视图(除了您在代码中显式使用的子集)。

        5
  •  1
  •   Owen S.    14 年前

    下面是一个使用XML::Parser的解决方案。欢迎评论。

    use XML::Parser;
    
    %elemMap = ();
    
    @context = ();
    
    sub on_start {
        my ($p, $elemName, @alist) = @_;
        my $parent = @context[-1];
        if ($parent) {
            $elemMap{$parent}{$elemName}++;
        }        
        push(@context, $elemName);
    }
    
    sub on_end {
        pop(@context);
    }
    
    $p = new XML::Parser(Handlers => {Start => \&on_start, End => \&on_end});
    $p->parse(STDIN);
    
    while (my ($elem, $childElems) = each(%elemMap)) {
        while (my ($childElem, $count) = each(%{$childElems})) {
            print "$elem > $childElem: $count\n";
        }
    }
    
        6
  •  0
  •   the Tin Man    14 年前

    当您第一次尝试找出未知XML文件的结构时,请在一个或多个文件中打开它,并开始对其进行分页。不要使用试图将整个文件加载到内存中的编辑器,除非您非常希望等待您的计算机。

    当您不知道数据是如何构造的时,构建一个解析器将是非常令人沮丧的,所以不要先跳到编码中去,跳到探索中去,直到您知道足够开始编码为止。