我有一个 XML 格式的配置文件。我需要解析 XML 并将其转换为 JSON。我可以使用 perl 的 XML2JSON 模块对其进行转换。但问题是,它没有维护 XML 元素的顺序。我严格需要按顺序排列元素,否则我无法配置
我的 XML 文件是这样的。我必须配置一个 IP 地址并将该 IP 设置为特定路由的网关。
<Config>
<ip>
<address>1.1.1.1</address>
<netmask>255.255.255.0</netmask>
</ip>
<route>
<network>20.20.20.0</network>
<netmask>55.255.255.0</netmask>
<gateway>1.1.1.1</gateway>
</route>
</Config>
这是我要转换为 JSON 的 Perl 代码
my $file = 'config.xml';
use Data::Dumper;
open my $fh, '<',$file or die;
$/ = undef;
my $data = <$fh>;
my $XML = $data;
my $XML2JSON = XML::XML2JSON->new();
my $Obj = $XML2JSON->xml2obj($XML);
print Dumper($Obj);
我得到的输出是,
$VAR1 = {'Config' => {'route' => {'netmask' => {'$t' => '55.255.255.0'},'gateway' => {'$t' => '1.1.1.1'},'network' => {'$t' => '20.20.20.0'}},'ip' => {'netmask' => {'$t' => '255.255.255.0'},'address' => {'$t' => '1.1.1.1'}}},'@encoding' => 'UTF-8','@version' => '1.0'};
我有一个读取 json 对象并配置的脚本。 但它失败了,因为它首先尝试将网关 IP 地址设置为尚未配置 IP 地址的路由,然后添加然后添加 IP 地址。
我严格希望关键ip排在第一位,然后是路由,以便正确配置而不会出现错误。像这样,我有许多依赖项,其中键的顺序是必须的。
有什么办法可以解决这个问题吗?我尝试了几乎所有 XML 解析模块,例如 XML::Simple、Twig::XML、XML::Parser。但没有任何帮助..
最佳答案
这是我编写的一个程序,它使用 XML::Parser
解析一些 XML 数据并以相同的顺序生成等效的 JSON。它忽略任何属性、处理指令等,并要求每个 XML 元素必须包含子元素列表或文本节点。混合文本和元素将不起作用,并且不会被检查,除非程序会在尝试取消引用字符串时终止
它旨在成为一个框架,供您根据需要进行增强,但由于它与您在问题中显示的 XML 数据一起工作得很好
use strict;
use warnings 'all';
use XML::Parser;
my $parser = XML::Parser->new(Handlers => {
Start => \&start_tag,
End => \&end_tag,
Char => \&text,
});
my $struct;
my @stack;
$parser->parsefile('config.xml');
print_json($struct->[1]);
sub start_tag {
my $expat = shift;
my ($tag, %attr) = @_;
my $elem = [ $tag => [] ];
if ( $struct ) {
my $content = $stack[-1][1];
push @{ $content }, $elem;
}
else {
$struct = $elem;
}
push @stack, $elem;
}
sub end_tag {
my $expat = shift;
my ($elem) = @_;
die "$elem <=> $stack[-1][0]" unless $stack[-1][0] eq $elem;
for my $content ( $stack[-1][1] ) {
$content = "@$content" unless grep ref, @$content;
}
pop @stack;
}
sub text {
my $expat = shift;
my ($string) = @_;
return unless $string =~ /\S/;
$string =~ s/\A\s+//;
$string =~ s/\s+\z//;
push @{ $stack[-1][1] }, $string;
}
sub print_json {
my ($data, $indent, $comma) = (@_, 0, '');
print "{\n";
for my $i ( 0 .. $#$data ) {
# Note that $data, $indent and $comma are overridden here
# to reflect the inner context
#
my $elem = $data->[$i];
my $comma = $i < $#$data ? ',' : '';
my ($tag, $data) = @$elem;
my $indent = $indent + 1;
printf qq{%s"%s" : }, ' ' x $indent, $tag;
if ( ref $data ) {
print_json($data, $indent, $comma);
}
else {
printf qq{"%s"%s\n}, $data, $comma;
}
}
# $indent and $comma (and $data) are restored here
#
printf "%s}%s\n", ' ' x $indent, $comma;
}
输出
{
"ip" : {
"address" : "1.1.1.1",
"netmask" : "255.255.255.0"
},
"route" : {
"network" : "20.20.20.0",
"netmask" : "55.255.255.0",
"gateway" : "1.1.1.1"
}
}
关于json - Perl XML2JSON : How to preserve XML element order?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37256569/