我在XML::Twig中有一个我无法理解的最奇怪的行为。
我有一个XML,它看起来像下面(但要大得多,大约500 MB)
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
<header creationtool="MemoQ" creationtoolversion="6.2.21" segtype="sentence" adminlang="en-us" creationid="" srclang="pt-pt" o-tmf="MemoQTM" datatype="unknown">
<prop type="defclient"> </prop>
<prop type="defproject"> </prop>
<prop type="defdomain"> </prop>
<prop type="defsubject"> </prop>
<prop type="description"> </prop>
<prop type="targetlang">it</prop>
<prop type="name">pt_PT-it_IT</prop>
</header>
<body>
<tu changedate="20120625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-pre"><seg>O recinto do Pavilhão Atlântico, versátil por natureza, está vocacionado para receber os mais variados eventos.</seg></prop>
<prop type="x-context-post"><seg>A Sala Atlântico, com uma arena de 5 200 m2, abriga, com uma versatilidade única, todo o tipo de eventos.</seg></prop>
<seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg>
</tuv>
<tuv xml:lang="it">
<seg>È composto da tre aree fra di esse integrate, le quali sono tutte facilmente adattabili alle caratteristiche specifiche di ogni evento.</seg>
</tuv>
</tu>
<tu changedate="20130625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>O recinto do Pavilhão Atlântico, versátil por natureza, está vocacionado para receber os mais variados eventos.</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
<tu changedate="20140625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
<tu changedate="20140625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Teste</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
<tu changedate="20110625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Teste</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
</body>
</tmx>
下面的代码在文档中传递两次:首先,它生成一个散列,将每个"seg"与最新的"changedate"属性相关联,然后滚动文档,只打印最新的(没有比散列后的"changedate"更小的"changedata")。这是代码:
use 5.010;
use strict;
use warnings;
use XML::Twig;
my $filename = 'pt_PT-it_IT-novo2.tmx';
my $out_filename = 'out.tmx';
open my $out, '>', $out_filename;
binmode $out, ':encoding(UTF-8)';
print "PASSAGE 1...n";
my $first_pass = new XML::Twig (twig_handlers => {tu => &first_pass});
$first_pass->parsefile($filename);
$first_pass->purge();
print "DONEn";
print "nPASSAGE 2....n";
my $second_pass = new XML::Twig (#twig_roots => { 'tu' => 1 },
#twig_print_outside_roots => 1,
pretty_print => 'indented',
twig_handlers => {tu => &second_pass});
$second_pass->parsefile($filename);
close $out;
print "nDONEn";
{my %hash;
sub first_pass {
my($twig, $tu) = @_;
my $seg = $tu->first_child('tuv')->first_child('seg')->text;
my $changedate = $tu->att('changedate');
if (
(!(exists($hash{$seg})) )
|| (($hash{$seg}) lt $changedate)
) {
$hash{$seg} = $changedate;
}
$twig->purge();
}
sub second_pass {
my($twig, $tu) = @_;
#print $original_tu->text;
my $seg = $tu->first_child('tuv')->first_child('seg')->text;
my $changedate = $tu->att('changedate');
#$changedate = substr $changedate, 0, 8;
#my $hash = md5($seg);
if (!(($hash{$seg}) eq $changedate)) {
print "================================n";
print "NOT PRINTEDn";
print $seg;
print "n BECAUSE DATE: ";
print $changedate;
print " IS OLDER THAN FOUND IN PASS ONE: ";
print $hash{$seg};
print "n=================================n";
$twig->purge;
}
else {
$twig->print($out);
$twig->purge;
}
#$twig->flush($out);
}
}
当我在上面的例子上运行上面的代码时,得到的结果是:
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
<body>
<tu changedate="20130625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>O recinto do Pavilhão Atlântico, versátil por natureza, está vocacionado para receber os mais variados eventos.</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
</body>
</tmx>
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
<body>
<tu changedate="20140625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
</body>
</tmx>
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
<body>
<tu changedate="20140625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Teste</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
</body>
</tmx>
正如您所看到的,在每个删除的"tu"("body"one_answers"tmx")之后,我得到了"tu"标记的括号,以及整个xml文档的左括号。
有人知道我该如何解决这个问题吗?
非常感谢您的帮助,无论多么微小!
编辑:可选地,我试着做
if (!(($hash{$seg}) eq $changedate)) {
print "================================n";
print "APAGADOn";
print $seg;
print "n POIS DATA DE ORIGINAL: ";
print $changedate;
print " E MAIS ANTIGA QUE ENCONTRADA: ";
print $hash{$seg};
print "n=================================n";
$tu->delete;
}
$twig->flush($out);
但后来我得到了这个:
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
<header adminlang="en-us" creationid="" creationtool="MemoQ" creationtoolversion="6.2.21" datatype="unknown" o-tmf="MemoQTM" segtype="sentence" srclang="pt-pt">
<prop type="defclient"> </prop>
<prop type="defproject"> </prop>
<prop type="defdomain"> </prop>
<prop type="defsubject"> </prop>
<prop type="description"> </prop>
<prop type="targetlang">it</prop>
<prop type="name">pt_PT-it_IT</prop>
</header>
<body></body>
</tmx>
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
<header adminlang="en-us" creationid="" creationtool="MemoQ" creationtoolversion="6.2.21" datatype="unknown" o-tmf="MemoQTM" segtype="sentence" srclang="pt-pt">
<prop type="defclient"> </prop>
<prop type="defproject"> </prop>
<prop type="defdomain"> </prop>
<prop type="defsubject"> </prop>
<prop type="description"> </prop>
<prop type="targetlang">it</prop>
<prop type="name">pt_PT-it_IT</prop>
</header>
<body>
<tu changedate="20130625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>O recinto do Pavilhão Atlântico, versátil por natureza, está vocacionado para receber os mais variados eventos.</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
<tu changedate="20140625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
<tu changedate="20140625T175037Z" changeid="ana">
<prop type="client"> </prop>
<prop type="project"> </prop>
<prop type="domain"> </prop>
<prop type="subject"> </prop>
<prop type="corrected">no</prop>
<prop type="aligned">yes</prop>
<tuv xml:lang="pt-pt">
<prop type="x-context-post"><seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.</seg></prop>
<seg>Teste</seg>
</tuv>
<tuv xml:lang="it">
<seg>Lo spazio di pertinenza del Pavilhão Atlântico, versatile per natura, è adatto a ricevere gli eventi più svariati.</seg>
</tuv>
</tu>
</body>
</tmx>
</body>
</tmx>
它在中间有很多"body"标签,也有很多"header"标签。这就是为什么我决定尝试"只打印最近的"策略。
再次感谢达森
如果您不想打印整个树枝,请不要打印。只打印相关部分:
# $twig->print($out); # Prints everything.
$tu->print($out);
我认为第二个传递处理程序应该删除tu
(如果它没有使用),或者刷新树枝(否则):
sub second_pass {
my($twig, $tu) = @_;
#print $original_tu->text;
my $seg = $tu->first_child('tuv')->first_child('seg')->text;
my $changedate = $tu->att('changedate');
#$changedate = substr $changedate, 0, 8;
#my $hash = md5($seg);
if (!(($hash{$seg}) eq $changedate)) {
print "================================n";
print "NOT PRINTEDn";
print $seg;
print "n BECAUSE DATE: ";
print $changedate;
print " IS OLDER THAN FOUND IN PASS ONE: ";
print $hash{$seg};
print "n=================================n";
$tu->delete;
}
else {
$t->flush($out);
}
}
刷新分支的末端应该在解析结束时自动发生。
对不起,我没看到你编辑。我认为,将当前元素上的delete和flush混合在一起会在模块的代码中造成一些混乱。看看冲洗是否能改善情况。