tags:

views:

53

answers:

1

Given the below XML and script, I can produce this:

{
  Item => {
    Details => { color => { Val => "green" }, texture => { Val => "smooth" } },
  },
}

but, I really want the following:

{
  Item => {
    Details => { color => "green", texture => "smooth" },
  },
}

I can't use GroupTags here because there could be many Details items (Key/Val pairs), and they could be unknown before processing. Is it possible to produce the desired structure without resorting to manual extraction via XPath, SAX, etc.?

use strict;
use warnings;
use Data::Dump;
use XML::Simple;


my $xml = do { local $/; scalar <DATA> };
my $obj = XMLin(
    $xml,
    NoAttr     => 1,
    GroupTags  => { Details => 'Item' },
    KeyAttr => [ 'Key'],
);
dd($obj);
exit;

__END__
<?xml version="1.0" encoding="UTF-8"?>
<List attr="ignore">
    <Item attr="ignore">
        <Details attr="ignore">
            <Item attr="ignore">
                <Key>color</Key>
                <Val>green</Val>
            </Item>
            <Item attr="ignore">
                <Key>texture</Key>
                <Val>smooth</Val>
            </Item>
        </Details>
    </Item>
</List>
+5  A: 

Add a ContentKey parameter:

my $obj = XMLin(
    $xml,
    NoAttr     => 1,
    GroupTags  => { Details => 'Item' },
    KeyAttr    => [ 'Key'],
    ContentKey => '-Val',
);

Output:

{
  Item => { Details => { color => "green", texture => "smooth" } },
}

The docs explain:

ContentKey => 'keyname' # in+out - seldom used

When text content is parsed to a hash value, this option lets you specify a name for the hash key to override the default 'content'. So for example:

XMLin('<opt one="1">Text</opt>', ContentKey => 'text')

will parse to:

{ 'one' => 1, 'text' => 'Text' }

instead of:

{ 'one' => 1, 'content' => 'Text' }

XMLout will also honour the value of this option when converting a hashref to XML.

You can also prefix your selected key name with a '-' character to have XMLin try a little harder to eliminate unnecessary 'content' keys after array folding.

Greg Bacon