XML::twig 过滤 PERL 中的 XML 个父节点
XML::twig to filter XML parent nodes in PERL
我有一个 xml 片段
<head>
<a>
<b attr_1=1>
<b attr_1=2>
<c attr_2 =3 attr_3 =5/>
<c attr_2 =4 attr_3 =6 />
</b>
</a>
<a>
<b attr_1=1/>
<b attr_1=3>
<c attr_2 =3 attr_3 =5/>
<c attr_2 =10 attr_3 =10/ >
</b>
</a>
</head>
现在只有那些具有 <b attr_1 =3>
(至少一个)并且至少有一个子 <c>
具有 attr_2=10
和 attr_3 =10
的节点是合法的。
因此输出文件应该有以下交易
<a>
<b attr_1=1/>
<b attr_1=3>(this is the legitimate value)
<c attr_2 =3 attr_3 =5/>
<c attr_2 =10 attr_3 =10/ >(this is the legitimate combination)
</b>
</a>
我的密码是
use strict;
use warnings;
use XML::Twig;
my $twig = new XML::Twig( twig_handlers => { a=> \&a} );
$twig->parsefile('1511.xml');
$twig->set_pretty_print('indented');
$twig->print_to_file('out.xml');
sub a {
my ( $twig, $a ) = @_ ;
$a->cut
unless grep { $_->att( 'attr_1' ) eq '3' } $a->children( 'b' )
}
这样我就可以升到等级了。如果有人可以解释如何遍历和 grep 直到节点 B 内的节点 C,请提供帮助。
您的 XML 文件中有一些错误。另外,您似乎删除了描述的某些部分。您还可以为处理程序和 *child
方法设置一些属性限制。
sub a {
my ( $twig, $a ) = @_ ;
my $cut = 1;
foreach my $b ($a->children('b[@attr_1="3"]')){
$cut &&= not grep {$_->att('attr_2') eq '10'
and $_->att('attr_3') eq '10'} $b->children('c');
}
$a->cut if $cut;
}
这是我用来测试的文件:
<head>
<a>
<b attr_1="1" />
<b attr_1="2">
<c attr_2 ="3" attr_3 ="5"/>
<c attr_2 ="4" attr_3 ="6" />
</b>
</a>
<a>
<b attr_1="1"/>
<b attr_1="3">
<c attr_2 ="3" attr_3 ="5"/>
<c attr_2 ="10" attr_3 ="10" />
</b>
</a>
<a>
<b attr_1="1"/>
<b attr_1="3">
<c attr_2 ="3" attr_3 ="5"/>
<c attr_2 ="10" attr_3 ="12" />
</b>
</a>
</head>
输出:
<head>
<a>
<b attr_1="1"/>
<b attr_1="3">
<c attr_2="3" attr_3="5"/>
<c attr_2="10" attr_3="10"/>
</b>
</a>
</head>
编辑: 如果您真的只想使用 grep
语句,您可以像这样使用一些嵌套的 grep,尽管我建议您使用上面的语句,更具可读性的解决方案。
$a->cut unless
grep {grep {$_->att('attr_2') eq '10' and $_->att('attr_3') eq '10'}
$_->children('c')} $a->children('b[@attr_1="3"]');
我有一个 xml 片段
<head>
<a>
<b attr_1=1>
<b attr_1=2>
<c attr_2 =3 attr_3 =5/>
<c attr_2 =4 attr_3 =6 />
</b>
</a>
<a>
<b attr_1=1/>
<b attr_1=3>
<c attr_2 =3 attr_3 =5/>
<c attr_2 =10 attr_3 =10/ >
</b>
</a>
</head>
现在只有那些具有 <b attr_1 =3>
(至少一个)并且至少有一个子 <c>
具有 attr_2=10
和 attr_3 =10
的节点是合法的。
因此输出文件应该有以下交易
<a>
<b attr_1=1/>
<b attr_1=3>(this is the legitimate value)
<c attr_2 =3 attr_3 =5/>
<c attr_2 =10 attr_3 =10/ >(this is the legitimate combination)
</b>
</a>
我的密码是
use strict;
use warnings;
use XML::Twig;
my $twig = new XML::Twig( twig_handlers => { a=> \&a} );
$twig->parsefile('1511.xml');
$twig->set_pretty_print('indented');
$twig->print_to_file('out.xml');
sub a {
my ( $twig, $a ) = @_ ;
$a->cut
unless grep { $_->att( 'attr_1' ) eq '3' } $a->children( 'b' )
}
这样我就可以升到等级了。如果有人可以解释如何遍历和 grep 直到节点 B 内的节点 C,请提供帮助。
您的 XML 文件中有一些错误。另外,您似乎删除了描述的某些部分。您还可以为处理程序和 *child
方法设置一些属性限制。
sub a {
my ( $twig, $a ) = @_ ;
my $cut = 1;
foreach my $b ($a->children('b[@attr_1="3"]')){
$cut &&= not grep {$_->att('attr_2') eq '10'
and $_->att('attr_3') eq '10'} $b->children('c');
}
$a->cut if $cut;
}
这是我用来测试的文件:
<head>
<a>
<b attr_1="1" />
<b attr_1="2">
<c attr_2 ="3" attr_3 ="5"/>
<c attr_2 ="4" attr_3 ="6" />
</b>
</a>
<a>
<b attr_1="1"/>
<b attr_1="3">
<c attr_2 ="3" attr_3 ="5"/>
<c attr_2 ="10" attr_3 ="10" />
</b>
</a>
<a>
<b attr_1="1"/>
<b attr_1="3">
<c attr_2 ="3" attr_3 ="5"/>
<c attr_2 ="10" attr_3 ="12" />
</b>
</a>
</head>
输出:
<head>
<a>
<b attr_1="1"/>
<b attr_1="3">
<c attr_2="3" attr_3="5"/>
<c attr_2="10" attr_3="10"/>
</b>
</a>
</head>
编辑: 如果您真的只想使用 grep
语句,您可以像这样使用一些嵌套的 grep,尽管我建议您使用上面的语句,更具可读性的解决方案。
$a->cut unless
grep {grep {$_->att('attr_2') eq '10' and $_->att('attr_3') eq '10'}
$_->children('c')} $a->children('b[@attr_1="3"]');