Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

XML understanding

by svankalken (Novice)
on Aug 21, 2006 at 23:57 UTC ( [id://568721]=perlquestion: print w/replies, xml ) Need Help??

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

I have the following XML file:
<config> <server> <name>server1</name> <file> <filename>/etc/named.conf</filename> <filename>/etc/nsswitch.conf</filename> </file> </server> <server> <name>server2</name> <file> <filename>/etc/named.conf</filename> <filename>/etc/nsswitch.conf</filename> <filename>/etc/hosts</filename> </file> </server> </config>
I can read it no problem using XML::Simple. Where I have problems is that the filename portion can have a different number of entries per server element. In other words, just as the example above, server 1 has fewer entries than server 2. If they have the same number of entries I can simple use
{server}->{file}->{filename}->[0] {server}->{file}->{filename}->[1]
...which isn't particularly elegant, but works well. I'm having trouble accessing the hash elements as a loop within in the loop. Any ideas? My sample code to do some of this is below:
use XML::Simple; use Data::Dumper; $xml = new XML::Simple (KeyAttr=>[]); $data = $xml->XMLin("xml.xml"); #print Dumper($data); foreach $machine (@{$data->{server}}) { $name=$machine->{name}; print "$name\n"; $file1=$machine->{file}->{filename}->[0]; $file2=$machine->{file}->{filename}->[1]; $file3=$machine->{file}->{filename}->[2]; print "\t$file1 $file2 $file3\t\n"; }

Replies are listed 'Best First'.
Re: XML understanding
by GrandFather (Saint) on Aug 22, 2006 at 00:09 UTC

    You just want to print the elements of an array. It takes a little digging to get to the array, but you've already done most of that. The only missing bit is casting the array reference to an array. The magic is @{$machine->{file}{filename}}. Here's the result:

    use strict; use warnings; use XML::Simple; my $str = <<XML; <config> <server> <name>server1</name> <file> <filename>/etc/named.conf</filename> <filename>/etc/nsswitch.conf</filename> </file> </server> <server> <name>server2</name> <file> <filename>/etc/named.conf</filename> <filename>/etc/nsswitch.conf</filename> <filename>/etc/hosts</filename> </file> </server> </config> XML my $xml = new XML::Simple (KeyAttr=>[]); my $data = $xml->XMLin ($str); foreach my $machine (@{$data->{server}}) { my $name = $machine->{name}; print "$name\n"; print "\t@{$machine->{file}{filename}}\n"; }

    Prints:

    server1 /etc/named.conf /etc/nsswitch.conf server2 /etc/named.conf /etc/nsswitch.conf /etc/hosts

    DWIM is Perl's answer to Gödel
Re: XML understanding
by imp (Priest) on Aug 22, 2006 at 00:07 UTC
    $machine->{file}{filename} provides an arrayref that contains the filename list. Just iterate over it, or join the values as in this example:
    use XML::Simple; use Data::Dumper; use strict; use warnings; my $xml = new XML::Simple (KeyAttr=>[]); my $data = $xml->XMLin("xml.xml"); #print Dumper($data); foreach my $machine (@{$data->{server}}) { my $name=$machine->{name}; print "$name\n"; my $file_list = $machine->{file}->{filename}; printf "\t%s\t\n",join(' ', @$file_list); }
Re: XML understanding
by izut (Chaplain) on Aug 22, 2006 at 11:35 UTC

    You can use XML::Twig for parsing that XML tree:

    #!/usr/bin/perl use strict; use warnings; use XML::Twig; my $twig = XML::Twig->new( twig_handlers => { 'server' => sub { print "server: ", $_->first_child('name')->tex +t, "\n"; foreach my $c ($_->children('file')) { print "filename: ", $_->text, "\n" for +each $c->children('filename'); } }, }, ); $twig->parse(*DATA); __DATA__ <config> <server> <name>server1</name> <file> <filename>/etc/named.conf</filename> <filename>/etc/nsswitch.conf</filename> </file> </server> <server> <name>server2</name> <file> <filename>/etc/named.conf</filename> <filename>/etc/nsswitch.conf</filename> <filename>/etc/hosts</filename> </file> </server> </config>

    Outputs:

    server: server1 filename: /etc/named.conf filename: /etc/nsswitch.conf server: server2 filename: /etc/named.conf filename: /etc/nsswitch.conf filename: /etc/hosts

    Igor 'izut' Sutton
    your code, your rules.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://568721]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-03-29 11:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found