views:

497

answers:

3

I just want to find the way of disable the sort operation in XML::Simple

For example:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Simple;

my %my_xml = (
    NAME  => [ 'test' ],
    EMAIL => [ '[email protected]' ],
    ID    => 12,
);

my $xs = XML::Simple->new;
print $xs->XMLout(\%my_xml, RootName => "datas", NoSort => 1);

__END__

I get following output:

<datas ID="12">
  <EMAIL>[email protected]</EMAIL>
  <NAME>test</NAME>
</datas>

But I want the output to be:

<datas ID="12">
  <NAME>test</NAME>
  <EMAIL>[email protected]</EMAIL>
</datas>

How can I achieve this?

A: 

The order of elements in a hash table are not guaranteed to be in the order you enter them. Have you tried printing out the elements of the hash table to verify that they are in the order you want?

Also, the order of elements in an XML file shouldn't matter to any application reading the XML - the information is still there and labeled by the tag.

Ron

This test seems to show that the nosort option is working, it's just the order of the hash:

use strict;
use XML::Simple;

my $name        = "Ron";
my $email       = "ron.savage\@gmail.com";
my $id          = 5;

my %my_xml = (  'NAME' => $name, 'EMAIL' => $email, 'ID' => $id );

my $var;
my $val;
print "Hash: \n";
foreach $var (keys(%my_xml)) 
   {
   $val = $my_xml{$var};
   print "    ${var}=${val}\n";
   }

my $xs = XML::Simple->new();
my $xml_ref = \%my_xml ;
my $xml = $xs->XMLout($xml_ref, RootName=> "datas" ,nosort => 1);

print "XML:\n".$xml;

output:

~/dot-dash-dot.com/files >perl testxml.pl
Hash:
    ID=5
    NAME=Ron
    [email protected]
XML:
<datas ID="5" NAME="Ron" EMAIL="[email protected]" />

This is perl, v5.8.4 built for i386-linux-thread-multi
Ron Savage
Yes I agree . But i am looking for option with out any sorting
joe
Actually, the order of element is significant in XML. DTDs and schemas let you specify in which order the elements should appear in a document. OTOH, the order of attributes is not usually considered significant.
mirod
+4  A: 

It seems that Tie::IxHash can help you.

In my tests, reversing the email and name lines in the hash in the code below result in them being reversed in the output. I am not sure that would still be the case with more complex data structures, depending on whether XML::Simple reuses the original hash or copies it.

#!/usr/bin/perl

use strict;
use warnings;

use Tie::IxHash;
use XML::Simple;

my( $id, $name, $email)= ( 'i1', 'John Doe', '[email protected]');

my %my_xml;
tie %my_xml, 'Tie::IxHash';
%my_xml = (
            'EMAIL' => [$email],                   
            'NAME' => [$name],
             'ID'  => $id,
          );

my $xs = XML::Simple->new();
my $xml_ref = \%my_xml ;
my $xml = $xs->XMLout($xml_ref, RootName=> "datas" ,NoSort => 1);

print $xml;
mirod
+3  A: 

According the Grant McLean (author of XML::Simple)

if we want is for the order of elements from the original document to be retained. Unfortunately, that is not possible with XML::Simple. When the document is parsed, XML::Simple stores the element data in hashes. Hashes do not remember the order in which keys were added so this data is lost.

If we want to retain the document order you need to use a different module. he recommends XML::LibXML. In fact he wrote an article about switching from XML::Simple to XML::LibXML here:

http://www.perlmonks.org/index.pl?node_id=490846

joe