我正在尝试将一个xml文件拆分成多个格式正确的片段,并且an ancient PerlMonks solution正在寻找我正在寻找的XML :: Twig的帮助,它会吐入Tee ...至少简单的数据输入。
如果我通过重新组合节点以过滤到父节点来使数据结构稍微复杂化,则第二个文件格式不正确:父节点缺少其开始标记。我很遗憾找不到原因。
SSCCE(与初始示例的区别在于包含<thing_list>
的{{1}}:
<thing>
虽然第一个use XML::Twig;
use IO::Tee;
use feature 'say';
open my $frufile, '>', 'fruit.xml' or die "fruit $!";
open my $vegfile, '>', 'veg.xml' or die "veg $!";
my $tee = IO::Tee->new($frufile, $vegfile);
select $tee;
my $twig=XML::Twig->new(
twig_handlers => {
thing => \&magic,
_default_ => sub {
say STDOUT '_default_ for '.$_->name;
$_[0]->flush($tee); #default filehandle = tee
1;
},
},
pretty_print => 'indented',
empty_tags => 'normal',
);
$twig->parse( *DATA );
sub magic {
my ($thing, $element) = @_;
say STDOUT "magic for ". $element->{att}{type};
for ($element->{att}{type}) {
if (/fruit/) {
$thing->flush($frufile);
} elsif (/vegetable/) {
$thing->flush($vegfile);
} else {
$thing->purge;
}
}
1;
}
__DATA__
<batch>
<header>
<foo>1</foo>
<bar>2</bar>
<baz>3</baz>
</header>
<thing_list>
<thing type="fruit" >Im an apple!</thing>
<thing type="city" >Toronto</thing>
<thing type="vegetable" >Im a carrot!</thing>
<thing type="city" >Melrose</thing>
<thing type="vegetable" >Im a potato!</thing>
<thing type="fruit" >Im a pear!</thing>
<thing type="vegetable" >Im a pickle!</thing>
<thing type="city" >Patna</thing>
<thing type="fruit" >Im a banana!</thing>
<thing type="vegetable" >Im an eggplant!</thing>
<thing type="city" >Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiwhenuakitanatahu</thing>
</thing_list>
<trailer>
<chrzaszcz>A</chrzaszcz>
<zdzblo>B</zdzblo>
</trailer>
</batch>
还可以:
fruit.xml
<batch>
<header>
<foo>1</foo>
<bar>2</bar>
<baz>3</baz>
</header>
<thing_list>
<thing type="fruit">Im an apple!</thing>
<thing type="fruit">Im a pear!</thing>
<thing type="fruit">Im a banana!</thing>
</thing_list>
<trailer>
<chrzaszcz>A</chrzaszcz>
<zdzblo>B</zdzblo>
</trailer>
</batch>
缺少veg.xml
<thing_list>
我还注意到,如果我将<batch>
<header>
<foo>1</foo>
<bar>2</bar>
<baz>3</baz>
</header>
<thing type="vegetable">Im a carrot!</thing>
<thing type="vegetable">Im a potato!</thing>
<thing type="vegetable">Im a pickle!</thing>
<thing type="vegetable">Im an eggplant!</thing>
</thing_list>
<trailer>
<chrzaszcz>A</chrzaszcz>
<zdzblo>B</zdzblo>
</trailer>
</batch>
标记注释到数据中,那么<thing_list>
中的开头标记对应的注释也会丢失,但不会来自veg.xml
。
我似乎明白第一条评论是在处理第一个fruit.xml
时发生的,第二条评论应该在处理文件的其余部分时从<thing>
处理程序处理。但我不明白,_default_
未被评论时是否相同。
WFIW,我在Windows 7机顶盒上使用Strawberry的Perl 5.20.1
答案 0 :(得分:3)
第一次到达$thing->flush($frufile);
时,它会打印尚未刷新的所有内容。如果您之前没有尝试解决此问题,则会输出:
<batch>
<header>
<foo>1</foo>
<bar>2</bar>
<baz>3</baz>
</header>
<thing_list>
<thing type="fruit">Im an apple!</thing>
尝试后,会打印
<thing_list>
<thing type="fruit">Im an apple!</thing>
随后您拨打magic
,<thing_list>
以及之前的所有内容都已打印出来,因此无法再次打印。
不要混合输出手柄!如果要生成两个文件,请处理模板两次。 (并摆脱那个_default_
枝条处理程序。)
也就是说,从twig_handlers
切换到twig_roots
(这对大型文档来说更好)似乎有效:
my $twig = XML::Twig->new(
twig_roots => {
'thing_list/thing' => sub {
my ($t, $element) = @_;
for ($element->{att}{type}) {
if (/fruit/) {
$t->flush($frufile);
} elsif (/vegetable/) {
$t->flush($vegfile);
} else {
$t->purge;
}
}
},
},
twig_print_outside_roots => 1,
pretty_print => 'indented',
empty_tags => 'normal',
);
使用风险自负:)