json - Perl XML2JSON : How to preserve XML element order?

标签 json perl xml-parsing

我有一个 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/

相关文章:

javascript - Ember JSON 加载问题 - 加载路线时出错 : undefined

xml - xpath:修剪节点中的空格

java - 解析编码为 UTF-8 和 UTF-16 的 XML 文件时出错

powershell - 带#sign 的成员(member)

perl - 确定日期范围内的日期的好方法是什么?

javascript - 将带有 Perl 变量的内联 javascript 更改为函数

java - 如何解决 org.json.JSONException : No value for index?

json - Angularjs 无法在 Bootstrap 选择器中工作

php - 使用 PHP 从 Mysql 生成 JSON

Perl DateTime 纳秒始终为 0