2017-04-06 5 views
0

私は小枝の子孫をループしています。このループでは、後で出力する新しい小枝を作成したいと考えています。XML :: Twigの理解wrap_in

# $twig already exists. 
my @descendants = $twig->root->first_child->descendants_or_self; 
foreach (@descendants) { 
    $_->root->wrap_in('tree'); 

    my $treetop = XML::Twig->new()->set_root($_); 

    $treetop->root->wrap_in('trees', treebank => { 
    id => 'someid' 
    }); 

    if (exists $hash{'somekey'}) { 
    $treetop->root->set_att(c => 'd'); 
    } 
} 

ループ内$_->sprintの例:

<node begin="0"> 
    <node a="b"></node> 
</node> 

しかし、この結果(IF-句最後後)である($treetop->sprint):

<node begin="0" c="d"> 
    <node a="b"></node> 
</node> 

つまり、属性は最初の「ルート」に追加され、折り返しは発生しません。しかし、私が達成しようとしていることである:

<treebank id="someid" c="d"> 
    <trees> 
    <tree> 
     <node begin="0"> 
     <node a="b"></node> 
     </node> 
    </tree> 
    </trees> 
</treebank> 

興味深いことに、私は$_->rootを呼び出すときに、私は元のルート($twigのルート)を見ることが、私は根が暗黙的にオブジェクトの一部として継承されていると思います。私はそれが私の混乱の大部分があると思う:$_rootは実際には$twigのルートであり、サブツリー自体のルートではない。

入力枝の子孫を取る正しい方法は、それを折り返し構造の小枝に変えますか?

+0

XML::Twigcutpasteメソッドを使用してこれを分離することができます(ない私のDV)。あなたのコードが現在何をしているかを理解するのに大いに役立ついくつかの完全なXML入力例を提案できますか? – Sobrique

+0

と[*最小限で完全で検証可能なサンプルを作成するにはどうすればいいですか? *](http://stackoverflow.com/help/mcve)。私はあなたの状況を正しく理解するためにも十分な情報の近くにあなたの多くの質問のどれもを覚えていません。あなたのコードとデータを単純にコピーして実行できるという理想は絶対に思いません。 – Borodin

+0

'descendants_or_self'は単にオブジェクト要素とそのすべての子孫を返しますか?あなたは ' ...'のようなものを生産、 'tree'要素で文書全体のルートノードを包む、それらのそれぞれのために、これらの要素のすべてをループしています。私はそれがあなたの意図ではないと確信しています。 – Borodin

答えて

1

通常、そのようなサブ文書を作成しようとすると、新しいサブ文書を作成し、コピーしたノードを挿入するだけです。

このような何か:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use XML::Twig; 

my $twig = XML::Twig->new->parse(\*DATA); 

foreach my $node ($twig->get_xpath('./node')) { 

    my $new_root = 
    XML::Twig::Elt->new('treebank', { id => "someid", c => "d" }); 
    my $new_doc = XML::Twig->new->set_root($new_root); 
    $new_doc->set_xml_version('1.0'); 
    my $tree = $new_doc->root->insert_new_elt('trees')->insert_new_elt('tree'); 

    $node->cut; 
    $node->paste('last_child', $tree); 

    $new_doc->set_pretty_print('indented'); 
    $new_doc->print; 
} 

__DATA__ 
<xml> 
<node begin="0" c="d"> 
    <node a="b"></node> 
</node> 
</xml> 

しかし、あなたの特定のポイントに対処する - はい、root文書ルートを与えています。特別な場合のXML要素です。rootは、ノードのコンテキストの一部であるため、最上位レベルを指しています。

wrap_inは、ノードを変更する特別なケースですが、特別なケースであるためルートノードでは機能しません。だから、(上記の私の例を使用して)ことができます:

foreach my $node ($twig->get_xpath('./node')) { 
    my $new_doc = XML::Twig->new; 
    $new_doc->set_xml_version('1.0'); 

    $node->cut; 
    $new_doc->set_root ($node); 
    $node->wrap_in('trees', treebank => { id => 'someid' }); 
    $new_doc->set_pretty_print('indented'); 
    $new_doc->print; 
} 

あなたは

関連する問題