如何从一个巨大的xml文件中删除重复项,但在perl中使用XML :: Twig保留那些具有最新'changedate'属性的重复项?

时间:2013-08-06 15:57:56

标签: xml perl xml-twig

我有以下巨大的XML文件:

<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "56.dtd">
<body>
<tu changedate="20130625T175037Z"">
  <tuv xml:lang="pt-pt">
    <prop type="x-context-pre">&lt;seg&gt;Some text.&lt;/seg&gt;</prop>
    <prop type="x-context-post">&lt;seg&gt;Other text.&lt;/seg&gt;</prop>
    <seg>The text I'm interested.</seg>
  </tuv>
  <tuv xml:lang="it">
    <seg>And it's translation in italian.</seg>
  </tuv>
 </tu> 

 .... followed by other <tu>'s
</body>

我正在使用哈希“将每个”seg“内容与其更改关联,以便我可以使用处理程序检查”seg“是否已经存在,然后查看找到的版本是否较旧以及是否所以,删除它。这种方法的问题是,如果找到的版本更新,没有办法删除在xml文件中解析的旧版本。这是我到目前为止的代码:

use 5.010;

use strict;
use warnings;

use XML::Twig;
use Digest::MD5 qw(md5);

my $filename = 'pt_PT-it_IT.tmx';
my $out_filename = 'out.xml';
open my $out, '>', $out_filename;
binmode $out;

my $original_twig = new XML::Twig (pretty_print => 'indented', twig_handlers => {tu => \&original_tu});
$original_twig->parsefile($filename);
$original_twig->flush($out);
close $out;

{ my %md5;
sub original_tu {
my($twig, $original_tu) = @_;
#print $original_tu->text;
my $original_seg = $original_tu->first_child('tuv')->first_child('seg')->text;

my $original_changedate = $original_tu->att('changedate');
$original_changedate = substr $original_changedate, 0, 8;
$hash = md5(original_seg);
if (exists($md5{$hash})) {
    if (($md5{$hash}) gt $original_changedate) {
        print "================================\n";
            print "DELETED\n";
            print $original_seg;
            print "\n BECAUSE ORIGINAL DATE: ";
            print $original_changedate;
            print " IS OLDER THAN THE FOUND ONE: ";
            print $other_changedate;
            print "\n=================================\n";
            $original_tu->delete(); 

        }


    }
else
    $md5{$hash} = $original_changedate;
}

}

提前感谢任何关于如何(重述)删除重复项的重复项,其中包含最大值(700 MB)XML文件中的“changedate”值。

谢谢!

1 个答案:

答案 0 :(得分:2)

我并不清楚tuseg是如何相关的。因此,我很难为您提供可能无法满足您需求的代码。

所以只是一个小评论,我相信你已经考虑过了:我认为你将不得不在2遍中做到这一点:

  1. 第一次传递确定每个seg的最新更改,将此数据存储在哈希{ md5 => date }中,所有tu,您创建$md5{$hash}的方式
  2. 然后在2cd传递中删除与存储值相比tu更低(或者只是不同)的所有changedate
  3. 希望散列足够小以适应内存。它比一次通过更慢(并且不太令人满意!),但它应该有效。