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 />";
}
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.