我试图从嵌套树结构的xml字符串生成数组数组。
但是当我生成引用变量$output
时,B1内的元素很少丢失(C1,D1,D2)。使用$test
cpan模块生成XML::LibXML::Reader
。
use strict;
use warnings;
use Data::Dumper;
use v5.10;
my $test = "start, /root/class1, A1
start, /root/class1/class2, B1
start, /root/class1/class2/class3, C1
start, /root/class1/class2/class3/class4, D1
end, /root/class1/class2/class3/class4, D1
start, /root/class1/class2/class3/class4, D2
end, /root/class1/class2/class3/class4, D2
end, /root/class1/class2/class3, C1
end, /root/class1/class2, B1
start, /root/class1/class2, B2
start, /root/class1/class2/class3, C2
start, /root/class1/class2/class3/class4, D1
end, /root/class1/class2/class3/class4, D1
start, /root/class1/class2/class3/class4, D2
end, /root/class1/class2/class3/class4, D2
start, /root/class1/class2/class3/class4, D3
end, /root/class1/class2/class3/class4, D3
end, /root/class1/class2/class3, C2
end, /root/class1/class2, B2
end, /root/class1, A1";
our $x = 0;
my $output = generator($test);
say "Output: ". Dumper $output;
sub generator{
my ($classes, $x, $subout) = (shift, shift, '');
my @out;
$x += 1;
while($classes =~ /(start(.+?class$x\,\ (\w+))\n(.*?)end\2)/gsi){
my ($data1, $value, $rest) = ($1, $3, $4);
$subout = generator($rest,$x) if $rest;
push @out, $value;
}
push @out, $subout if $subout;
# say "X: $x ". Dumper \@out;
return \@out;
}
输出是:
Output: $VAR1 = [
'A1',
[
'B1',
'B2',
[
'C2',
[
'D1',
'D2',
'D3'
]
]
]
];
我错过了什么吗?
创建数据结构的任何其他方法也很有用。
的xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<class1 name="A1">
<class2 name="B1">
<class3 name="C1">
<class4 name="D1">
</class4>
<class4 name="D2">
</class4>
</class3>
</class2>
<class2 name="B2">
<class3 name="C2">
<class4 name="D1">
</class4>
<class4 name="D2">
</class4>
<class4 name="D3">
</class4>
</class3>
</class2>
</class1>
</root>
答案 0 :(得分:1)
此代码将按您的要求执行。但这基本上是可怕的XML::Simple
试图做的事情。它丢失了信息,使用通用XML文档是不可能的
use strict;
use warnings 'all';
use XML::LibXML::Reader;
use constant XML_FILE => 'root.xml';
my %data;
my @stack = (\%data);
my $reader = XML::LibXML::Reader->new(location => XML_FILE);
while ( $reader->read ) {
my $type = $reader->nodeType;
if ( $type == XML_READER_TYPE_ELEMENT ) {
next unless my $name = $reader->getAttribute('name');
push @stack, ($stack[-1]{$name} = {});
}
elsif ( $type == XML_READER_TYPE_END_ELEMENT ) {
pop @stack if $reader->getAttribute('name');
}
}
use Data::Dump;
dd \%data;
{
A1 => {
B1 => { C1 => { D1 => {}, D2 => {} } },
B2 => { C2 => { D1 => {}, D2 => {}, D3 => {} } },
},
}