Posted on 2009-01-22 15:43:16-08 by cwoodfield
Null KeyAttr tag changes resulting structure
Hi,

I'm noticing a major difference in resulting data structures when using KeyAttr, if there is an instance of the tag referenced in KeyAttr that is null.

I'm calling XMLin as follows:
my $xml = new XML::Simple(ForceArray => ['element'], KeyAttr => 'name'); $r = $xml->XMLin("testfile.xml"); print Dumper($r);

When run against the following XML, I get sensible output, with <name> being the hash key for each struct (which only contains 'value' => val in this testcase):
<xml> <element> <name>foo</name> <value>bar</value> </element> <element> <name>bar</name> <value>baz</value> </element> </xml>

Resulting Data::Dumper output:
$VAR1 = { 'element' => { 'bar' => { 'value' => 'baz' }, 'foo' => { 'value' => 'bar' } } };

However, if I introduce an <element> where <name> is null, I get something completely different!
<xml> <element> <name>foo</name> <value>bar</value> </element> <element> <name></name> <value>baz</value> </element> </xml>

Resulting struct (Data::Dumper output):
$VAR1 = { 'element' => [ { 'value' => 'bar', 'name' => 'foo' }, { 'value' => 'baz', 'name' => {} } ] };

This results is that $r->{element} is now an array, not a hash as it was before, and the <name> tags no longer become a hash key for anything. Because of this, I now have to test for ref($r->{element} after XMLin, and fix my code to "move things around" if this happens. I've observed that this will happen even if there is a single null <name> element in the XML, no matter how many other <elements> there are with non-null <name> tags. In the event of a null <name> tag, this is what I'd prefer to have the resulting struct look like:
$VAR1 = { 'element' => { '' => { 'value' => 'baz' }, 'foo' => { 'value' => 'bar' } } };

(And yes, I've tested to verify that a empty-string hash key is legal). Any suggestions or ideas?
Direct Responses: Write a response
Perl Weekly newsletter
A free weekly newsletter for people who are busy to read all the blogs. click here to check it out.