如何解决Perl反序列化XML
| 我有这样的XML文件(某些应用程序的输出):<data>
<call function=\"get_user_data\">
<output>
<integer name=\"my_id\" value=\"-31\" />
<string name=\"login\" value=\"root\" />
<integer name=\"ip_list\" value=\"2\" />
<array name=\"i\">
<item>
<ip_address name=\"user_ip\" value=\"0.0.0.0\" />
<ip_address name=\"user_mask\" value=\"0.0.0.0\"/>
</item>
<item>
<ip_address name=\"user_ip\" value=\"94.230.160.230\" />
<ip_address name=\"user_mask\" value=\"255.255.255.0\"/>
</item>
</array>
<integer name=\"modules\" value=\"2\" />
<array name=\"i\">
<item>
<string name=\"module_name\" value=\"core\" />
</item>
<item>
<string name=\"module_name\" value=\"devices\" />
</item>
</array>
<integer name=\"addition_modules\" value=\"0\"/>
<array name=\"i\"/>
</output>
</call>
</data>
我需要为这个perl结构解析它:
$data = {
my_id => -31,login => \"root\",ip_list => [
{
user_ip => \"0.0.0.0\",user_mask => \"0.0.0.0\"
},{
user_ip => \"94.230.160.230\",user_mask => \"255.255.255.0\"
}
],modules => [
{
module_name => \"core\"
},{
module_name => \"devices\"
}
],addition_modules => []
}
请帮助我,做到这一点!
解决方法
这是一种糟糕的XML格式。这是多余的:为什么要给出每个数组的元素数量,它在那里,并且层次结构定义不正确:数组的名称(以及(如果必须的话,它的元素数量))应该是数组的属性,而不是同一级别之前的元素。
无论如何...您的格式是如此具体,以至于我怀疑您可以在此处使用常规的XML :: Simple,所以我退出了XML :: Twig,我认为这样做可以:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
use Test::More tests => 1;
my $expected= {
my_id => -31,login => \"root\",ip_list => [
{ user_ip => \"0.0.0.0\",user_mask => \"0.0.0.0\"
},{ user_ip => \"94.230.160.230\",user_mask => \"255.255.255.0\"
}
],modules => [
{ module_name => \"core\" },{ module_name => \"devices\" }
],addition_modules => []
};
my $data={};
my $t=XML::Twig->new( twig_handlers => { \'integer[@name=\"my_id\"]\' => sub { add_field( $data,$_)},\'string[@name=\"login\"]\' => sub { add_field( $data,array => sub { array( $data,@_); },},)
->parse( \\*DATA); # replace with parsefile( \'file.xml\') to parse a file
is_deeply( $data,$expected,\'one test to rule them all\');
sub array
{ my( $data,$t,$array)= @_;
my $name= $array->prev_sibling( \'integer\')->att( \'name\');
$data->{$name}=[];
foreach my $item ($array->children( \'item\'))
{ my $item_data={};
foreach my $child ($item->children)
{ add_field( $item_data,$child); }
push @{$data->{$name}},$item_data;
}
}
# get a name/value pair of attributes and add it to a hash,which
# could be the overall $data or an element in an array
sub add_field
{ my( $data,$elt)= @_;
$data->{$elt->att( \'name\')}= $elt->att( \'value\');
}
__DATA__
<data>
<call function=\"get_user_data\">
<output>
<integer name=\"my_id\" value=\"-31\" />
<string name=\"login\" value=\"root\" />
<integer name=\"ip_list\" value=\"2\" />
<array name=\"i\">
<item>
<ip_address name=\"user_ip\" value=\"0.0.0.0\" />
<ip_address name=\"user_mask\" value=\"0.0.0.0\"/>
</item>
<item>
<ip_address name=\"user_ip\" value=\"94.230.160.230\" />
<ip_address name=\"user_mask\" value=\"255.255.255.0\"/>
</item>
</array>
<integer name=\"modules\" value=\"2\" />
<array name=\"i\">
<item>
<string name=\"module_name\" value=\"core\" />
</item>
<item>
<string name=\"module_name\" value=\"devices\" />
</item>
</array>
<integer name=\"addition_modules\" value=\"0\"/>
<array name=\"i\"/>
</output>
</call>
</data>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。