Ya he visto algunas respuestas en varios lugares, con respecto a establecer el orden de los elementos XML que se devuelven por XMLout
. Sin embargo, no puedo resolver un problema usando esas respuestas/ejemplos.XML :: Orden de elemento de salida simple de hash complejo
Tengo un script que necesita generar algunos datos XML, y ciertos elementos deben imprimirse en cierto orden. Hash es bastante complejo y no pude lograr ningún resultado anulando sorted_keys
en el objeto XML::Simple
. Bueno, lo hice, pero no de la manera que quería.
El código de ejemplo está debajo, los detalles sobre el problema están debajo del código.
#!/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";
Por lo tanto, la salida de este script será la siguiente:
<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
elementos se imprimen, y el orden de salida es por orden alfabético, por clasificación en name
atributo. El orden de salida es AAA, GGG, ZZZ.
Sin embargo, lo que necesitaría es tener la salida mientras se ordena (numéricamente, de menor a mayor) en el elemento i
. Entonces esa salida estará en orden ZZZ, AAA, GGG.
No tengo control sobre el orden en el hash (no sin usar el módulo Tie::...
), así que no puedo hacerlo de esa manera. Si uso NoSort => 1
, la salida no será ordenada por nada en particular, así que terminaré obteniendo resultados aleatorios.
Por lo tanto, estoy bastante seguro de que debe haber una manera de resolver esto de la manera que yo lo deseo al anular la subrutina sorted_keys
. Sin embargo, no pude obtener los resultados que quería, porque sorted_keys
se invoca para cada instancia de item_list
. Cuando se invoca sorted_keys
para el elemento opt
, entonces simplemente tengo acceso a la referencia completa de hash, pero de nuevo no hay forma de garantizar el pedido de salida sin confiar en el módulo Tie::
.
Ahora, he conseguido que esto funcione como yo quiero, mediante el uso de Tie::IxHash
módulo, a continuación, anulando sorted_keys
y (re) creación de un subhash item_list
, volviendo a insertar los valores de hash de original en la nueva (ordenada), entonces eliminando subhash en hash original y sustituyéndolo por hash ordenado nuevo.
Algo como esto:
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);
}
Aunque esto funciona (y hasta ahora parece funcionar de forma fiable), yo creo que tiene que haber una manera de lograr esto sin usar Tie::IxHash
módulo y hacer todo lo que la recreación de hash/reordenando, y solo de alguna manera clasificando/devolviendo cierta información desde sorted_keys
.
No puedo entenderlo, y realmente no entiendo cómo se supone que sorted_keys
funciona (especialmente cuando se obtienen resultados diferentes con conjuntos de datos de entrada diferentes o complejos;), pero espero que haya alguien por ahí que sabe esto.
Es decir, han intentado modificar XML/Simple.pm
sí mismo y cambiar el orden de clasificación en la última línea de retorno de subrutina sorted_keys
, pero todavía era conseguir de forma alfanumérica ordenados de salida. Me temo que no puedo entender cómo lo modificaría para que no se ordene en name
, sino en i
.
Cualquier ayuda es muy apreciada :)
TLDR, bit +1 para la minuciosidad del esfuerzo (en mi humilde opinión), habría hecho +2 si pudiera :) – DVK