了解 XML::Twig"s wrap_in

Understanding XML::Twig"s 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>

换句话说,属性被添加到初始 'root',并且没有发生换行。但我想要实现的是:

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

有趣的是,当我调用 $_->root 时,我看到了原始根($twig 的根),所以我猜根是作为对象的一部分隐式继承的。我认为这就是我最困惑的地方:特殊 $_root 实际上是 $twig 的根,而不是子树本身的根。

将输入的 twig 后代变成具有包装结构的 twig 的正确方法是什么?

通常在尝试创建这样的子文档时,我只是创建一个新的,然后插入一个复制的节点。

像这样:

#!/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 确实提供了 document 根目录。这是一个特例 XML 元素,root 将您指向顶层,因为它是节点上下文的一部分。

wrap_in 是修改 node 的特例,但它不适用于根节点,因为它们是特例。所以你可以(使用我上面的例子):

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::Twig

cutpaste 方法将其分开