将XML数据解析为不同的结构

时间:2016-06-06 22:30:08

标签: xml perl xml-simple

我有以下XML文件,我正在尝试解析它

<Books>
  <book name="first" feed="contentfeed" mode="modes" />
  <book name="first" feed="communityfeed" mode="modes" region="1"/>
  <book name="second" feed="contentfeed" mode="" />
  <book name="second" feed="communityfeed" mode="modes" />
  <book name="second" feed="articlefeed" mode="modes" /> 
</Books>

我正在使用Perl版本5.8和XML::Simple。以下是我写的代码

    use XML::Simple;

    my $xs = new XML::Simple( KeyAttr => { book => 'name' } , ForceArray => [ 'book','name' ] );
    my $config = $xs->XMLin( <complete path to xml file> );

以下是结果(使用Data::Dumper显示)

'book' => {
    'first' => {
        'feed'   => 'communityfeed',
        'mode'   => 'modes',
        'region' => '1'
    },
    'second' => {
        'feed' => 'articlefeed',
        'mode' => 'modes'
    },
}

相反,我希望以下面的格式输出

'book' => {
    'first' => {
        'communityfeed' => { mode => 'modes', region => '1' },
        'contentfeed'   => { mode => 'modes' }
    },
    'second' => {
        'communityfeed' => { mode => 'modes' },
        'contentfeed'   => { mode => '' },
        'articlefeed'   => { mode => 'modes' }
    },
}

注释

  1. 无法更改XML文件格式,因为它是当前的生产版本
  2. 首选版本5.8,因为这是父脚本中使用的版本,解析逻辑应该合并到该脚本中
  3. 你以前遇到过这种问题吗?如果是这样,那么如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

XML::Simple是一个令人尴尬和令人沮丧的模块,我很怀疑你是否可以说服它来构建你需要的数据结构。几乎任何其他XML解析器都是向前迈进的

以下是使用XML::Twig的解决方案。您可以查询已解析的XML数据并构建您喜欢的任何数据结构

我只使用Data::Dump来显示结果数据

use strict;
use warnings 'all';

use XML::Twig;

my $config;

{
    my $twig = XML::Twig->new;
    $twig->parsefile('books.xml');

    for my $book ( $twig->findnodes('/Books/book') ) {

        my $atts = $book->atts;
        my ( $name, $feed ) = delete @{$atts}{qw/ name feed /};

        $config->{book}{$name}{$feed} = $atts;
    }
}

use Data::Dump;
dd $config;

输出

{
  book => {
    first  => {
                communityfeed => { mode => "modes", region => 1 },
                contentfeed   => { mode => "modes" },
              },
    second => {
                articlefeed   => { mode => "modes" },
                communityfeed => { mode => "modes" },
                contentfeed   => { mode => "" },
              },
  },
}