如何使用Perl';s XML::细枝?

如何使用Perl';s XML::细枝?,xml,perl,twig,Xml,Perl,Twig,我有一些XML文件,如下所示: <machines> <server> 127.0.0.1 </server> <proxy> <ip>127.0.0.2</ip> <etc>abc</etc> </proxy> </machines> 127.0.0.1 127.0.0.2 abc 我想保留服务器并删除其他服务器,输出应为: <machin

我有一些XML文件,如下所示:

<machines>
<server>
    127.0.0.1
</server>
<proxy>
    <ip>127.0.0.2</ip>
    <etc>abc</etc>
</proxy>
</machines>

127.0.0.1
127.0.0.2
abc
我想保留服务器并删除其他服务器,输出应为:

<machines>
<server>
127.0.0.1
</server>
</machines>

127.0.0.1
我写的剧本如下:

use warnings;
use strict;
use feature ':5.10';
use XML::Twig;

my $path='C:\strawberry\perl\site\lib\file.xml';
my $filehandle;
my $tweak_server =sub{
    my ($twig, $root) =@_;
    my $elt=$root;
    while( $elt=$elt->next_elt($root)){
        my $tag=$elt->tag;
        say $tag;
        if ($tag!~/server/){
            $elt->delete($tag);         
        }       
    }
    $twig->flush;
};




open( $filehandle, "+<$path") or die "cannot open out file out_file:$!";
my $roots = { machines => 1 };
my $handlers = { 'machines' => $tweak_server,
            };
my $twig = new XML::Twig(TwigRoots => $roots,
                 TwigHandlers => $handlers,
                 pretty_print  => 'indented'#,
                # twig_print_outside_roots => \*$filehandle
                 );
$twig->parsefile($path);
close $filehandle;
use warnings;
use strict;
use feature ':5.10';
use XML::Twig;

my $tweak_server =sub{
my ($twig, $root) =@_;
my $elt=$root;
my $text=$elt->first_child_text('id');
if ($text=~m/12/){
    while( $elt=$elt->next_elt('#ELT')){
        my $tag=$elt->tag;
        say $tag;
        if ($tag!~/id/){
            $elt->delete;           
        }       
    }
}
};

my $roots = { machines => 1 };
my $handlers = { 'machines/aaa' => $tweak_server,
            };
my $twig =XML::Twig->new(TwigRoots => $roots,
                 TwigHandlers => $handlers,
                 pretty_print  => 'indented'#,
                # twig_print_outside_roots => \*$filehandle
                 )
    ->parse( \*DATA) 
    ->print; 
__DATA__

<machines> 
<server> 127.0.0.1 </server> 
<aaa>
<id>12</id> 
<ip>127.0.0.2</ip>   
<option>127.0.0.6</option>
<etc>abc</etc>
</aaa> 
<aaa>
<id>14</id> 
<ip>127.0.0.2</ip>   
<etc>abc</etc>
</aaa> 
<aaa>
<id>15</id> 
<ip>127.0.0.2</ip>
<etc>abc</etc>
</aaa>
</machines>
使用警告;
严格使用;
使用特征“:5.10”;
使用XML::Twig;
我的$path='C:\草莓\perl\site\lib\file.xml';
我的$filehandle;
我的$tweak_server=sub{
我的($twig,$root)=@;
my$elt=$root;
while($elt=$elt->next_elt($root)){
my$tag=$elt->tag;
说$tag;
如果($tag!~/server/){
$elt->delete($tag);
}       
}
$twig->flush;
};

打开($filehandle,“+以下命令将删除代理
元素:

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

my $str = '
<machines>
<server>
    127.0.0.1
</server>
<proxy>
    <ip>127.0.0.2</ip>
    <etc>abc</etc>
</proxy>
</machines>
';

my $t = XML::Twig->new(
        twig_handlers => {
            proxy => sub { $_->delete() },
        },
        pretty_print  => 'indented',
);
$t->parse($str);
$t->print($str);
print "\n";

__END__

<machines>
  <server>
    127.0.0.1
</server>
</machines>
使用警告;
严格使用;
使用XML::Twig;
我的$str
127.0.0.1
127.0.0.2
abc
';
my$t=XML::Twig->new(
细枝处理程序=>{
proxy=>sub{$\->delete()},
},
漂亮的打印=>“缩进”,
);
$t->parse($str);
$t->打印($str);
打印“\n”;
__结束__
127.0.0.1

如果您不想打印出
server
#PCDATA
,那么就不要打印
say$tag;

如果您的要求是只保留服务器元素,那么您可以通过将它们作为
twig_根
来告诉模块。这将产生保留XML和服务器元素根的效果(及其内容),同时放弃所有其他内容:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots => { server => 1 },
                pretty_print => 'indented',
              )
         ->parse( \*DATA)
         ->print;

__DATA__
<machines>
<server>
    127.0.0.1
</server>
<proxy>
    <ip>127.0.0.2</ip>
    <etc>abc</etc>
</proxy>
</machines>
!/usr/bin/perl
严格使用;
使用警告;
使用XML::Twig;
XML::Twig->new(Twig\u根=>{server=>1},
漂亮的打印=>“缩进”,
)
->解析(\*数据)
->印刷品;
__资料__
127.0.0.1
127.0.0.2
abc

你会得到
#PCDATA
,因为这是文本内容的“标签”。如果你想循环使用“真实”元素,请使用
$elt->next_elt('#elt')
。谢谢你,在twig.pm中,我刚刚找到了=item next_elt($optional#elt,$optional#condition)那么“#ELT”可以是第一个参数吗?不,这两个参数都是可选的,因为它们的类型不同(标量与XML::Twig::ELT),所以该方法可以确定哪一个是使用过。试试看!@mirod我改变了问题,期待你的回答!!一旦你删除了元素,那么
next\u elt
返回空的,所以你只删除第一个。我想你需要用
while($elt=$elt->next\u elt($root))替换
foreach my$elt($root->first\u child('ip')->next\u兄弟姐妹)
。在任何情况下,不要对已删除的元素执行
下一步操作
,您可能会得到它的后代(在我的头顶,我不记得该元素在什么时候被有效删除)但是在机器中,除了代理和服务器之外,还有很多其他的标签我没有列出。但是这是一种方式,谢谢你的回答。
<ip>127.0.0.2</ip>   
<option>127.0.0.6</option>
<etc>abc</etc>
 <id>12</id>
use warnings;
use strict;
use XML::Twig;

my $str = '
<machines>
<server>
    127.0.0.1
</server>
<proxy>
    <ip>127.0.0.2</ip>
    <etc>abc</etc>
</proxy>
</machines>
';

my $t = XML::Twig->new(
        twig_handlers => {
            proxy => sub { $_->delete() },
        },
        pretty_print  => 'indented',
);
$t->parse($str);
$t->print($str);
print "\n";

__END__

<machines>
  <server>
    127.0.0.1
</server>
</machines>
#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots => { server => 1 },
                pretty_print => 'indented',
              )
         ->parse( \*DATA)
         ->print;

__DATA__
<machines>
<server>
    127.0.0.1
</server>
<proxy>
    <ip>127.0.0.2</ip>
    <etc>abc</etc>
</proxy>
</machines>