4

我正在使用XML::Simple并且希望将此数据转换为 XML:

@rooms = (
   {
      id => 4,
      is_key => 0,
      name => B507,
      capacity => 35
   },
   {
      id => 5,
      is_key => 1,
      name => B502,
      capacity => 24
   }
);

我想输出这个:

<rooms>
   <room id=4 is_key=0>
      <name>B507</name>
      <capacity>35</capacity>
   </room>
   <room id=5 is_key=1>
      <name>B502</name>
      <capacity>24</capacity>
   </room>
</rooms>

我看不出有办法做到这一点XML::Simple::XMLout。我错过了什么吗?

4

3 回答 3

6

我发现XML::Simple使用起来不直观且非常尴尬。很容易最终只是向它抛出随机选项以尝试使其正常工作。

但是,如果您坚持使用它,则有一种方法。首先,该ForceArray选项非常有用,正如文档所述,

查看“ForceArray”,因为您几乎肯定会想要打开它

因此,您需要调整数据,使其看起来ForceArray在解析原始 XML 时生效。这只涉及将所有应该是元素内容而不是属性值的数据放入匿名数组中。

这段代码可以满足您的需要。该KeepRoot选项只是告诉XMLout顶级哈希是根元素,它不必将整个东西包装在另一个元素中。

use strict;
use warnings;

use XML::Simple;

my @rooms = (
   {
      id => 4,
      is_key => 0,
      name => 'B507',
      capacity => 35
   },
   {
      id => 5,
      is_key => 1,
      name => 'B502',
      capacity => 24
   }
);

for my $room (@rooms) {
  for my $k (keys %$room) {
      $room->{$k} = [ $room->{$k} ] unless grep $k eq $_, qw/ is_key id /;
  }
}

my $xml = {rooms => {room => \@rooms} };

print XMLout($xml, KeepRoot => 1);

输出

<rooms>
  <room id="4" is_key="0">
    <name>B507</name>
    <capacity>35</capacity>
  </room>
  <room id="5" is_key="1">
    <name>B502</name>
    <capacity>24</capacity>
  </room>
</rooms>

更新

您可能更喜欢使用 的解决方案XML::Smart,它允许您指定哪些节点是元素,哪些是标签。这使您可以保持原始数据@rooms不变。

该程序接受对XML::Simple解决方案的类似哈希引用,它们循环遍历所有/rooms/room元素,将所有节点namecapacity子节点设置为使用set_tag.

请注意,使用 XML 输出是scalar $smart->data()因为在列表上下文中调用该data方法时将返回第二个值:指示 XML 是否为 Unicode 编码的布尔标志。这似乎没有记录在 POD 中。

$smart->set_order如果您不关心属性和元素在 XML 中出现的顺序,则可以省略调用。

use strict;
use warnings;

use XML::Smart;

my @rooms = (
   {
      id => 4,
      is_key => 0,
      name => 'B507',
      capacity => 35
   },
   {
      id => 5,
      is_key => 1,
      name => 'B502',
      capacity => 24
   }
);

my $smart = XML::Smart->new;
$smart->{rooms} = { room => \@rooms };

for my $room (@{$smart->{rooms}{room}}) {
  $room->set_order(qw/ id is_key name capacity /);
  $room->{name}->set_tag;
  $room->{capacity}->set_tag;
}

print scalar $smart->data(noheader => 1, nometagen => 1);

输出

<rooms>
  <room id="4" is_key="0">
    <name>B507</name>
    <capacity>35</capacity>
  </room>
  <room id="5" is_key="1">
    <name>B502</name>
    <capacity>24</capacity>
  </room>
</rooms>
于 2012-07-20T16:00:46.093 回答
2

哈希值 arrayrefs 成为 XML 元素内容,简单的哈希值成为 XML 属性值。

use strictures;
use XML::Simple qw(:strict);

print XMLout(
    {
        room => [
            {
                id       => 4,
                is_key   => 0,
                name     => ['B507'],
                capacity => [35],
            },
            {
                id       => 5,
                is_key   => 1,
                name     => ['B502'],
                capacity => [24],
            }
        ]
    },
    KeyAttr  => [],
    RootName => 'rooms'
);

<rooms>
  <room id="4" is_key="0">
    <capacity>35</capacity>
    <name>B507</name>
  </room>
  <room id="5" is_key="1">
    <capacity>24</capacity>
    <name>B502</name>
  </room>
</rooms>
于 2012-07-20T15:53:09.753 回答
0

Daxim 的回答已经是正确的。既然我已经打出来了,我还是会发布这个。这是一段代码,可以将您的数据结构转换为您需要的数据结构(Daxim 已经指出)。

my $stuff = { 
  'room' =>  [ 
    map { { 
      'id' => $_->{'id'}, 
      'is_key' => $_->{'is_key'}, 
      'name' => [ $_->{'name'} ], 
      'capacity' => [  $_->{'capacity'} ] 
    } } @rooms 
  ]
};

print XMLout($stuff, RootName=> 'rooms', );
于 2012-07-20T16:01:18.610 回答