我有一个包含多个level3元素的xml文件。我想删除除一个这样的元素之外的所有元素。我的xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<level1 id="level1_id">
<level2 id="level2_id">
<level3 id="level3_id1">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
<level3 id="level3_id2">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
<level3 id="level3_id3">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
</level2>
</level1>
我的perl脚本:
my $filename = 'test3.xml';
my $outfile = $filename."_after";
open my $output, '>', $outfile or die "Couldn't open output file\n";
my $twig = new XML::Twig (twig_handlers => { 'level2' => \&edit });
$twig->parsefile($filename);
#$twig->flush;
$twig->print($output);
sub edit {
my ($twig, $element) = @_;
my @elements= $element->children('level3');
print $#elements."\n";
my @elements= @elements[1..$#elements];
print $#elements."\n";
my $count = 0;
foreach (@elements){
$count++;
$_->delete;
}
print $count;
$twig->purge;
}
然而,这只留下了level1元素:
<?xml version="1.0" encoding="UTF-8"?>
<level1 id="level1_id"></level1>
另一方面,当顶级为level2时,我的脚本运行正常。示例xml文件和处理后的结果:
<?xml version="1.0" encoding="UTF-8"?>
<level2 id="level2_id">
<level3 id="level3_id1">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
<level3 id="level3_id2">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
<level3 id="level3_id3">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
</level2>
结果:
<?xml version="1.0" encoding="UTF-8"?>
<level2 id="level2_id">
<level3 id="level3_id1">
<attributes>
<attribute>1</attribute>
<attribute>2</attribute>
</attributes>
</level3>
</level2>
这正是我想要的,即只留下一个level3元素。我究竟做错了什么?是否与我如何定义枝条处理程序有关? 我不想硬编码xml结构,例如我的$ twig =新的XML :: Twig(twig_handlers =&gt; {'level1 / level2'=&gt; \&amp; edit}); 我不知道level2在实际的xml文件中有多深,实际文件的结构可能不一样,所以这部分应该是动态的
答案 0 :(得分:1)
不需要第$twig->purge
行或类似的内容,我也不明白为什么要写它
它将丢弃已解析但未打印到输出的任何内容,这是您刚刚编辑的整个level2
元素
我还建议你写
my $twig = XML::Twig->new(
twig_handlers => { level2 => \&edit },
pretty_print => 'indented',
);
由于您使用的间接对象语法不明确且容易出错。 pretty_print
选项还可以使输出XML更具可读性。
答案 1 :(得分:-1)
我建议除非您特别想要对大文件进行增量解析,否则twig_handers
会不必要地复杂化。如果您希望将XML视为流并修改/丢弃其中的一部分,它实际上通常只是加载整个XML,并且使用它更简单,更清晰,它就是一个强大的工具。
您要做的似乎是删除所有&#39; level3&#39;第一个元素之后。
所以:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new->parsefile('your_xml_file.xml');
my $count;
foreach my $level3 ( $twig->get_xpath('.//level3') ) {
#delete after the first one.
$level3->delete if $count++;
}
#set formatting
$twig -> set_pretty_print('indented_a');
#print to stdout
$twig->print;