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

Hello Monks,

I am trying to add a hash to a hash reference. Here is a snippet of the original xml data.
<policies> <New name="Test3" date="28-8-104" description="asdf" link_name="Test3.doc" /> <Newer name="Whatever" date="28-8-104" description="asdf" link_name="Whatever.doc" /> <policies2 name="General Admit to GPRMC" catagory="General" description="" link_name="General Admit to GPRMC.doc" /> </policies>

Here is the perl code I am using.
use strict; my $xs = new XML::Simple; my $xml = $xs->XMLin("$folder_path\\policies.xml", forcearray => 1, ke +yattr => ['policies']); my $hash_add = [{ $cat => [{ 'name' => "$name", 'link_name' => "$link_name", 'description' => "$desc", 'date' => "$today_date" }] }]; # Add to hash push (@{$xml->{'policies'}}, $hash_add); print "Content-type: text/html\n\n"; # Sort hash @{ $xml->{'policies'} } = sort { "\L$a->{name}" cmp "\L$b->{name}"} @{ + $xml->{'policies'} }; use Data::Dumper; print Dumper($xml); $xs->XMLout($xml, outputfile => "$folder_path\\policies.xml", attrinde +nt => 1);

This is the data dump that I come out with is.
'policies' => [ { 'New' => [ { 'date' => '28-8-104', 'name' => 'Test3', 'link_name' => 'Test3.doc', 'description' => 'asdf' } ], 'policies2' => [ { 'name' => 'General Admit +to GPRMC', 'link_name' => 'General A +dmit to GPRMC.doc', 'description' => '', 'catagory' => 'General' } ], 'Newer' => [ { 'date' => '28-8-104', 'name' => 'Whatever', 'link_name' => 'Whatever.doc' +, 'description' => 'asdf' } ] }, [ { 'Newer' => { 'date' => '28-8-104', 'name' => 'whatever', 'description' => 'something +', 'link_name' => 'whatever.do +c' } } ] ]

But my xml file looks like this.
<policies> <New name="Test3" date="28-8-104" description="asdf" link_name="Test3.doc" /> <Newer name="Whatever" date="28-8-104" description="asdf" link_name="Whatever.doc" /> <policies2 name="General Admit to GPRMC" catagory="General" description="" link_name="General Admit to GPRMC.doc" /> </policies> <policies> <anon name="whatever" date="28-8-104" description="something" link_name="whatever.doc" /> </policies>

My question is how do I get it so that it isn't adding the extra policies brackets. And how do I sort the catagories and the name inside of the catagories. I get the error "No such pseudo-hash field "name"" I apologize for the long post, but I wanted to be as thorough as I could. Any help is appreciated.
Thanks

Replies are listed 'Best First'.
Re: Adding a hash to a hash reference.
by ihb (Deacon) on Sep 29, 2004 at 00:28 UTC

    Regarding your extra brackets, try using

    my $hash_add = { $cat => [{ 'name' => "$name", 'link_name' => "$link_name", 'description' => "$desc", 'date' => "$today_date" }] }; for (keys %$hash_add) { $xml->{policies}->[0]->{$_} = $hash_add->{$_}; }
    I haven't used XML::Simple myself but judging from your sample I think this will do what you want.

    Regarding your sort issue I think you want the extra brackets. In fact, they should all be in own brackets, it seems like. Again, I haven't use XML::Simple myself, but if you have a hash with the category as hash, you don't get it sorted. If you store the category alongside name, date, etc you can have each item represented as a hash (as you do now) and store all the hashes in an array, sorted.

    Hope this helps,
    ihb

    Read argumentation in its context!

Re: Adding a hash to a hash reference.
by pg (Canon) on Sep 29, 2004 at 03:10 UTC

    This must be close to what you wanted (you have to observe the original data structure a little bit more carefully, see how XML::Simple use/understand things):

    use strict; use XML::Simple; my $xs = new XML::Simple; my $xml = $xs->XMLin("policies.xml", forcearray => 1, keyattr => ['pol +icies']); my $policyproperties = { 'name' => "1", 'link_name' => "2", 'description' => "3", 'date' => "4" }; # Add to hash $xml->{'addedone'} = $policyproperties; print "Content-type: text/html\n\n"; # Sort hash #@{ $xml->{'policies'} } = sort { "\L$a->{name}" cmp "\L$b->{name}"} @ +{ $xml->{'policies'} }; use Data::Dumper; print Dumper($xml); $xs->XMLout($xml, outputfile => "policies1.xml", attrindent => 1);

    Output:

    <opt> <New name="Test3" date="28-8-104" description="asdf" link_name="Test3.doc" /> <Newer name="Whatever" date="28-8-104" description="asdf" link_name="Whatever.doc" /> <addedone name="1" date="4" description="3" link_name="2" /> <policies2 name="General Admit to GPRMC" catagory="General" description="" link_name="General Admit to GPRMC.doc" /> </opt>

      A slightly different version that keeps root node:

      use strict; use XML::Simple; use Data::Dumper; my $xs = new XML::Simple("KeepRoot" => 1); my $xml = $xs->XMLin("policies.xml", forcearray => 1, keyattr => ['pol +icies']); my $new = { 'name' => "1", 'link_name' => "2", 'description' => "3", 'date' => "4" }; # Add to hash print Dumper($xml); $xml->{'policies'}->[0]->{'added'} = $new; print "Content-type: text/html\n\n"; # Sort hash #@{ $xml->{'policies'} } = sort { "\L$a->{name}" cmp "\L$b->{name}"} @ +{ $xml->{'policies'} }; print Dumper($xml); $xs->XMLout($xml, outputfile => "policies1.xml", attrindent => 1);

      Output:

      <policies> <New name="Test3" date="28-8-104" description="asdf" link_name="Test3.doc" /> <Newer name="Whatever" date="28-8-104" description="asdf" link_name="Whatever.doc" /> <added name="1" date="4" description="3" link_name="2" /> <policies2 name="General Admit to GPRMC" catagory="General" description="" link_name="General Admit to GPRMC.doc" /> </policies>
        All off these ways overwrite the existing one. Is there a way to add so you have 2 Newer?
        <Newer name="Whatever" date="28-8-104" description="asdf" link_name="Whatever.doc" /> <Newer name="1" date="4" description="3" link_name="2" />