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

I am going through a book called XML and Perl. And I am using Windows with Strawberry Perl. I cannot seem to get this thing to work even though I copy pasted it (at first I hand coded everything).

The code is listed below:

use strict; use XML::Parser; my $parser = XML::Parser->new(Style => 'Stream', Handlers => {Init => \&init, Start => \&start, Char => \&char, End => \&end, Final => \&final}); $parser->parsefile(shift); #################################### # These variables keep track # # of each distribution data, and # # are reset at each distribution. # # # my $dist_count = 0; # my $dist_cost = 0; # my $dist_out = 0; # #################################### #################################### # These variables keep track # # of the totals which are # # accumulated throughout the # # parsing process # # # my $total_count = 0; # my $total_cost = 0; # my $total_out = 0; # #################################### my $curr_val = ""; ## Retains the text value ## within the current node my @os_avail = (); ## An array of available ## operating systems sub init { my $e = shift; print "\n***** Software Inventory Report *****\n"; print "-------------------------------------\n\n"; } sub start{ my ($e, $tag, %attr) = @_; if ($tag eq "distribution") { print "*$attr{name} (version $attr{version})*\n"; } elsif ($tag eq "os") { push(@os_avail,$attr{name}); } } sub char { my ($e, $string) = @_; $curr_val = $string; } sub end { my ($e, $tag) = @_; if ($tag eq "price") { $dist_cost = $curr_val; $total_cost += $curr_val; } elsif ($tag eq "total") { $dist_count += $curr_val; $total_count += $curr_val; } elsif ($tag eq "out") { $dist_out += $curr_val; $total_out += $curr_val; } elsif ($tag eq "distribution") { print "Packages: $dist_count\n"; print "Available: ".($dist_count - $dist_out)."\n"; print "Value ($dist_cost per piece): \$".($dist_count*$dist_cost). +"\n"; print "-------------------------------------\n\n"; ## Empty the distribution variables $dist_count = 0; $dist_out = 0; @os_avail = (); } } sub final { my $e = shift; print "Total software packages: $total_count\n"; print "Total software packages available: ".($total_count -$total_ou +t)."\n"; print "Total cost for $total_count pieces of software: $total_cost\n +"; }

The following is the input file:

<?xml version="1.0"?> <software_inventory> <package name="Dreamweaver" version="4"> <operating_system name="Microsoft Windows"> <licenses_purchased>15</licenses_purchased> <licenses_in_use>8</licenses_in_use> </operating_system> <operating_system name="Apple Mac OS"> <licenses_purchased>10</licenses_purchased> <licenses_in_use>2</licenses_in_use> </operating_system> <price>299.99</price> </package> <package name="Microsoft Visual C++ Enterprise Edition" version="6" +> <operating_system name="Microsoft Windows"> <licenses_purchased>15</licenses_purchased> <licenses_in_use>8</licenses_in_use> </operating_system> <price>1299.00</price> </package> <package name="XML Spy" version="4.2"> <operating_system name="Microsoft Windows"> <licenses_purchased>15</licenses_purchased> <licenses_in_use>8</licenses_in_use> </operating_system> <price>399.00</price> </package> <package name="Borland JBuilder Enterprise" version="6"> <operating_system name="Microsoft Windows"> <licenses_purchased>15</licenses_purchased> <licenses_in_use>8</licenses_in_use> </operating_system> <operating_system name="Apple Mac OS"> <licenses_purchased>10</licenses_purchased> <licenses_in_use>2</licenses_in_use> </operating_system> <operating_system name="Linux"> <licenses_purchased>10</licenses_purchased> <licenses_in_use>2</licenses_in_use> </operating_system> <operating_system name="Solaris Sparc"> <licenses_purchased>10</licenses_purchased> <licenses_in_use>2</licenses_in_use> </operating_system> <price>2999.00</price> </package> </software_inventory>

I am expecting this kind of output (from the book itself):

***** Software Inventory Report ***** --------------------------------------------------- *Dreamweaver (version 4)* Packages Purchased: 25 Packages Available: 15 Cost (299.99 per piece): $7499.75 ---------------------------------------------------- *Microsoft Visual C++ Enterprise Edition (version 6)* Packages Purchased: 15 Packages Available: 7 Cost (1299.00 per piece): $19485 ---------------------------------------------------- *XML Spy (version 4.2)* Packages Purchased: 15 Packages Available: 7 Cost (399.00 per piece): $5985 ---------------------------------------------------- *Borland JBuilder Enterprise (version 6)* Packages Purchased: 45 Packages Available: 31 Cost (2999.00 per piece): $134955 ---------------------------------------------------- Total software packages purchased: 100 Total software packages available: 60 Total cost for 100 software packages: 4996.99

But instead I got this:

***** Software Inventory Report ***** ------------------------------------- Total software packages: Total software packages available: 0 Total cost for pieces of software: 4996.99

Where did it go wrong? How come the output is not the same as expected? Please kindly show me some light ;) Thank you in advance.

Replies are listed 'Best First'.
Re: XML::Parser SAX in Perl -> the handlers are not getting called
by toolic (Bishop) on Jan 31, 2011 at 14:52 UTC
    use strict and warnings
    ***** Software Inventory Report ***** ------------------------------------- Use of uninitialized value $total_count in concatenation (.) or string + at Total software packages: Use of uninitialized value $total_out in subtraction (-) Use of uninitialized value $total_count in subtraction (-) Total software packages available: 0 Use of uninitialized value $total_count in concatenation (.) or string + at Total cost for pieces of software: 4996.99
    Start your debugging by eliminating those warning messages.

    Better yet... promote your warnings to errors:

    use warnings FATAL => 'all';

    Update: those warnings occur because you did not initialize those variables before you parse your XML file. Move the parsefile line after the variable declarations/initializations.

      Yes I realize it now. Thank you, toolic.
Re: XML::Parser SAX in Perl -> the handlers are not getting called
by PeterPeiGuo (Hermit) on Jan 31, 2011 at 14:52 UTC

    Some tags, for example total and out, they never showed in the XML document.

    Peter (Guo) Pei

      Hi Peter Thank you :)