Question

I'm trying to parse some XML into Perl, but testing isn't yielding what I'd expect.

$buffer = qq[<DeliveryReport><message id="msgID" sentdate="xxxxx" donedate="xxxxx" status="xxxxxx" gsmerror="0" /></DeliveryReport>];

$xml = XML::Simple->new( ForceArray => 1 );

$file = $xml->XMLin($buffer) or die "Failed for $reply: $!\n";
use Data::Dumper;
print Dumper($file);

$msgid          = $file->{message}->{id};
$message_status = $file->{message}->{status};
print "OUTPUT: $msgid  $message_status";

but the output is blank and the print Dumper looks wrong regards id attribute but I'm not sure why.

$VAR1 = {
    'message' => {
        'msgID' => {
            'status' => 'xxxxxx',
            'gsmerror' => '0',
            'sentdate' => 'xxxxx',
            'donedate' => 'xxxxx'
        }
    }
};

OUTPUT:

Here is the final code working correctly.

use XML::Simple;
use Data::Dumper;

$xml = XML::Simple->new (KeyAttr=>'',ForceArray => 1);
$file = $xml->XMLin('

<DeliveryReport>
    <message id="msgID1" sentdate="xxxxx" donedate="xxxxx" status="xxxxxx" gsmerror="0" />
    <message id="msgID2" sentdate="yyy" donedate="yyy" status="yyy" gsmerror="0" />
</DeliveryReport>
                ') or die "Failed for $reply: $!\n";

print Dumper($file);


$numOfMsgs = @{$file->{message}};
print "<br /><br />I've received $numOfMsgs records<br />";

for($i = 0; $i < $numOfMsgs; $i++) {

     $msgid = $file->{message}->[$i]->{id};
     $message_status = $file->{message}->[$i]->{status};

     print "message id: [$msgid]<br />";
     print "status id: [$message_status]<br />";
     print "<br />";
}
Was it helpful?

Solution

By default, XML::Simple chooses to fold around the following keys by default: name, key, id (see note 1).

Your XML schema contains the id key, which is why the hash is being split there. You can clear the KeyAttr value when you create your object (e.g. $xml = XML::Simple( KeyAttr=>"" );) to override the default behavior.

Your output, with multiple message entries, would look like:

$VAR1 = {
          'message' => [
                       {
                         'gsmerror' => '0',
                         'status' => 'xxxxxx',
                         'id' => 'msgID',
                         'donedate' => 'xxxxx',
                         'sentdate' => 'xxxxx'
                       },
                       {
                         'gsmerror' => '1',
                         'status' => 'yyyyyy',
                         'id' => 'msgID2',
                         'donedate' => 'yyyyy',
                         'sentdate' => 'yyyyy'
                       }
                     ]
        };

So you need to adjust your code slightly to account for %message containing an array of message hashes. The format would be the same for a single message if you keep the ForceArray option, so your code change would work for both cases.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top