によって返されるXML要素の順序の設定に関して、さまざまな場所ですでにいくつかの回答を見てきましたXMLout
。しかし、私はそれらの答え/例を使用して問題を解決することはできません。
いくつかのXMLデータを出力する必要があるスクリプトがあり、特定の要素を特定の順序で出力する必要があります。ハッシュはかなり複雑で、オブジェクトをオーバーライドsorted_keys
しても結果を得ることができませんでした。XML::Simple
まあ、私はしましたが、私が望んでいた方法ではありませんでした。
サンプルコードは以下にあり、問題の詳細はコードの下にあります。
#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
package MyXMLSimple;
use base 'XML::Simple';
sub sorted_keys
{
my ($self, $name, $hashref) = @_;
# ...
return $self->SUPER::sorted_keys($name, $hashref);
}
package main;
my $xmlParser = MyXMLSimple->new;
my $items = {
'status' => 'OK',
'fields' => {
'i1' => {
'header' => 'Header 1',
'max_size' => '3'
},
'i2' => {
'header' => 'Header 2',
'max_size' => '8'
}
},
'item_list' => {
'GGG' => {
'index' => '3',
'i' => 3,
'points' => {
'p5' => {
'data' => '10',
}
},
},
'AAA' => {
'index' => '1',
'i' => 2,
'points' => {
'p7' => {
'data' => '22',
}
},
},
'ZZZ' => {
'index' => '2',
'i' => 1,
'points' => {
'p6' => {
'data' => '15',
}
},
}
}
};
my $xml = $xmlParser->XMLout($items);
print "$xml";
したがって、このスクリプトの出力は次のようになります。
<opt status="OK">
<fields name="i1" header="Header 1" max_size="3" />
<fields name="i2" header="Header 2" max_size="8" />
<item_list name="AAA" i="2" index="1">
<points name="p7" data="22" />
</item_list>
<item_list name="GGG" i="3" index="3">
<points name="p5" data="10" />
</item_list>
<item_list name="ZZZ" i="1" index="2">
<points name="p6" data="15" />
</item_list>
</opt>
item_list
name
属性でソートすることにより、要素が出力され、出力順序はアルファベット順になります。出力順序はAAA、GGG、ZZZです。
ただし、必要なのは、要素で(数値的には、最低から最高に)ソートされている間に出力を取得することi
です。そのため、出力はZZZ、AAA、GGGの順になります。
私はハッシュの順序を制御できないので(Tie::...
モジュールを使用せずに)、そのようにすることはできません。を使用するNoSort => 1
と、出力は特に何もソートされないため、ランダムな出力が得られます。
sorted_keys
したがって、サブルーチンをオーバーライドすることで、これを希望どおりに分類する方法が必要であると確信しています。sorted_keys
ただし、のインスタンスごとにが呼び出されるため、希望する結果を得ることができませんでしitem_list
た。sorted_keys
要素に対してが呼び出されると、ハッシュ参照全体にアクセスできるようになりますが、モジュールopt
に依存せずに出力の順序を保証する手段はありません。Tie::
Tie::IxHash
これで、モジュールを使用し、サブハッシュをオーバーライドsorted_keys
して(再)作成し、item_list
元のハッシュから新しい(順序付けられた)ハッシュに値を再挿入し、元のハッシュのサブハッシュを削除することで、これを希望どおりに機能させることができました。新しい順序付けされたハッシュで置き換えます。
このようなもの:
sub sorted_keys
{
my ($self, $name, $hashref) = @_;
if ($name eq "opt")
{
my $clist = { };
tie %{$clist}, "Tie::IxHash";
my @sorted_keys = sort { $hashref->{item_list}->{$a}->{i} <=> $hashref->{item_list}->{$b}->{i} } keys %{$hashref->{item_list}};
foreach my $sorted_key (@sorted_keys)
{
$clist->{$sorted_key} = $hashref->{item_list}->{$sorted_key};
}
delete $hashref->{item_list};
$hashref->{item_list} = $clist;
}
return $self->SUPER::sorted_keys($name, $hashref);
}
Tie::IxHash
これは機能しますが(これまでのところ確実に機能しているようです)、モジュールを使用せずに、ハッシュの再作成/並べ替えをすべて行わずに、内部から特定のデータを何らかの方法で並べ替え/返すことによってのみ、これを実現する方法が必要だと思いますsorted_keys
。
私はそれを理解することができず、どのように機能するのか本当にわかりませんsorted_keys
(特に入力データの異なる/複雑なセットで異なる結果が得られる場合;)、しかしこれを知っている誰かがそこにいることを願っています。
XML/Simple.pm
つまり、サブルーチンの最後の戻り行で自分自身を変更してソート順を変更しようとしましたsorted_keys
が、それでも英数字でソートされた出力が得られていました。私はそれをどのように変更するのか理解できないので、それがソートされないのではないかと心配していname
ますi
。