in reply to XML::Twig Help

One approach is to use Twig handlers. For example:
use warnings; use strict; use XML::Twig; my $xmlstr = <<EOF; <AGENT hostname="viper3"> <LADDER> <ACL> <ACCOUNT id="4cf031986c"> <USERNAME>emcon</USERNAME> <HOST>*sppcon*</HOST> <PERMISSION>CDOPS</PERMISSION> </ACCOUNT> <ACCOUNT id="b92794bbd7"> <USERNAME>cpemcon</USERNAME> <HOST>*</HOST> <PERMISSION>COPS</PERMISSION> </ACCOUNT> <ACCOUNT id="8ff0478641"> <USERNAME>dbemcon</USERNAME> <HOST>*</HOST> <PERMISSION>COPS</PERMISSION> </ACCOUNT> <ACCOUNT id="22d2647740"> <USERNAME>tuxemcon</USERNAME> <HOST>*</HOST> <PERMISSION>COPS</PERMISSION> </ACCOUNT> </ACL> </LADDER> </AGENT> EOF my $twig = XML::Twig->new( twig_handlers => {ACCOUNT => \&acct} ); $twig->parse($xmlstr); sub acct { my ($t, $elt) = @_; print $elt->att('id'), "\n"; print $elt->first_child('USERNAME' )->text(), "\n"; print $elt->first_child('HOST' )->text(), "\n"; print $elt->first_child('PERMISSION')->text(), "\n"; print "\n"; } __END__ 4cf031986c emcon *sppcon* CDOPS b92794bbd7 cpemcon * COPS 8ff0478641 dbemcon * COPS 22d2647740 tuxemcon * COPS

Update: There is a great tutorial at http://web.archive.org/web/20080702002018/http://xmltwig.com (unfortunately, the tutorial link from XML::Twig seems to be down).

Update: using mirod's suggestion, and refactoring a little...

sub acct { my ($t, $elt) = @_; print $elt->att('id'), "\n"; for my $tag (qw(USERNAME HOST PERMISSION)) { print $elt->field($tag), "\n"; } print "\n"; }

