Scarborough has asked for the wisdom of the Perl Monks concerning the following question:

I have a problem which I hope the wise ones will be able to assist with.
I have looked at The Perl Cook book and its suggestion Tie::IxHash which does not fit the bill on this occassion. The hash I am retrieving from is returned from XML::Simple::XMLin and I guess this does not use Tie::IxHash.
The data in the hash is complex, and represents job spec., perameters and run dates for jobs run on a night shift all of which need to be in a certain order.

My simple solution is to put an extra field containing a number in the XML. But this would mean re-numbering all the jobs should, as often happens, an extra job is inserted or one removed in the middle of the list, I'm sure you would agree wide open to error.

So can anyone give me some ideas on this one?
What I used in the end
For anyone interested I sorted out this problem at the XML stage by using this format
<groupname> <job> <jobname>foo<jobname> <runs>MONSATXBH</runs> </job> <job> <jobname>bar</jobname> <runs>ME</runs> </job> </groupname>
This gave me an array of hashes and of course an array comes out in the same order every time. Probably not as good as a SAX filter but this worked for me.

Replies are listed 'Best First'.
Re: Retrieving from a hash in Insertion Order
by borisz (Canon) on Jun 23, 2004 at 09:44 UTC
    You may add a SAX Filter to XML::Simple that insert your order number for you on the fly.
    Boris
      Thank you for this advice, I'm not sure what a SAX filter is but I'll dig a little deeper.
      Thanks again
        Ok, here is a example, that add a attribute order to every element b.
        #!/usr/bin/perl use strict; use warnings; package MySAXHandler; use base qw(XML::SAX::Base); our $counter = 0; use Data::Dumper; sub start_element { my ( $self, $el ) = @_; if ( $el->{LocalName} eq 'b' ) { unless ( ( $el->{Attributes}->{'{}order'}->{Value} || 0 ) != 0 ) { $el->{Attributes}->{'{}order'} = { 'LocalName' => 'order', 'Prefix' => '', 'Value' => $counter++ +, 'Name' => 'order', 'NamespaceURI' => '' }, } } # process element start event $self->SUPER::start_element($el); } 1; use XML::Simple; use Data::Dumper; use XML::SAX; my $xml = <<"ENDE"; <opt> <a> <b a="12" attr_c="13">test</b> <b a="12" attr_c="14">test</b> <b a="12" attr_c="15">test</b> <b a="12" attr_c="16">test</b> <b a="12" attr_c="17">test</b> </a> </opt> ENDE my $simple = XML::Simple->new( ForceArray => 1); my $filter = MySAXHandler->new( Handler => $simple ); my $parser = XML::SAX::ParserFactory->parser( Handler => $filter ); my $ref = $parser->parse_string($xml); print Dumper($ref);
        Boris
Re: Retrieving from a hash in Insertion Order
by Hena (Friar) on Jun 23, 2004 at 09:43 UTC
    Perhaps make an array of the keys in your hash. And when adding push to array the keys. Then shift will give keys back in insertion order.
      I did consider this myself but as the data is already in the hash from XML::Simple I discounted it as I can't garuntee the return order. But thanks for your help.
Re: Retrieving from a hash in Insertion Order
by delirium (Chaplain) on Jun 23, 2004 at 11:32 UTC
    and run dates

    Those run dates don't happen to coincide with the order you need the hash sorted, do they?

      No sorry there just things like MONSATXBH which means monday to saturday not bank holidays.