Я уже видел несколько ответов в разных местах, касающихся установки порядка элементов 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
.