Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Problem with a Ref to a global variable while using XML::Parser

by beamsack (Scribe)
on May 28, 2002 at 21:28 UTC ( #169918=perlquestion: print w/replies, xml ) Need Help??
beamsack has asked for the wisdom of the Perl Monks concerning the following question:

I am new to Perl and attempting to parse XML into an array of hashes using XML::Parser.
The script parses each child element of a <story> element into a hash. A reference to the hash is pushed on an array. When printing out the array of hashes, only the values from the last element parsed are displayed.
Overwriting the global hash is probably causing the problem.
I would like to either:
Create a lexically scoped hash variable but I am having difficulty due to the event driven XML::Parser subs (StartTag, EndTag, and Text)
Effectively deal with the global hash variable (by redefining it?)
thanks in advance monks -
use strict; use XML::Parser; use LWP::Simple; my @curr; my @stories; # global hash my %story; my $xml = get(""); die "Failed to obtain xml " unless defined($xml); my $p = XML::Parser->new(Style => 'Stream'); $p->parse($xml); # print out the results foreach my $hashref (@stories) { print "$hashref->{title}\n"; } # StartTag - called when the start of an XML tag is found sub StartTag { my($p, $tag) = @_; push @curr, $tag; } # EndTag - called when the end of a XML tag is seen sub EndTag { my($p, $tag) = @_; # pushes the hash ref onto the array if ($tag eq 'story') { push @stories, \%story; } pop @curr; } # Text - called when text data is encountered sub Text { unless ($curr[-1] eq 'story') { $story{$curr[-1]} = $_; } }
Example of a story element
<story> <title>Debian And WineX</title> <url></url> <time>2002-05-28 18:25:01</time> <author>Hemos</author> ... </story>

Replies are listed 'Best First'.
Re: Problem with a Ref to a global variable while using XML::Parser
by clintp (Curate) on May 28, 2002 at 23:50 UTC
    I think you answered your own question (Effectively deal with the global hash variable (by redefining it?)). Can't you just let the last thing on @stories be the hash reference and not even deal with the hash?
    sub StartTag { # Other stuff okay... but add.. if ($tag eq 'story') { push @stories, {}; } } # This subroutine is mostly superflous now I think... sub EndTag { pop @curr; } sub Text { unless ($curr[-1] eq 'story') { $stories[-1]->{$curr[-1]} = $_; } }
    And that might do it. (untested)
      And that did it clintp!
      The script now works as expected.
      And thanks to crazyinsomniac for the recommendations.
(crazyinsomniac: perlref) Re: Problem with a Ref to a global variable while using XML::Parser
by crazyinsomniac (Prior) on May 29, 2002 at 00:24 UTC
    First, I reccomend you sit down and read perldata,perlref, and skim through perllol and perldsc, and then consider this piece of code
    #!/usr/bin/perl -w use strict; $\="\n"; my %jar = qw( a b c d); my @ppp = ( \%jar ); print a => $jar{a}; print a => $ppp[0]->{a}; print c => $jar{c}; print c => $ppp[0]->{c}; $jar{a}='gork'; $jar{c}='gork'; push @ppp, \%jar; print a => $jar{a}; print a => $ppp[0]->{a}; print a => $ppp[1]->{a}; print c => $jar{c}; print c => $ppp[0]->{c}; print c => $ppp[1]->{c}; { my %jar = ( a => shark => c => shark => 1 => 2 ); push @ppp, \%jar; } print a => $jar{a}; print a => $ppp[0]->{a}; print a => $ppp[1]->{a}; print a => $ppp[2]->{a}; print c => $jar{c}; print c => $ppp[0]->{c}; print c => $ppp[1]->{c}; print c => $ppp[2]->{c};
    Basically, all you're pushing onto your array, is the same hashref over and over and over again, whose values you redefine, over and over and over and over again.

    Now your hash is not a global, even though you kind of treat it as such (globals live in the package namespace, they aren't declared with my, they're declared with use vars '%global', or our(%global), or %package::name::global).

    Before you push @stories, \%story, you could simply create a new hash, and push it's reference onto @stories. Example

    use strict; $\="\n"; my %f = 1..4; print \%f; my %b = %f; print \%b; print they => are => not => equal => chr(33) if \%b ne \%f ;

    Of all the things I've lost, I miss my mind the most.
    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://169918]
Approved by Zaxo
[Corion]: Meh. I think I have now the parts down that I want from a simple Javascript frontend for single-page- applications with a aPerl backend. But it seems that all Javascript templating modules either don't support two-way binding (which would be nice) or ...
[Corion]: ... don't support server-side precompilation (which means the client has to compile all templates to Javascript themselves), or are giant frameworks that expect to do everything (which is not what I want)
[Corion]: I feel that there is a talk somewhere in there, either about the structure and parts, or how I used several parts to get a complete whole.
[Corion]: Maybe I can still find something that is compatible with handlebars.js (which has JS precompilation) but allows for two-way data binding (which is great for the UI)

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2017-03-30 07:50 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (355 votes). Check out past polls.