XML::Twig
使用set_text
方法时,会出现警告:
set_text($ string) 设置元素的文本:如果元素是PCDATA,只需设置其文本,否则剪切元素的所有子元素并为其创建一个PCDATA子元素,它保存文本。
所以如果我想做一些简单的事情,比如说 - 改变我的XML :: Document中所有文本的大小写:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
'pretty_print' => 'indented_a',
'twig_handlers' => {
'_all_' => sub {
my $newtext = $_->text_only;
$newtext =~ tr/[a-z]/[A-Z]/;
$_->set_text($newtext);
}
}
);
$twig->parse( \*DATA );
$twig->print;
__DATA__
<root>
<some_content>fish
<a_subnode>morefish</a_subnode>
</some_content>
<some_more_content>cabbage</some_more_content>
</root>
这 - 由于set_text
取代儿童 - 被摧毁为:
<root></root>
但如果我只关注一个(底层)节点(例如a_subnode
),那么它可以正常工作。
是否有一种优雅的方法来替换/转换元素中的文本而不破坏它下面的数据结构?我的意思是,我可以测试儿童或类似事物的存在,但......似乎应该有更好的方法来做到这一点。 (可能是另一个图书馆?)
(为了清楚起见 - 这是我在文档中对所有文本进行音译的例子,我的实际用例相当复杂,但仍然是“文本转换”)。
我可能正在考虑使用节点剪切/粘贴方法(剪切所有子节点,替换文本,粘贴所有子节点),但这似乎是一种低效的方法。答案 0 :(得分:4)
不要在_all_
上使用处理程序,而是只在文本元素#TEXT
上使用,并将text_only
更改为text
。它应该工作。
更新:或者在创建树枝时使用char_handler
选项:char_handler => sub { uc shift },
而不是处理程序。
答案 1 :(得分:2)
我目前的做法是:
cut
所有孩子。paste
所有孩子。 这似乎效率低下,但似乎确实有效:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
use Data::Dumper;
sub replace_text {
my ( $twig, $element ) = @_;
my $newtext = $element->text_only;
my @children;
foreach my $child ( $element->children ) {
if ( not $child->tag eq "#PCDATA" ) {
push( @children, $child->cut );
}
}
$newtext =~ tr/[a-z]/[A-Z]/;
$element->set_text($newtext);
$_->paste( 'last_child', $element ) for @children;
}
my $twig =
XML::Twig->new( 'twig_handlers' => { '_all_' => \&replace_text, } );
$twig->parse( \*DATA );
print "Result:\n";
$twig->print;
__DATA__
<root>
<some_content>fish
<a_subnode>morefish</a_subnode>
</some_content>
<some_more_content>cabbage</some_more_content>
</root>
这会将我的输出转换为:
<root><some_content>FISH
<a_subnode>MOREFISH</a_subnode></some_content><some_more_content>CABBAGE</some_more_content></root>
因此,虽然它确实对节点进行了变换,但由于某种原因,它也会破坏输出格式。
重新解析:
XML::Twig -> new ( 'pretty_print' => 'indented_a' ) -> parse ( $twig -> sprint ) -> print;
似乎要做的伎俩。 (虽然重新格式化的双重解析似乎更不优雅)
<root>
<some_content>FISH
<a_subnode>MOREFISH</a_subnode></some_content>
<some_more_content>CABBAGE</some_more_content>
</root>