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

I'm constructing a UI via WxWidgets and will be using an XML file for the configuration allowing it to be modified outside of my perl code. My question is how can I determine the number of buttons needed for creation based on the layout of my XML code below?
<?xml version="1.0" encoding="utf-8"?> <install type="module" version="1.0.0"> <name>TEST</name> <notebook_tabs> <tab index="1">Create <button internal_name="test1" parent="-1" text="button 1" x_coordinate="5" y_coordinate="5" x_size="-1" y_size="-1" evt_1="EVT_BUTTON" evt_1_function="testclick" /> <button internal_name="test2" parent="-1" text="button 2" x_coordinate="50" y_coordinate="50" x_size="-1" y_size="-1" evt_1="EVT_BUTTON" evt_1_function="testclick2" /> </tab> <tab index="2">Assign</tab> </notebook_tabs> </install>
Below is my test code...I'm able to retrieve the tabs data but can't seem to determine the number of buttons and the params for each.
use strict; use warnings; use XML::Simple; my $config = XMLin('C:\path\tp\test.xml'); use Data::Dumper; #print Dumper($config); my @tabs = $config->{notebook_tabs}; print Dumper(@tabs);
Any help or suggestions would be greatly appreciated.

Replies are listed 'Best First'.
Re: XML Parsing questions and recommendations?
by moritz (Cardinal) on Oct 08, 2008 at 14:49 UTC
    This works for me:
    use strict; use warnings; use XML::Simple; my $config = XMLin('foo.xml', ForceArray => [qw(tab button)]); my @tabs = @{$config->{notebook_tabs}{tab}}; my $n = 1; for my $t (@tabs) { print "In tab No. $n\n"; if (exists $t->{button}) { print "\t found ", scalar(@{$t->{button}}), " button\n"; } else { print "\t no tabs\n"; } $n++; } __END__ In tab No. 1 found 2 button In tab No. 2 no tabs
Re: XML Parsing questions and recommendations?
by toolic (Bishop) on Oct 08, 2008 at 15:02 UTC
    I recommend XML::Twig:
    use strict; use warnings; use XML::Twig; use Data::Dumper; my $xfile = <<EOF; <?xml version="1.0" encoding="utf-8"?> <install type="module" version="1.0.0"> <name>TEST</name> <notebook_tabs> <tab index="1">Create <button internal_name="test1" parent="-1" text="button 1" x_coordinate="5" y_coordinate="5" x_size="-1" y_size="-1" evt_1="EVT_BUTTON" evt_1_function="testclick" /> <button internal_name="test2" parent="-1" text="button 2" x_coordinate="50" y_coordinate="50" x_size="-1" y_size="-1" evt_1="EVT_BUTTON" evt_1_function="testclick2" /> </tab> <tab index="2">Assign</tab> </notebook_tabs> </install> EOF my $t= new XML::Twig(); $t->parse($xfile); my $install = $t->root(); my $note_tabs = $install->first_child('notebook_tabs'); my @tabs = $note_tabs->children('tab'); for my $tab (@tabs) { print "\nTab ", $tab->att('index'), "\n"; my @buttons = $tab->children('button'); print "number of buttons = ", scalar @buttons, "\n"; for my $button (@buttons) { my @params = $button->atts(); print Dumper(\@params); } }

    Prints:

      This does seem easier but I receive this error when reading from my xml file:
      not well-formed (invalid token) at line 1, column 2, byte 2:
      I would assume that's this line correct:
      <?xml version="1.0" encoding="utf-8"?>
      I don't see anything wrong with it ???
        nm...I found my error...had to use $t->parsefile($xml_file); Thanks!
Re: XML Parsing questions and recommendations?
by Your Mother (Archbishop) on Oct 08, 2008 at 16:52 UTC

    And perhaps lastly, an XML::LibXML example.

    use XML::LibXML; my $parser = XML::LibXML->new(); my $doc = $parser->parse_string( do{ local $/; <DATA> } ); for my $button ( $doc->findnodes("//button") ) { print "A button\n"; for my $attr ( $button->attributes ) { printf "%30s --> %s\n", $attr->name, $attr->getValue; } } __DATA__ <?xml version="1.0" encoding="utf-8"?> <install type="module" version="1.0.0"> <name>TEST</name> <notebook_tabs> <tab index="1">Create <button internal_name="test1" parent="-1" text="button 1" x_coordinate="5" y_coordinate="5" x_size="-1" y_size="-1" evt_1="EVT_BUTTON" evt_1_function="testclick" /> <button internal_name="test2" parent="-1" text="button 2" x_coordinate="50" y_coordinate="50" x_size="-1" y_size="-1" evt_1="EVT_BUTTON" evt_1_function="testclick2" /> </tab> <tab index="2">Assign</tab> </notebook_tabs> </install>