Question

I am trying to parse XML into an array of hashes I know you can do this using XML::Simple, but it is not giving me the desired results.

This is my XML:

<?xml version="1.0" ?>
<resultset>
<table name="PROFILE">
 <column name="ID" type="String"/>
 <column name="VERSION" type="String"/>
 <column name="NAME" type="String"/>
 <column name="DESCRIPTION" type="String"/>
<data>
<r><c>0</c><c>1.0</c><c>Default profile</c><c>Default profile</c></r>
<r><c>2</c><c>1.2</c><c>Custom 2</c><c></c></r>
<r><c>3</c><c>6.0</c><c>Custom 3</c><c></c></r>
<r><c>1</c><c>1.15</c><c> For Compare</c><c>The built in profile for compare.</c></r>
<r><c>4</c><c>1.3</c><c>Custom 4</c><c> </c></r>
<r><c>6</c><c>11.0</c><c>Custom 6</c><c>Please only make approved changes.</c></r>
</data>
</table>
</resultset>

This is the output I get from using XML::Simple, XMLin() then printing using Data::Dumper:

$VAR1 = {
          'table' => {
                     'name' => 'PROFILE',
                     'data' => {
                               'r' => [
                                      {
                                        'c' => [
                                               '0',
                                               '1.0',
                                               'Default profile',
                                               'Default profile'
                                             ]
                                      },
                                      {
                                        'c' => [
                                               '2',
                                               '1.2',
                                               'Custom 2',
                                               {}
                                             ]
                                      },
                                      {
                                        'c' => [
                                               '3',
                                               '6.0',
                                               'Custom 3',
                                               {}
                                             ]
                                      },
                                      {
                                        'c' => [
                                               '1',
                                               '1.15',
                                               ' For Compare',
                                               'The built in profile for compare.'
                                             ]
                                      },
                                      {
                                        'c' => [
                                               '4',
                                               '1.3',
                                               'Custom 4',
                                               {}
                                             ]
                                      },
                                      {
                                        'c' => [
                                               '6',
                                               '11.0',
                                               'Custom 6',
                                               'Please only make approved changes.'
                                             ]
                                      }
                                    ]
                             },
                     'column' => {
                                 'ID' => {
                                         'type' => 'String'
                                       },
                                 'NAME' => {
                                           'type' => 'String'
                                         },
                                 'DESCRIPTION' => {
                                                  'type' => 'String'
                                                },
                                 'VERSION' => {
                                              'type' => 'String'
                                            }
                               }
                   }
        };

But I want the following output instead:

$VAR1 = [
          {
            'ID' => '0',
            'NAME' => 'Default profile',
            'DESCRIPTION' => 'Default profile',
            'VERSION' => '1.0'
          },
          {
            'ID' => '2',
            'NAME' => 'Custom 2',
            'DESCRIPTION' => '',
            'VERSION' => '1.2'
          },
          {
            'ID' => '3',
            'NAME' => 'Custom 3',
            'DESCRIPTION' => '',
            'VERSION' => '6.0'
          },
          {
            'ID' => '1',
            'NAME' => ' For Compare',
            'DESCRIPTION' => 'The built in profile for compare.',
            'VERSION' => '1.15'
          },
          {
            'ID' => '4',
            'NAME' => 'Custom 4',
            'DESCRIPTION' => ' ',
            'VERSION' => '1.3'
          },
          {
            'ID' => '6',
            'NAME' => 'Custom 6',
            'DESCRIPTION' => 'Please only make approved changes.',
            'VERSION' => '11.0'
          }
        ];

I don't know if it is possible to get this output with XML::Simple or if it's the best way, but I have looked through the CPAN documentation and searched online and I don't know where to start. Can someone please help me figure out how to get the desired output?

Était-ce utile?

La solution

Yes, it might be possible to fiddle with the settings of XML::Simple some more in order to get the output closer to what you want. However, ultimately you're going to need to do some sort of translation to get your exact goal.

Why not just do the translation with what you've been given? It would probably be possible to pull the column names from the XML, and deal with the wierd empty data being turned into a hash ref, but I leave that up to you:

use XML::Simple;

use strict;
use warnings;

my $data = do { local $/; <DATA> };

my $xml = XMLin($data);

my @formatted = map {
    {
        ID          => $_->{c}[0],
        VERSION     => $_->{c}[1],
        NAME        => $_->{c}[2],
        DESCRIPTION => ref $_->{c}[3] ? '' : $_->{c}[3],
    }
} @{$xml->{table}{data}{r}};

use Data::Dump;
dd \@formatted;


__DATA__
<?xml version="1.0" ?>
<resultset>
<table name="PROFILE">
 <column name="ID" type="String"/>
 <column name="VERSION" type="String"/>
 <column name="NAME" type="String"/>
 <column name="DESCRIPTION" type="String"/>
<data>
<r><c>0</c><c>1.0</c><c>Default profile</c><c>Default profile</c></r>
<r><c>2</c><c>1.2</c><c>Custom 2</c><c></c></r>
<r><c>3</c><c>6.0</c><c>Custom 3</c><c></c></r>
<r><c>1</c><c>1.15</c><c> For Compare</c><c>The built in profile for compare.</c></r>
<r><c>4</c><c>1.3</c><c>Custom 4</c><c> </c></r>
<r><c>6</c><c>11.0</c><c>Custom 6</c><c>Please only make approved changes.</c></r>
</data>
</table>
</resultset>

outputs

[
  {
    DESCRIPTION => "Default profile",
    ID => 0,
    NAME => "Default profile",
    VERSION => "1.0",
  },
  { DESCRIPTION => "", ID => 2, NAME => "Custom 2", VERSION => "1.2" },
  { DESCRIPTION => "", ID => 3, NAME => "Custom 3", VERSION => "6.0" },
  {
    DESCRIPTION => "The built in profile for compare.",
    ID => 1,
    NAME => " For Compare",
    VERSION => "1.15",
  },
  { DESCRIPTION => "", ID => 4, NAME => "Custom 4", VERSION => "1.3" },
  {
    DESCRIPTION => "Please only make approved changes.",
    ID => 6,
    NAME => "Custom 6",
    VERSION => "11.0",
  },
]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top