0

I am using Perl with XML::Simple to convert a hash into an XML document.

My script looks as follows:

#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;

my $xml_simple = XML::Simple->new( NoAttr => 1,
                   KeepRoot => 1);

my $hash = { output => { 'products' => [ { 'product' => { 'titel' => 'ABN AMRO Bank hypotheken',
                                                          'owner' => 'ABN AMRO Hypotheken Groep',
                                                          'code' => 'ABN AMRO BANK R' } },
                                         { 'product' => { 'titel' => 'Aegon',
                                                          'owner' => 'AEGON Hypotheken',
                                                          'code' => 'AEGON pilot' } } ],
                         'date' => '2012-02-20'} };


my $xml = $xml_simple->XMLout( $hash );

print Dumper( $xml );

The output I am getting is:

<output>
  <date>2012-02-20</date>
  <products>
      <name>product</name>
      <code>ABN AMRO BANK R</code>
      <owner>ABN AMRO Hypotheken Groep</owner>
      <titel>ABN AMRO Bank hypotheken</titel>
  </products>
  <products>
      <name>product</name>
      <code>AEGON pilot</code>
      <owner>AEGON Hypotheken</owner>
      <titel>Aegon</titel>
  </products>
</output>

but what I am looking for is this (see the 'product' nodes):

<output>
  <date>2012-02-20</date>
  <products>
    <product>
      <code>ABN AMRO BANK R</code>
      <owner>ABN AMRO Hypotheken Groep</owner>
      <titel>ABN AMRO Bank hypotheken</titel>
    </product>
    <product>
      <code>AEGON pilot</code>
      <owner>AEGON Hypotheken</owner>
      <titel>Aegon</titel>
    </product>
  </products>
</output>

Is this doable with XML::Simple or should I use a different module?

Mauritz Hansen
  • 4,674
  • 3
  • 29
  • 34

1 Answers1

3

You can let XML::Simple tell you what data structure it wants

#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
my $desired_xml = << 'END';
<myxml>
<output>
  <date>2012-02-20</date>
  <products>
    <product>
      <code>ABN AMRO BANK R</code>
      <owner>ABN AMRO Hypotheken Groep</owner>
      <titel>ABN AMRO Bank hypotheken</titel>
    </product>
    <product>
      <code>AEGON pilot</code>
      <owner>AEGON Hypotheken</owner>
      <titel>Aegon</titel>
    </product>
  </products>
</output>
</myxml>
END
#print $desired_xml;
my $xml_simple = XML::Simple->new(
    NoAttr   => 1,
    KeepRoot => 1
);
#my $hash = XMLin( $desired_xml, forcearray => 1 );
my $hash = {
    output => [
        {
            date     => ["2012-02-20"],
            products => [
                {
                    product => [
                        {
                            code  => ["ABN AMRO BANK R"],
                            owner => ["ABN AMRO Hypotheken Groep"],
                            titel => ["ABN AMRO Bank hypotheken"],
                        },
                        {
                            code  => ["AEGON pilot"],
                            owner => ["AEGON Hypotheken"],
                            titel => ["Aegon"],
                        },
                    ],
                },
            ],
        },
    ],
  };
#print Data::Dumper->Dump( [$hash], [qw(hash)] );
my $xml = $xml_simple->XMLout($hash);
print Data::Dumper->Dump( [$xml], [qw(xml)] );
Philip Durbin
  • 4,042
  • 2
  • 25
  • 36
  • 1
    +1. To spell out one thing in the code explicitely: setting ForceArray is not necessary for XMLout. – daxim Mar 22 '12 at 13:26
  • Thanks Philip. I actually got it working just before your answer by playing with the structure of my hash. Doing it your way (i.e. having XML simply tell you what it needs) is much less painful. – Mauritz Hansen Mar 22 '12 at 13:28
  • Disabling array folding altogether, using a parameter `KeyAttr => {}` would stop the restructuring of the XML. – Borodin Mar 22 '12 at 14:00