Ozeroc has asked for the wisdom of the Perl Monks concerning the following question:

Hello all, Looking for help adding nested elements to my data structure so that XML::Simple will output properly. Here are the significant portions of my code:
use XML::Simple; my $xs = XML::Simple->new( ForceArray => 1, KeepRoot => 1, NoAttr => 1 + ); my $data = { 'Things' => { 'Thing' => [] } }; ... push @{ $data->{Things}->{Thing} }, { 'Item' => $var1, 'Number' => $var2, 'Details' => { 'Detail' => { 'Color' => $var3 } } }; ... my $xml = $xs->XMLout($data); print $xml;
When I print the XML I get:
<Things> <Thing> <Item>XXX</Item> <Number>9999</Number> <Details> <name>Detail</name> <Color>Blue</Color> </Details> </Thing> </Things>
What I'm looking for is:
<Things> <Thing> <Item>XXX</Item> <Number>9999</Number> <Details> <Detail> <Color>Blue</Color> </Detail> </Details> </Thing> </Things>
This is probably a simple problem and I'm assuming that XML::Simple can't go that deep. Any help is greatly appreciated.

Rob

Replies are listed 'Best First'.
Re: XML::Simple and Adding Nested Elements
by psini (Deacon) on May 21, 2008 at 12:50 UTC

    From the POD for XML::Simple I found this:

    Note 1: The default value for 'KeyAttr' is ['name', 'key', 'id']. If you do not want folding on input or unfolding on output you must setting this option to an empty list to disable the feature.

    I think that your problem will go away if you add a KeyAttr=>() in the parameter list as in:

    my $xs = XML::Simple->new( ForceArray => 1, KeepRoot => 1, NoAttr => 1, KeyAttr => ());

    Rule One: Do not act incautiously when confronting a little bald wrinkly smiling man.

      That was it! Well, it was actually:
      my $xs = XML::Simple->new( ForceArray => 1, KeepRoot => 1, NoAttr => 1 +, KeyAttr => []);
      ...with square brackets.
      I had read this but I figured you wouldn't need to set a key attribute to empty if you set NoAttr => 1. That's what I get for making assumptions!
      Thanks!

      Rob

        No, KeyAttr e NoAttr refer to completely different things. It is just a bit confusing...

        Rule One: Do not act incautiously when confronting a little bald wrinkly smiling man.

XML::Simple and Adding Additional Nested Elements
by Ozeroc (Novice) on May 23, 2008 at 07:49 UTC
    Hello all, Looking for help adding additional nested elements to my data structure for eventual output with XML:Simple. Here are the significant portions of my code:
    use XML::Simple; my $xs = XML::Simple->new( ForceArray => 1, KeepRoot => 1, NoAttr => 1 +, KeyAttr => [] ); my $data = { 'Things' => { 'Thing' => [] } }; ... push @{ $data->{Things}->{Thing} }, { 'Item' => $var1, 'Number' => $var2, 'Details' => { 'Detail' => { 'Color' => $var3 } }, }; ... push @{ $data->{Things}->{Thing} }, { 'AdditionalInfo' => { 'Info' => $var4, 'Stuff' => $var5, 'MoreDetails' => { 'ExtraColor' => $var6 } } };
    I'd like to add one or more chunks of 'additional info' as needed. I'd like my resulting XML to look like this:
    <Things> <Thing> <Item>Item1</Item> <Number>123</Number> <Details> <Detail> <Color>Blue</Color> </Detail> </Details> <AdditionalInfo> <Info>data</Info> <Stuff>moredata</Stuff> <MoreDetails> <ExtraColor>Purple</ExtraColor> </MoreDetails> </AdditionalInfo> </Thing> </Things>
    How can I add a hash of additional infomation to a specific Item? When I run the code above the 'AdditionInfo' hash gets appended to the end of the data structure, which makes sense. How do I add data deeper than the initial data structure declaration?
    Thanks for any insight provided. I've already read perldata, BTW...

    Rob

      Obviously you can do this:

      push @{ $data->{Things}->{Thing} }, { 'Item' => $var1, 'Number' => $var2, 'Details' => { 'Detail' => { 'Color' => $var3 } }, 'AdditionalInfo' => { 'Info' => $var4, 'Stuff' => $var5, 'MoreDetails' => { 'ExtraColor' => $var6 } } };

      But probably it is not what you really want. If the real question is "How can I dinamically build the structure that will generate my XML?", the answer is not so simple (aka, I can't make it for you :)):

      The right path to enlightment is to understand how complex data structures work in perl (your example id a HoHoHoHoH, not the very simplest) so you can handle them in a better way

      As an example, the following code probably do what you expect:

      $struc={ 'Item' => $var1, 'Number' => $var2, 'Details' => { 'Detail' => { 'Color' => $var3 } } } $struc->{AdditionalInfo}={ 'Info' => $var4, 'Stuff' => $var5, 'MoreDetails' => { 'ExtraColor' => $var6 } }; push @{ $data->{Things}->{Thing} },$struc;

      Not sure, I can't try it now

      Rule One: Do not act incautiously when confronting a little bald wrinkly smiling man.

        Thank you. That's a good idea. One last question. How would I find a specific Item? I was thinking along these lines:
        if ($data{Things}{Thing}{Item} = "aValue") { ...