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

When I try to parse the following formatted xml data with XML::Simple, I am not able to forcearray the .server. element unless I change the case of the .name. element (or rename it). The value of name is used as a key to the rest of the server elements when left in lower case. Is XML::Simple looking for lower case .name. elements and doing something with them

<data> <server> <name>cns04-fs16</name> <location>atlanta</location> <grouping> <primary>Storage Servers</primary> <secondary>Mail Filers</secondary> </grouping> <event> <name>disk</ name > <state> <name>online</name> <data></data> </state> <length>6.43 days</length> <received_by>10.10.10.10</received_by> <color>yellow</color> <received_at>Thu Mar 30 15:03:16 EST 2006</received_at> <sparedata>Disk on cns04-fs16 at WARNING level</sparedata> <entry> <color>yellow</color> <desc>/mail/vol/cns04-fs16 (93%) has reached the defined d +isk space WARNING level (92%)</desc> </entry> </event> </server> <server> <name>titan </name> <location>atlanta</location> <grouping> <primary>Storage Servers</primary> <secondary>Bluearc Servers</secondary> </grouping> <event> <name>basys</name> <state> <name>online</name> <data></data> </state> <length>6.44 days</length> <received_by>10.10.10.10</received_by> <color>yellow</color> <received_at>Thu Mar 30 15:05:12 2006</received_at> <sparedata></sparedata> <entry> <color>yellow</color> <desc>node 1 is in status (notUp)</desc> </entry> <entry> <color>yellow</color> <desc>TITANPC-2 is in status (notUp)</desc> </entry> <entry> <color>yellow</color> <desc>EVS006 is in status (offLine)</desc> </entry> </event> </server> </data>

Replies are listed 'Best First'.
Re: XML::Simple element handling
by blue_cowdawg (Monsignor) on May 10, 2006 at 17:43 UTC

    Brer Monk,
    I wrote a quick little ditty to check out your XML as follows:

    #!/usr/bin/perl -w use strict; use XML::Simple; use Data::Dumper; my $stuff=XMLin(); print Dumper($stuff);
    When I ran my code I noticed the following oddity in the Data::Dumper output:
    $VAR1 = { 'server' => { 'location' => 'atlanta', 'name' => 'cns04-fs16', 'event' => { 'name' => 'diskname > online 6.43 days 10.10.10.10 yellow Thu Mar 30 15:03:16 EST 2006 Disk on cns04-fs16 at WARNING level yellow /mail/vol/cns04-fs16 (93%) has reached the defined disk sp +ace WARNING level (92%) titan atlanta Storage Servers Bluearc Servers basys online 6.44 days 10.10.10.10 yellow Thu Mar 30 15:05:12 2006 yellow node 1 is in status (notUp) yellow TITANPC-2 is in status (notUp) yellow EVS006 is in status (offLine) ' }, 'grouping' => { 'secondary' => 'Mail Filers', 'primary' => 'Storage Servers' } } };

    Immediately I suspected that your XML had some sort of error in it and lo and behold, if I changed one line from

    <name>disk</ name >
    to
    <name>disk</name>
    eliminating the extra space after the closing tag's slash and when I reran my test I got:
    $VAR1 = { 'server' => { 'titan ' => { 'location' => 'atlanta', 'grouping' => { 'secondary' => 'Bluear +c Servers', 'primary' => 'Storage +Servers' }, 'event' => { 'sparedata' => {}, 'entry' => [ { 'color' => ' +yellow', 'desc' => 'n +ode 1 is in status (notUp)' }, { 'color' => ' +yellow', 'desc' => 'T +ITANPC-2 is in status (notUp)' }, { 'color' => ' +yellow', 'desc' => 'E +VS006 is in status (offLine)' } ], 'received_by' => '10.10.1 +0.10', 'name' => 'basys', 'state' => { 'name' => 'onl +ine', 'data' => {} }, 'received_at' => 'Thu Mar + 30 15:05:12 2006', 'length' => '6.44 days', 'color' => 'yellow' } }, 'cns04-fs16' => { 'location' => 'atlanta', 'grouping' => { 'secondary' => 'Ma +il Filers', 'primary' => 'Stor +age Servers' }, 'event' => { 'sparedata' => 'Disk +on cns04-fs16 at WARNING level', 'entry' => { 'color' => + 'yellow', + 'desc' => '/mail/vol/cns04-fs16 (93%) has reached the defined disk s +pace WARNING level (92%)' }, 'received_by' => '10. +10.10.10', 'name' => +'disk', 'state' => { 'name' => +'online', 'data' => +{} }, 'received_at' => 'Thu + Mar 30 15:03:16 EST 2006', 'length' => '6.43 day +s', 'color' => 'yellow' } } } };

    That to my eye looks much better.

    Now, I must confess that my XML foo is not quite what it should be so I'm not sure if the space after the closing tag's slash is allowed there or not, but I'm not arguing with results. Either the XML was incorrect or there is a parsing issue with XML::Simple.

    HTH


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
      space must have been added when i was formatting my input. In my xml file the space is not there. with the code below i expect the server elements to be put into an array. this is my perl:
      #!/ms/local/perl5.8.0/bin/perl -w use strict; use XML::Simple; use Data::Dumper; my $bbtmpdata = "bb.xml"; my $xml = new XML::Simple; my $bbevents = $xml->XMLin($bbtmpdata, forcearray=>['server']); print Dumper($bbevents);
            i expect the server elements to be put into an array. this is my perl

        What exactly do you mean by that? Can you post a shortened example of what you want the structure to look like?

        Based on a best guess of what you meant I changed my code to look like:

        #!/usr/bin/perl -w use strict; use XML::Simple; use Data::Dumper; my $stuff=XMLin(undef,KeyAttr=>['server']); print Dumper($stuff);
        which then takes the server element and treats everything enclosed by that as an array. Is that what you were after? Short sample of the structure:
        $VAR1 = { 'server' => [ { 'location' => 'atlanta', 'name' => 'cns04-fs16', 'event' => { 'sparedata' => 'Disk on cns04-fs16 +at WARNING level', 'entry' => { 'color' => 'yellow', 'desc' => '/mail/vol/cns +04-fs16 (9 3%) has reached the defined disk space WARNING level (92%) +' }, 'received_by' => '10.10.10.10', 'name' => 'disk', 'state' => { 'name' => 'online', 'data' => {} }, 'received_at' => 'Thu Mar 30 15:03: +16 EST 200 6', 'length' => '6.43 days', 'color' => 'yellow' }, 'grouping' => { 'secondary' => 'Mail Filers', 'primary' => 'Storage Servers' } },


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: XML::Simple element handling
by grantm (Parson) on May 11, 2006 at 02:28 UTC
    I am not able to forcearray the .server. element unless I change the case of the .name.

    XML::Simple treats elements or attributes named 'name', 'key' or 'id' in a special way by default. You would use the KeyAttr option to tell it not to, as explained in the documentation.

    In your case, the ForceArray is working correctly, but array folding happens next and turns the array into a hash keyed on 'name'. If you don't want that then just turn off array folding.

    This node may make that a bit clearer.

      thanks for the data. keyattr was the problem. as always, rtfm