Yes, wise choice. XML::Simple
... isn't. It's for simple XML.
As noted in the comments though - your data is a little ambiguous - specifically, how do you tell what the elements should be called within 'groups' or 'users'.
This looks like you might have parsed some JSON. (Indeed, you can turn it straight back into JSON:
print to_json ( $data, { pretty => 1 } );
The core problem is - where JSON supports arrays, XML does not. So there's really very little you could do that will directly turn your data structure into XML.
However if you don't mind doing a bit of work yourself:
Here's how you assemble some XML using XML::Twig
Assembling XML in Perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new( 'pretty_print' => 'indented' );
$twig->set_root(
XML::Twig::Elt->new(
'map',
)
);
my $item = $twig->root->insert_new_elt('item', { 'id' => 1, 'name' => 'A' } );
my $users = $item ->insert_new_elt( 'users' );
$users -> insert_new_elt ( 'user', { 'id' => 1, 'name' => 'u1' } );
$users -> insert_new_elt ( 'user', { 'id' => 2, 'name' => 'u2' } );
my $groups = $item -> insert_new_elt ('last_child', 'groups');
$groups -> insert_new_elt ( 'group', { 'id' => 1, 'name' => 'g1' } );
$twig->set_xml_version("1.0");
$twig->set_encoding('utf-8');
$twig->print;
Which prints:
<?xml version="1.0" encoding="utf-8"?>
<map>
<item id="1" name="A">
<users>
<user id="2" name="u2"/>
<user id="1" name="u1"/>
</users>
<groups>
<group id="1" name="g1"/>
</groups>
</item>
</map>
Iterating your data structure is left as an exercise for the reader.
As Borodin correctly notes - you have no way to infer map
item
group
or user
from your data structure. The latter two you can perhaps infer based on plurals, but given your data set, the best I can come up with is something like this:
use strict;
use warnings;
use XML::Twig;
my $data = {
id => 1,
name => "A",
users => [ { id => 1, name => "u1" }, { id => 2, name => "u2" } ],
groups => [ { id => 1, name => "g1" } ]
};
my $twig = XML::Twig->new( 'pretty_print' => 'indented' );
$twig->set_root( XML::Twig::Elt->new( 'map', ) );
my $item = $twig->root->insert_new_elt('item');
foreach my $key ( keys %$data ) {
if ( not ref $data->{$key} ) {
$item->set_att( $key, $data->{$key} );
next;
}
if ( ref( $data->{$key} ) eq "ARRAY" ) {
my $fakearray = $item->insert_new_elt($key);
foreach my $element ( @{ $data->{$key} } ) {
my $name = $key;
$name =~ s/s$//g;
$fakearray->insert_new_elt( $name, $element );
}
next;
}
if ( ref ( $data -> {$key} ) eq "HASH" ) {
$item -> insert_new_elt( $key, $data -> {$key} );
next;
}
}
$twig->set_xml_version("1.0");
$twig->set_encoding('utf-8');
$twig->print;
This isn't ideal because - map
is hardcoded, as is item
. And I take the very simplistic approach of assuming the array has an s
on the end, to pluralise it.