XML :: Twig在我不想要它们时给我标签,同时在Perl中有选择地打印xml元素

时间:2013-08-08 09:17:59

标签: xml perl xml-twig

我遇到了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">&lt;seg&gt;O recinto do Pavilhão Atlântico, versátil por natureza, está vocacionado para receber os mais variados eventos.&lt;/seg&gt;</prop>
      <prop type="x-context-post">&lt;seg&gt;A Sala Atlântico, com uma arena de 5 200 m2, abriga, com uma versatilidade única, todo o tipo de eventos.&lt;/seg&gt;</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">&lt;seg&gt;Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/seg&gt;</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">&lt;seg&gt;Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/seg&gt;</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">&lt;seg&gt;Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/seg&gt;</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">&lt;seg&gt;Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/seg&gt;</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”属性相关联,然后滚动文档,只打印“tu”,它们是最近的(没有比哈希更小的“改变”)。这是代码:

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 "DONE\n";


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 "\nDONE\n";

{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 PRINTED\n";
                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">&lt;seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/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">&lt;seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/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">&lt;seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/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”和“tmx”)以及整个xml文档的左括号后,我会得到“tu”标签的括号。

有谁知道如何解决这个问题?

非常感谢您的帮助,不管它多么小!

编辑: 或者,我尝试了

if (!(($hash{$seg}) eq $changedate)) {
        print "================================\n";
            print "APAGADO\n";
            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">&lt;seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/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">&lt;seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/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">&lt;seg>Composto por três áreas integradas, todos os espaços são facilmente adaptados às características de cada evento.&lt;/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>

中间有很多“身体”标签以及“标题”标签。 这就是我决定尝试“仅打印最新”策略的原因。

再次感谢 大森

2 个答案:

答案 0 :(得分:2)

如果您不想打印整个树枝,请勿打印。仅打印相关部分:

# $twig->print($out); # Prints everything.
$tu->print($out);

答案 1 :(得分:2)

我认为第二个传递处理程序应该删除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 PRINTED\n";
                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);
}

}

刷新树枝的末端应该在解析结束时自动发生。

抱歉,我没见过你编辑。我认为发生的事情是在当前元素上混合删除和flush会在模块的代码中造成一些混乱。看看冲洗条件是否有所改善。