in reply to Re^3: Parsing XML w/ Attributes
in thread Parsing XML w/ Attributes

I think it's safe to assume each host is there just once so it may be better to use ForceArray => ['process'] Which will somewhat simplify the code:

#!/usr/bin/perl -w use strict; use XML::Simple; my $parser = new XML::Simple(ForceArray => ['process']); my $ref = $parser->XMLin('c:\temp\file.xml'); foreach my $host (keys(%$ref)){ foreach my $proc (keys(%{$ref->{$host}->{process}})){ print "$proc is running on $host\n"; } }
Also it may be better to use each() instead of foreach():
#!/usr/bin/perl -w use strict; use XML::Simple; my $parser = new XML::Simple(ForceArray => ['process']); my $ref = $parser->XMLin('c:\temp\file.xml'); while (my ($host, $processes) = each %$ref){ foreach my $proc (keys(%{$processes->{process}})){ print "$proc is running on $host\n"; } }
Or using a different module:
use XML::Rules; my $parser = XML::Rules->new( rules => { process => sub { '@list' => $_[1]->{name}}, _default => sub { $_[0] => $_[1]->{list}}, config => 'pass no content', } ); my $data = $parser->parse(\*DATA); #use Data::Dumper; #print Dumper($data); foreach my $host (sort keys %$data) { foreach my $proc (@{$data->{$host}}) { print "$host runs $proc\n"; } } __DATA__ <?xml version="1.0" encoding="utf-8"?> <config> ...

Replies are listed 'Best First'.
Re^5: Parsing XML w/ Attributes
by jrsimmon (Hermit) on Dec 20, 2007 at 15:53 UTC
    Good suggestion (++) on ForceArray => ['process']. I'm not quite sure I see the benefit of each() over foreach() though. Is it the syntax that you like better, or is there an inherit benefit that I'm not aware of?

      It's the fact that you can name both the key and the value from the hash as you iterate so you do not have to use $hash{$key}, but instead have just $value. Which is especially handy if that hash is not in a variable, but rather is part of a more complex datstructure. So that instead of

      foreach my $key (keys %{$data->{blah}[$idx]{blih}}) { print "$key : $data->{blah}[$idx]{blih}{$key}\n"; }
      you have just
      while (my ($key, $value) = each %{$data->{blah}[$idx]{blih}}) { print "$key : $value\n"; }

      In that example it did not make a big difference especially because the value was used only once, but it may be handy. Especially if you find yourself doing something like

      foreach my $key (keys %{$data->{blah}[$idx]{blih}}) { my $value = $data->{blah}[$idx]{blih}{$key}; ... }
      Of course you have to keep in mind that the two are not equivalent. The $value created in the last snippet is a copy, the $value created by each() is an alias. Which makes a huge difference if you modify it :-)