6

によって返される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_listname属性でソートすることにより、要素が出力され、出力順序はアルファベット順になります。出力順序は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

4

2 に答える 2

2

この時点で、あなたは XML::Simple から脱却したと思います。要素内の子の順序が気になる場合は、より XML に似たモジュールを使用する必要があります。必要な XML 作成のスタイル (おそらくXML::TreeBuilder ) については、new_from_lolメソッドを参照してください。または XML::LibXML、XML::Twig、XML::Writer...

また、過去に Tie::IxHash と XML::Simple を混ぜてみましたが、うまくいきませんでした。あなたは実際にかなりここまで来ました。しかし、私はこの方法が狂気であると信じています

于 2010-11-12T14:41:12.127 に答える