XML::TWIG 过滤 PERL 中的 XML

XML::TWIG to filter the XML in PERL

我莫名其妙地卡住了,撞着我的头。 我必须从一个巨大的 XML 文件中删除不需要的交易。

<TRADEEXT>
  <TRADE origin = 1,version =1>
     <EVENT externtype ='PROC'/>
     <EVENT externtype ='PROCC'/>
  </TRADE>
  <TRADE origin = 1,version =1>
     <EVENT externtype ='PROCC'/>
  </TRADE>
</TRADEEXT>

现在,第二个交易在不合法的节点内有 externtype = 'PROCC'(合法值为 'PROC')

因此最终输出应该是

<TRADEEXT>
   <TRADE origin = 1,version =1>
      <EVENT externtype ='PROC'/>
      <EVENT externtype ='PROCC'/>
   </TRADE>
<TRADEEXT>

应该将其粘贴到新文件中。这里要注意的最重要的一点是,即使一个事件具有非法价值,由于另一个事件具有合法价值,贸易也变得合法。 因此,至少一个事件应该是合法的,这将使整个交易合法 我的密码是

use strict;
use warnings;
use XML::Twig;

my $twig = new XML::Twig( twig_handlers => { TRADE => \&TRADE } );
$twig->parsefile('1513.xml');
$twig->set_pretty_print('indented');
$twig->print_to_file('out.xml');

sub TRADE {
    my ( $twig, $TRADE ) = @_;
    foreach  my $c ($TRADE->children('EVENT')) 
    {
     $c->cut($TRADE) unless
     $c->att('eventtype') eq "PROC"

      ;
    }
}

不幸的是,它正在删除 EVENT 标签而不是 TRADE 标签。

如有任何提示,我们将不胜感激。

我不知道XML::Twig。在 XML::LibXML,你会做

for my $bad_trade ('/TRADEEXT/TRADE[ EVENT/@externtype = "PROCC" ]') {
    $bad_trade->parentNode->removeChild($bad_trade);
}

您需要 $TRADE->cut 而不是 $c->cut。但是,由于您的条件是 $c,您可能需要改为执行以下操作:

sub TRADE {

    my ( $node, $TRADE ) = @_ ;

    $TRADE->cut
      unless grep { $_->att( 'eventtype' ) eq 'PROC' } $TRADE->children( 'EVENT' );
}