私は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
に設定します。name
capacity
set_tag
scalar $smart->data()
リストコンテキストで呼び出されると、data
メソッドは2番目の値(XMLがUnicodeでエンコードされているかどうかを示すブールフラグ)を返すため、XMLはを使用して出力されることに注意してください。これは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>