为什么findvalue非常慢(LibXML)

时间:2016-10-26 14:19:42

标签: xml perl

数组/项目中有30,000组数据。 在我的工作服务器上,(A)需要30分钟,(B)需要5秒钟。 在我的家用电脑上,(A)和(B)都需要5秒钟。

为什么(A)在我的工作服务器上这么慢?

===========================================
                    foreach my $node2 ($node1->findnodes('array/item')){

= APPROACH (A) ============================
                        $xml_index = $node2->findvalue('index');
                        $xml_value = $node2->findvalue('value');

= APPROACH (B) ============================
                        foreach my $node3 ($node2->childNodes){
                            if($node3->nodeType() == XML_ELEMENT_NODE){
                                if($node3->getName() eq "index"){
                                    $xml_index=$node3->to_literal();
                                }
                                if($node3->getName() eq "value"){   
                                    $xml_value=$node3->to_literal();
                                }
                            }
                        }
===========================================

如果你需要看到整件事 -

#! /usr/bin/perl -w

use warnings;
use strict;
use XML::LibXML;
use POSIX qw( strftime );
use File::Basename;

my $parser = XML::LibXML->new();

my $filebase; my $file; my $int; my $boolDone; my $str;
my $line; my $whole; my $name; my $inputfilename;my $inputfolder;my $outputfile; my $doc; my $dt;my $dt1;my $dt2;my $dto_type;
my $xml_index; my $xml_value;

# INPUT
$inputfolder = ".";
opendir (DIR, $inputfolder) or die $!;

while ($inputfilename = readdir(DIR)){
    # one loop per file
    next if $inputfilename eq '.';
    next if $inputfilename eq '..';

    if(substr($inputfilename,-4) eq ".dto"){
        $doc = $parser->parse_file($inputfolder."/".$inputfilename);
        $dto_type = $doc->findvalue('object/class');

        if($dto_type eq "sshp.escs.cecs.mips.data.MipsPeerStatusObject_TImpl"){
            print "Importing File: ".$inputfilename."\n";

            #OUTPUT
            $outputfile = &ExtractFilenameNoExt($inputfilename);
            $outputfile = $outputfile.".csv";
            open(my $fh, '>', $outputfile) or die "Error '$outputfile' $!";

            #csv file headers
            $line = "index,"."value";
            print $fh $line."\n";

            $int = 1;
            foreach my $node1 ($doc->findnodes('object/field/object/field/object/field/object/field')){
                if($node1->findvalue('name') eq "statusData"){
                    foreach my $node2 ($node1->findnodes('array/item')){

#                       $xml_index = $node2->findvalue('index');
#                       $xml_value = $node2->findvalue('value');

                        foreach my $node3 ($node2->childNodes){
                            if($node3->nodeType() == XML_ELEMENT_NODE){
                                if($node3->getName() eq "index"){
                                    $xml_index=$node3->to_literal();
                                }
                                if($node3->getName() eq "value"){   
                                    $xml_value=$node3->to_literal();
                                }
                            }
                        }

                        $line = $xml_index.",".$xml_value;
                        print $fh $line."\n";
                        $xml_index = "";
                        $xml_value = "";

                        if($int %10000 == 0){
                            print $int."\n";
                        }
                        $int++;
                    }
                }
            }
            close $fh;
        }
    }
}

my $elapsed_seconds = time - $^T;
print "duration: ".$elapsed_seconds." seconds";

sub ExtractFilenameNoExt(){
    my ($file) = @_;
    $file = basename($file);
    return substr($file,0,(length($file)-length(ExtractExt($file))-1));
}
sub ExtractExt{
    my ($file) = @_;
    return substr($file, rindex($file, '.') + 1);
}

如果你需要查看xml的样本 -

<?xml version='1.0' encoding='UTF-8'?>
<object>
  <field>
    <object>
      <field>
        <object>
          <field>
            <object>
              <field>
                <name>statusData</name>
                <class>[B</class>
                <array>
                  <class>[B</class>
                  <size>30152</size>
                  <item>
                    <class>java.lang.Byte</class>
                    <index>0</index>
                    <value>0</value>
                  </item>
                  <item>
                    <class>java.lang.Byte</class>
                    <index>1</index>
                    <value>0</value>
                  </item>
                  <item>
                    <class>java.lang.Byte</class>
                    <index>30150</index>
                    <value>-63</value>
                  </item>
                  <item>
                    <class>java.lang.Byte</class>
                    <index>30151</index>
                    <value>-24</value>
                  </item>
                </array>
              </field>
            </object>
          </field>
        </object>
      </field>
    </object>
  </field>
</object>

2 个答案:

答案 0 :(得分:2)

我会尝试更像:

use XML::Rules;

my @rules = (
  item => [
    'array' => sub {
      my $item = $_[1];
      print "index: $item->{index} value: $item->{value}\n";
    },
  ],
  'index,value' => 'content',
  _default => undef,
);

my $xr = XML::Rules->new(
  rules => \@rules,
);
$xr->parse($xml);
# or
$xr->parse_file($xml_file);

答案 1 :(得分:1)

在你的方法A中,我认为findvalue方法创建了一个内部读取所有内容的循环。 我要做的是尝试编写类似于方法B

的东西