2017-04-06 10 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

(안 내 DV). 전체 예제 XML 입력이 현재 코드가하는 일을 이해하는데 많은 도움이 될 것이라고 제안 할 수 있습니까? – Sobrique

+0

[* 좋은 질문이 있습니까?] (http://stackoverflow.com/questions/how-to-ask) 및 [* 최소, 완전하고 검증 가능한 예제를 만드는 방법 *] (http://stackoverflow.com/help/mcve). 귀하의 상황을 제대로 이해하기에 충분한 정보가있는 곳이라면 어디에서나 많은 질문을 던지 셨을 것입니다. 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; 
} 

당신은 XML::Twigcutpaste 방법을 사용하여 이것을 분리 할 수 ​​있습니다,