Replies are listed 'Best First'.
Re^2: XML::Twig Help
by mirod (Canon) on Jan 07, 2011 at 14:35 UTC

    Usually, instead of writing $elt->first_child('USERNAME'  )->text(), I write $elt->field( 'USERNAME'), it is easier to read. It also doesn't die if there is no USERNAME child, which may be convenient.

    Oh, and xmltwig.com is down at the moment, but it's mirrored at mirod.org.

      ++mirod, I was unaware of field.

      On another topic, you probably didn't see my update regarding access to your excellent website. Were you aware that it has been tough to get to for some time now?

        I REALLY appreciate your help team...

        OK, that seems to help me understand handlers better but what about situations where the xml tag has multiple children of the same name? When attempting to use the handler as below I only get the first TYPE element.

        i.e.

        use strict; use XML::Twig; my $xmlstr = <<EOF; <TREES> <APPLE> <TYPE id="1001">Scarlet</TYPE> <TYPE id="1002">Red</TYPE> <TYPE id="1003">Gold</TYPE> <TYPE id="1004">Fuji</TYPE> <TYPE id="1005">Scarlet</TYPE> </APPLE> <PEAR> <TYPE id="1001">Bradford</TYPE> <TYPE id="1002">Cleveland Select</TYPE> <TYPE id="1003">Aristocrat</TYPE> <TYPE id="1004">Autumn Blaze</TYPE> </PEAR> </TREES> EOF my $twig = XML::Twig->new(twig_handlers => {APPLE => \&apple}); $twig->parse($xmlstr); sub apple { my ($t, $elt) = @_; print $elt->att('id'), "\n"; print $elt->field('TYPE' ), "\n"; print "\n"; }
        Good day team,
        I wanted to thank everyone for the suggestions and I seem to be on my way using this module but I am stuck on one final extraction component and not sure exactly what I am doing wrong.

        Below is a sample of the xml and the small snipnet of code I am trying to utilize. But No Joy!

        I would appreciate one final example to help me get over this last hump and I think I will be ok if I could just understand how to walk down the twig just a few elements and then be able to understand the proper way to get further down the twig.

        Again many thanks in advance.

        #!/home/p1aldbw1/aldb/perl-5.12.2/bin/perl use warnings; use strict; use XML::Twig; use Data::Dumper; my $xmlstr = <<EOF; <AGENT hostname="viper3"> <NAMESPACE> <APPCLASS name="ORACLE_AVAILABILITY"> <INSTANCE name="atecr"> <PARAMETER name="InstanceStatus"> <TYPE>CONSUMER</TYPE> <BORDER> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </BORDER> <ALARM1> <ACTIVE>1</ACTIVE> <MIN>1</MIN> <MAX>1</MAX> <TRIGGER>After 7 times</TRIGGER> <RECOVERY>1</RECOVERY> <STATE>WARN</STATE> </ALARM1> <ALARM2> <ACTIVE>1</ACTIVE> <MIN>2</MIN> <MAX>2</MAX> <TRIGGER>After 7 times</TRIGGER> <RECOVERY>1</RECOVERY> <STATE>ALARM</STATE> </ALARM2> </PARAMETER> <PARAMETER name="RSSpaceLeft"> <TYPE>CONSUMER</TYPE> <BORDER> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </BORDER> <ALARM1> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </ALARM1> <ALARM2> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </ALARM2> </PARAMETER> <PARAMETER name="CannotExtend"> <TYPE>CONSUMER</TYPE> <BORDER> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </BORDER> <ALARM1> <ACTIVE>1</ACTIVE> <MIN>1</MIN> <MAX>1</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>1</RECOVERY> <STATE>ALARM</STATE> </ALARM1> <ALARM2> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </ALARM2> </PARAMETER> </INSTANCE> </APPCLASS> <APPCLASS name="ORACLE_CAPACITY"> <INSTANCE name="atecq"> <PARAMETER name="FreeSpace"> <TYPE>CONSUMER</TYPE> <BORDER> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </BORDER> <ALARM1> <ACTIVE>1</ACTIVE> <MIN>1</MIN> <MAX>1</MAX> <TRIGGER>After 7 times</TRIGGER> <RECOVERY>1</RECOVERY> <STATE>WARN</STATE> </ALARM1> <ALARM2> <ACTIVE>1</ACTIVE> <MIN>2</MIN> <MAX>2</MAX> <TRIGGER>After 7 times</TRIGGER> <RECOVERY>1</RECOVERY> <STATE>ALARM</STATE> </ALARM2> </PARAMETER> <PARAMETER name="ExtentsLeft"> <TYPE>CONSUMER</TYPE> <BORDER> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </BORDER> <ALARM1> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </ALARM1> <ALARM2> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </ALARM2> </PARAMETER> <PARAMETER name="CursorsLeft"> <TYPE>CONSUMER</TYPE> <BORDER> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </BORDER> <ALARM1> <ACTIVE>1</ACTIVE> <MIN>1</MIN> <MAX>1</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>1</RECOVERY> <STATE>ALARM</STATE> </ALARM1> <ALARM2> <ACTIVE>0</ACTIVE> <MIN>0</MIN> <MAX>0</MAX> <TRIGGER>Immediate</TRIGGER> <RECOVERY>0</RECOVERY> <STATE>OK</STATE> </ALARM2> </PARAMETER> </INSTANCE> </APPCLASS> </NAMESPACE> </AGENT EOF my $twig = XML::Twig->new(twig_handlers => {NAMESPACE => \&namespace}) +; $twig->parse($xmlstr); my(@NAMESPACE,$APPCLASS,$INSTANCE,$PARAMETER,$PARAM_TYPE); sub namespace { my ($t, $elt) = @_; for my $appclass ( $elt->children() ) { $APPCLASS = $appclass->att('name'); for my $instance ($appclass->children()) { $INSTANCE = $instance->att('name'); for my $parameter ($instance->children()) { $PARAMETER = $parameter->att('name'); $PARAM_TYPE = $parameter->field('TYPE'); @NAMESPACE = $APPCLASS . "~" . $INSTANCE . "~" . $PARA +METER . "~" . $PARAM_TYPE; } } } } print Dumper @NAMESPACE; print "\n\n";


        I must be on the right track because it does in fact return the first branch as expected.

        $VAR1 = 'ORACLE_CAPACITY~atecq~CursorsLeft~CONSUMER';