J'ai déjà vu quelques réponses sur différents endroits, en ce qui concerne la définition de l'ordre des éléments XML renvoyés par XMLout
. Cependant, je ne suis pas capable de résoudre un problème en utilisant ces réponses/exemples.XML :: Ordre simple des éléments de sortie du hachage complexe
J'ai un script qui doit générer des données XML, et certains éléments doivent être imprimés dans un certain ordre. Hash est assez complexe, et je n'ai pas pu obtenir de résultats en remplaçant sorted_keys
dans l'objet XML::Simple
. Eh bien, je l'ai fait, mais pas de la façon dont je le voulais.
Exemple de code ci-dessous, les détails sur le problème sont en dessous du code.
#!/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";
Ainsi, la sortie de ce script sera la suivante:
<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
éléments sont imprimés, et l'ordre de sortie est par ordre alphabétique, par le tri sur name
attribut. L'ordre de sortie est AAA, GGG, ZZZ.
Cependant, ce dont j'ai besoin est d'avoir la sortie tout en étant triée (numériquement, du plus bas au plus haut) sur l'élément i
. Donc, cette sortie sera dans l'ordre ZZZ, AAA, GGG.
Je n'ai aucun contrôle sur l'ordre dans le hachage (pas sans utiliser le module Tie::...
), donc je ne peux pas le faire de cette façon. Si j'utilise NoSort => 1
, la sortie ne sera pas triée par quelque chose en particulier, donc je finirai par avoir une sortie aléatoire. Donc, je suis assez sûr qu'il doit y avoir un moyen de régler cela comme je le veux en remplaçant le sous-programme sorted_keys
. Cependant, je n'ai pas pu obtenir les résultats voulus, car sorted_keys
est invoqué pour chaque instance de item_list
. Lorsque sorted_keys
est invoqué pour l'élément opt
, alors j'ai simplement accès à la référence de hachage entier, mais encore une fois aucun moyen de garantir l'ordre de sortie sans compter sur le module Tie::
.
Maintenant, j'ai réussi à obtenir que cela fonctionne comme je le veux, en utilisant le module Tie::IxHash
, puis remplaçant sorted_keys
et (re) créer un Subhash item_list
, en réinsérant les valeurs de hachage d'origine dans la nouvelle (ordonnée) un, puis supprimer subhash dans le hash d'origine et le remplacer par un nouveau hash ordonné.
Quelque chose comme ceci:
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);
}
Bien que cela fonctionne (et donc semble bien fonctionner de manière fiable), je ne crois qu'il doit y avoir un moyen d'y parvenir sans utiliser le module Tie::IxHash
et de faire tout ce que les loisirs de hachage/réorganisation, et seulement en triant/retournant certaines données de sorted_keys
. Je ne peux pas comprendre, et je ne comprends pas vraiment comment sorted_keys
est censé fonctionner (surtout quand vous obtenez des résultats différents avec des ensembles différents/complexes de données d'entrée;), mais j'espère qu'il y a quelqu'un là-bas qui sait cela. Je veux dire, j'ai essayé de modifier XML/Simple.pm
lui-même et de changer l'ordre de tri dans la dernière ligne de retour du sous-programme sorted_keys
, mais je recevais toujours la sortie triée alphanumérique. J'ai peur de ne pas savoir comment je le modifierais donc il ne triera pas sur name
mais sur i
.
Toute aide est très appréciée :)
TLDR, bit +1 pour la minutie de (à mon humble avis, futile) effort - aurait fait +2 si je pouvais :) – DVK