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

am a fairly newbiee at coding in perl so please bear with me. I am sure this is probably a simple issue, but cant seem to figure it out myself. Basically I have this code that pulls in XML using XML::Twig, and then is supposed to process based on when it hits a certain criteria. Well the issue is that it works, but it loops 4 times with that code. I have figured out that it has to do with the XML having 4 entries, but am not sure how to clean it up and remove it. I have some variables that will be dynamic once I get past this section, so the code is not complete yet, so please bear with me. Can anyone help out? Below is my code and the XML that I am working with.
#!/usr/local/bin/perl use XML::Twig; use Net::Telnet(); $db = "hrdm2"; $comm = "stop-$db.sh"; $cachedel = "No"; my $s= new XML::Twig( TwigHandlers=> { Product => \&product}); $s->parsefile( 'testservers2.xml'); exit; sub product { my ($s, $product)= @_; my %product; $product{id}= $product->field( 'ServerID'); $product{name}= $product->field( 'DBName'); $product{commandstop}= $product->field( 'CommandStop'); $product{commandstart}= $product->field( 'CommandStart'); $product{cache}= $product->field( 'CacheDir'); if ($db eq $product{name} && $comm eq $product{commandstop} && $ +cachedel eq 'No') { print "DB Name: $product{name}\n" ; print "Command: $product{commandstop}\n"; print "Server: $product{id}\n"; print "Cache Dir:$product{cache}\n"; print "Cache Del: No\n"; $pass = "pass"; $t = new Net::Telnet (Timeout => 500); $t->open("$product{id}"); $t->login('root', $pass); @lines = $t->cmd("cd /apps/gcpsscripts"); @lines = $t->cmd("ls"); @lines = $t->cmd("sh $product{commandstop}"); print @lines; $product->delete; } elsif ($db eq $product{name} && $comm eq $product{commandstop} && +$cachedel eq 'Yes') { print "DB Name: $product{name}\n" ; print "Command: $product{commandstop}\n"; print "Server: $product{id}\n"; print "Cache Dir:$product{cache}\n"; print "Cache Del: Yes\n"; $pass = "pass"; $t = new Net::Telnet (Timeout => 500); $t->open("$product{id}"); $t->login('root', $pass); @lines = $t->cmd("cd /apps/gcpsscripts"); @lines = $t->cmd("ls"); @lines = $t->cmd("sh $product{commandstop}"); print @lines; $product->delete; } elsif ($db eq $product{name} && $comm eq $product{commandstart}) { print "DB Name: $product{name}\n" ; print "Command: $product{commandstart}\n"; print "Server: $product{id}\n"; $pass = "pass"; $t = new Net::Telnet (Timeout => 500); $t->open("$product{id}"); $t->login('root', $pass); @lines = $t->cmd("cd /apps/gcpsscripts"); @lines = $t->cmd("ls"); @lines = $t->cmd("sh $product{commandstart}"); print @lines; $product->delete; } open (LOGFILE, '>>C:\\temp\\stopstart.log') or die "Can't open + log file.\n"; print LOGFILE "\n"; print LOGFILE "@lines \n"; print LOGFILE "\n"; close LOGFILE; }
XML Code below
<?xml version='1.0'?> <Products> <Product> <DBName>hrdm2</DBName> <ServerID>psdevax03</ServerID> <CommandStop>stop-hrdm2.sh</CommandStop> <CommandStart>start-hrdm2.sh</CommandStart> <CacheDir>/apps/846hrdm2/appserv/hrdm2/CACHE</CacheDir> </Product> <Product> <DBName>hrdev</DBName> <ServerID>psdevax06</ServerID> <CommandStop>stop-hrdev.sh</CommandStop> <CommandStart>start-hrdev.sh</CommandStart> <CacheDir>/apps/846hrdev/appserv/hrdev/CACHE</CacheDir> </Product> <Product> <DBName>epdev</DBName> <ServerID>psdevax06</ServerID> <CommandStop>stop-epdev.sh</CommandStop> <CommandStart>start-epdev.sh</CommandStart> <CacheDir>/apps/846epdev/appserv/epdev/CACHE</CacheDir> </Product> <Product> <DBName>eptst</DBName> <ServerID>psdevax06</ServerID> <CommandStop>stop-eptst.sh</CommandStop> <CommandStart>start-eptst.sh</CommandStart> <CacheDir>/apps/846eptst/appserv/eptst/CACHE</CacheDir> </Product> </Products>

Replies are listed 'Best First'.
Re: Perl code looping using XML::Twig
by roubi (Hermit) on Apr 21, 2009 at 00:01 UTC
    First let me advise that you should start use-ing strict and warnings. Today. What you are describing seems like the expected behavior from XML::Twig. Are you asking how to quickly return from 'product' once one of your conditions has been hit? I am no XML::Twig expert but you could do that with a closure like this:
    #!/usr/local/bin/perl use XML::Twig; use Net::Telnet(); $db = "hrdm2"; $comm = "stop-$db.sh"; $cachedel = "No"; $done = 0; my $s= new XML::Twig( TwigHandlers=> { Product => \&product}); $s->parsefile( 'testservers2.xml'); exit; sub product { my ($s, $product)= @_; return if $done; my %product; # In all your if/elsif statements add $done = 1; # Rest of your code }
      Thanks roubi. That was my issue (adding a closure). I was able to return from product once one of my conditions was met. I will also add everyones recommendation for using strict and warnings going forward. Thanks everyone.
Re: Perl code looping using XML::Twig
by toolic (Bishop) on Apr 21, 2009 at 00:45 UTC
    Since it is not clear to me what problem you are trying to solve, all I can offer is the following generic advice.

    Provide more details regarding your problem. Is your output not what you expect it to be? Are you getting unexpected warning or error messages (after you add use warnings and use strict, as others have suggested)?

    Neaten your code up with perltidy.

    There are too many constructs named "product": a sub, a hash and a reference. Since you do not seem to be passing the hash around anywhere, you should consider reducing confusion by eliminating the hash variable. For example, instead of $product{id} why not just $id?

    Use more parentheses to group terms of your long expressions, and then use named operators:

    if (($db eq $name) and ($comm eq $commandstop) and ($cachedel eq 'No') +)
Re: Perl code looping using XML::Twig
by edoc (Chaplain) on Apr 20, 2009 at 23:53 UTC

    First thing, stick "use strict;" in there and fix any errors.

    You'll then need to explain what you think it should be doing as opposed to what it is doing.

    cheers,

    J

Re: Perl code looping using XML::Twig
by fawzi (Initiate) on Apr 21, 2009 at 03:44 UTC
    hi , i am not too familiar with Twig... but in xml parser, the "product" subroutine would be called as many times as the element in the xml file are found, but you knew that... the way i dealt with this is to have a counter to stop iteration whenever i want to. here is snippets of your source code that i modified... use FileHandle; use XML::Twig; use Net::Telnet(); my $db = "hrdm2"; my $comm = "stop-$db.sh"; my $cachedel = "No"; my $productCnt = 0; # Added counter here . . . sub product { my ($s, $product)= @_; my %product; $productCnt++; #increment counter here. print ("Debug: product: productCnt: $productCnt\n"); if ($productCnt >= 2) { exit; # i exited, but you could do something else. } else { $product{id}= $product->field( 'ServerID'); $product{name}= $product->field( 'DBName'); $product{commandstop}= $product->field( 'CommandStop'); . . . . }