2011-10-27 14 views
2

私は、次のようないくつかのXMLファイルを持っている:PerlのXML :: Twigを使って要素を削除する方法はありますか?

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

と私は、サーバーを維持し、他の人を削除すると、出力は次のようになります。次のように

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

私は、スクリプトを書いた:

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) [email protected]_; 
    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; 

出力を得ました。

server 
#PCDATA 
<machines> 
<server></server> 
<proxy> 
<ip>127.0.0.2</ip> 
<etc>abc</etc> 
</proxy> 
</machines> 

「#PCDATA」がなぜ存在するのか、なぜ期待していないのはなぜうまくいかないのか分かりません。

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

my $tweak_server =sub{ 
my ($twig, $root) [email protected]_; 
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> 

、出力は次のとおりです:次のように私が試した

@mirod

<machines> 
<server> 127.0.0.1 </server> 
<aaa> 
<id>12</id> 
<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> 

と私がしたいだけではなく1、三つの要素を削除するには、次のとおりです。

<ip>127.0.0.2</ip> 
<option>127.0.0.6</option> 
<etc>abc</etc> 

要素下

<id>12</id> 

ご意見はありますか?

+1

あなたが '#のPCDATA'を取得:すべての残りの部分を破棄しながら、これは、XMLおよびサーバー要素(とその内容)のルートを維持する効果があります。実際の要素をループしたい場合は、 '$ elt-> next_elt( '#ELT')'を使います。 – mirod

+0

twig.pmにありがとう、私はちょうどitem = next_elt($ optional_elt、$ optional_condition)を見つけたので、 '#ELT'は最初の引数にすることができますか? – trivial

+1

いいえ、両方の引数はオプションで、その型が異なるため(スカラー対XML :: Twig :: Elt)、メソッドはどちらが使用されているか把握することができます。それを試してみてください! – mirod

答えて

2

以下はproxyの要素を削除します:あなたはsay $tag;を取り除く、その後、server#PCDATAを印刷したくない場合は

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> 

を。

+1

しかし、machinseでは、プロキシとサーバーを除いて、他にもたくさんのタグがあります。これは、私が使用している$ elt($ root-> first_child( 'id') - > next_siblings)です。私は記載されていませんが、それは方法です、あなたにお返事ありがとうございます。 – trivial

2

サーバー要素のみを保持する必要がある場合は、モジュールにtwig_rootsと言うことができます。それは、テキストコンテンツのための「タグ」ですので、

#!/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> 
+1

ええ、それはうまく動作します。ありがとう! – trivial

関連する問題