Search code examples
xmlperldata-structuresreferencexml-simple

How do I access data in a nested data structure from XML::Simple?


I have to write a Perl script to convert an XML file into a CSV file. I've already written something simple in one context, and need to enhance it for a different dataset, and can't quite figure out what to do.

I'm using XML::Simple.

Here is one record of the data:

<custom-objects xmlns="http://www.demandware.com/xml/impex/customobject/2006-10-31">
    <custom-object type-id="emailBackInStockHistory" object-id="bczCAiaag0APcaaacLsvpJRmzW">
        <object-attribute attribute-id="email">[email protected]</object-attribute>
        <object-attribute attribute-id="emailSentAt">2010-04-10T09:00:01.000+0000</object-attribute>
        <object-attribute attribute-id="productID">someprodid</object-attribute>
        <object-attribute attribute-id="requestedAt">2010-04-09T10:07:54.000+0000</object-attribute>
        <object-attribute attribute-id="siteID">someSITEid</object-attribute>
    </custom-object>
</custom-objects>

Using the Data::Dumper module I see that the data is parsed as this:

'custom-object' => [
    {
        'type-id'          => 'emailBackInStockHistory',
        'object-id'        => 'bczCAiaag0APcaaacLsvpJRmzW',
        'object-attribute' => [
            {
                'attribute-id' => 'email',
                'content'      => '[email protected]'
            },
            {
                'attribute-id' => 'emailSentAt',
                'content'      => '2010-04-10T09:00:01.000+0000'
            },
            {
                'attribute-id' => 'productID',
                'content'      => 'someprodid'
            },
            {
                'attribute-id' => 'requestedAt',
                'content'      => '2010-04-09T10:07:54.000+0000'
            },
            {
                'attribute-id' => 'siteID',
                'content'      => 'someSITEid'
            }
        ]
    },

Here is some code that I've tried to use to perform this export:

foreach $o (@{$data->{'custom-object'}}) {
    print $o->{'type-id'},   ",";
    print $o->{'object-id'}, ",";
    print $o->{'custom-object'}->{'object-attribute'}->{'email'}, ",";
    print "\n";

The type-id and object-id attributes get output properly, but I can't figure out how to print the data from the object-attribute reference.


Solution

  • You need to iterate over your object-attribute array-ref like your doing with the custom-object array-ref. Also have a look at Text::CSV for a more robust way of creating csv files.

    foreach my $obj ( @{ $data->{'custom-object'} } ) {
        print $obj->{'type-id'}, ",";
        print $obj->{'object-id'}, ",";
        foreach my $attr ( @{ $obj->{'object-attribute'} } ) {
            if ( $attr->{'attribute-id'} eq 'email' ) {
                print $attr->{'content'}, ",";
            }
        }
        print "\n";
    }