Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Can't call method "getAttribute"

by Squeakers (Initiate)
on Jul 20, 2009 at 02:10 UTC ( [id://781506]=perlquestion: print w/replies, xml ) Need Help??

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

Hey guys/gals, noob here. I have a problem and the peps at CodingForums.com suggested I try here. I didnt write this script but i am trying to get it to work.

I run the script and it returns: Can't call method getAttribute on an undefined value at line 114

Here is a link to the discussion on codingforums, not sure if it will help.

http://www.codingforums.com/showthread.php?t=171916

They mentioned that possible one of the modules wasnt working correctly. I am not a programmer and I am in need of help.

Thanks to all that contribute.

Here is the complete code:

#!/usr/bin/perl ################################################################# # Yahoo Weather Rss Information Atomizer # Version 0.7.1 # Loud-Soft.com # Provided As Is ################################################################# use strict; use XML::XPath; use LWP::Simple; use XML::XPath::XMLParser; use Getopt::Long; use File::Copy; ################################################################# # Variables ################################################################# # Constants (Change these to localize) my $zipcode = "60642"; my $unit = "F"; my $scripthome = "/Library/prlprograms/yweather.pl"; my $icondir = $scripthome."images/"; my $datadir = $scripthome."data/"; my $datafile = $datadir."weather.xml"; my $imagefile = $icondir."weather.png"; # Constants (Do not change these) my $pre="yweather"; my $uri="http://xml.weather.yahoo.com/ns/rss/1.0"; my $url="http://xml.weather.yahoo.com/forecastrss?p=$zipcode&u=$unit"; my %data; my $xp; ################################################################# # Subroutines ################################################################# # Print usage sub usage { print "Yahoo Weather Information\n\n"; print "Usage:\n"; print " ./yweather.pl -ct Displays current temperature\n\n"; print "Arguments: \n"; print " -lc City \n"; print " -lr Region\n"; print " -lt Country\n"; print " -cc Weather Code (used for images)\n"; print " -ct Current Temperature\n"; print " -cw Current Weather Description\n"; print " -cd Current Date\n"; print " -ah Current Humidity\n"; print " -av Current Visibilty\n"; print " -ap Current Barometric Pressure\n"; print " -ar Change in Barometric Pressure\n"; print " -sr Time of Sunrise\n"; print " -ss Time of Sunset\n"; print " -wc Current Wind Chill\n"; print " -wd Current Wind Direction\n"; print " -ws Current Wind Speed\n"; print " -ut Temperature Unit\n"; print " -ud Distance Unit\n"; print " -up Pressure Unit \n"; print " -us Speed Unit\n"; print " -fd1 Tomorrow's Day\n"; print " -fg1 Tomorrow's Date\n"; print " -fl1 Tomorrow's Low Temp\n"; print " -fh1 Tomorrow's High Temp\n"; print " -ft1 Tomorrow's Description\n"; print " -fc1 Tomorrow's Weather Code\n"; print " -fd2 Day After Tomorrow's Day\n"; print " -fg2 Day After Tomorrow's Date\n"; print " -fl2 Day After Tomorrow's Low Temp\n"; print " -fh2 Day After Tomorrow's High Temp\n"; print " -ft2 Day After Tomorrow's Description\n"; print " -fc2 Day After Tomorrow's Weather Code\n"; print " --copyimage Copy Appropriate Image to Current Image\n"; print " --update Update xml source file\n" ; print " \n"; print "All data is returned without units. To get data with units,\n"; print "use a combination of commands.\n\n"; print "Example: (Displays Current temperature with unit)\n"; print " ./yweather.pl -ct && ./yweather.pl -ut\n"; } # Print data sub args{ my ($arg) = @_; print $data{$arg} . "\n"; } # Subroutine to update xml data from yahoo sub update_weather { LWP::Simple::getstore($url,$datafile); } # Subroutine to download images from yahoo sub get_images { my $imgurl = "http://l.yimg.com/a/i/us/nws/weather/gr/"; for (0..47) { LWP::Simple::getstore($imgurl.$_."d.png",$icondir.$_."d.png"); LWP::Simple::getstore($imgurl.$_."n.png",$icondir.$_."n.png"); } File::Copy::copy($icondir."0d.png", $imagefile); } # Parse XML sub get_data { my($element, $attribute, $index) = @_; if ($index){$index=1;} my $nodeset = $xp->find("//yweather:$element"); my $node = $nodeset->get_node($index); return $node->getAttribute($attribute); } # Copy correct image to the image define in $imagefile sub copy_image { my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); my $night = $data{'ss'}; my $morning = $data{'sr'}; # my $condition = $data{'cc'}; my $imagesub; if ($hour % 12){ if(($hour-12) < int(substr($night,0,1))){ $imagesub = "d"; }elsif(($minute) < int(substr($night,2,3))){ $imagesub = "d"; }else{ $imagesub = "n"; } } else { if(($hour) < int(substr($morning,0,1))){ $imagesub = "n"; }elsif(($minute) < int(substr($morning,2,3))){ $imagesub = "n"; }else{ $imagesub = "d"; } } File::Copy::copy($icondir.$data{'cc'}.$imagesub.".png", $imagefile) or die "File ".$icondir.$data{'cc'}.$imagesub.".png"." cannot be copie +d. ".$data{'lr'}; } ################################################################# # Check that files exist ################################################################# #ensure directories exist unless(-d $datadir){ mkdir $datadir; } unless(-d $icondir){ mkdir $icondir; } # Check if weather.xml exists if (!(-e $datafile)){update_weather()} $xp = XML::XPath->new(filename => $datafile); $xp->set_namespace($pre, $uri); # Check if images exist if (!(-e $icondir."0d.png")){get_images()} # Check if image exist if (!(-e $imagefile)){copy_image()} ################################################################# # Data Setup ################################################################# # Location Information $data{'lc'} = get_data("location","city"); $data{'lr'} = get_data("location","region"); $data{'lt'} = get_data("location","country"); # Current Weather Information $data{'cc'} = get_data("condition","code"); $data{'ct'} = get_data("condition","temp"); $data{'cw'} = get_data("condition","text"); $data{'cd'} = get_data("condition","date"); # Current Atmosphere Information $data{'ah'} = get_data("atmosphere","humidity"); $data{'av'} = get_data("atmosphere","visibility"); $data{'ap'} = get_data("atmosphere","pressure"); $data{'ar'} = get_data("atmosphere","rising"); # Todays Sunrise and sunset $data{'sr'} = get_data("astronomy","sunrise"); $data{'ss'} = get_data("astronomy","sunset"); # Current wind information $data{'wc'} = get_data("wind","chill"); $data{'wd'} = get_data("wind","direction"); $data{'ws'} = get_data("wind","speed"); # Unit information $data{'ut'} = get_data("units","temperature"); $data{'ud'} = get_data("units","distance"); $data{'up'} = get_data("units","pressure"); $data{'us'} = get_data("units","speed"); # Forecast (Tomorrow) $data{'fd1'} = get_data("forecast[1]","day"); $data{'fg1'} = get_data("forecast[1]","date"); $data{'fl1'} = get_data("forecast[1]","low"); $data{'fh1'} = get_data("forecast[1]","high"); $data{'ft1'} = get_data("forecast[1]","text"); $data{'fc1'} = get_data("forecast[1]","code"); # Forecast (Day after tomorrow) $data{'fd2'} = get_data("forecast[2]","day"); $data{'fg2'} = get_data("forecast[2]","date"); $data{'fl2'} = get_data("forecast[2]","low"); $data{'fh2'} = get_data("forecast[2]","high"); $data{'ft2'} = get_data("forecast[2]","text"); $data{'fc2'} = get_data("forecast[2]","code"); ################################################################# # Parse arguments ################################################################# if(($#ARGV + 1) == 1){ my $arg = substr($ARGV[0],1); if ($data{$arg}){ args($arg); } elsif($arg eq "-update"){ update_weather(); } elsif($arg eq "-copyimage"){ copy_image(); } else { usage(); } } else { usage(); }

Replies are listed 'Best First'.
Re: Can't call method "getAttribute"
by kyle (Abbot) on Jul 20, 2009 at 02:40 UTC

    The only place I see "getAttribute" is in this sub:

    sub get_data { my($element, $attribute, $index) = @_; if ($index){$index=1;} my $nodeset = $xp->find("//yweather:$element"); my $node = $nodeset->get_node($index); return $node->getAttribute($attribute); }

    The error message means that $node is undef at this point. That means that undef was returned from $nodeset->get_node($index). I see a lot of calls to this sub, but in every case, there's no $index passed. According to the code that's there, that makes $index undef also. That's what I can see without running it.

    My guess is that the bit that says "if ($index){$index=1;}" should actually say "if (!$index){$index=1;}" (note the exclamation point). That's just a guess.

    To really find out what's going on, I'd recommend running this under the Perl debugger. See perldebug for the gory details.

      I changed the code according to your recomendations and still get the same error. I tried running the perldebug and this is beyond my noob capabilities. If you could give me a brief of what your looking for and how to get it, i will provide. Thanks
Re: Can't call method "getAttribute"
by GrandFather (Saint) on Jul 20, 2009 at 02:45 UTC

    I would guess that the feed that the script uses to obtain weather information from has changed its layout or has ceased to exist since the script was written. There is nothing in the script that performs any much error checking so when things go pear shaped you don't get much that's helpful.


    True laziness is hard work
      This was a thought I had, and searching for yahoo weather rss feed i came up with a different url

      http://weather.yahooapis.com/forecastrss

      but i wasnt sure how to incorporate this into the code since the code seems to have 2 different urls

        I could be wrong here correct me if I am wrong. I tried to fetch the URL in the code with the variable replaced as in the code. i.e. (zipcode=60642 and unit=F) http://xml.weather.yahoo.com/forecastrss?p=60642&u=F
        I got following
        <rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss +/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"> <channel> <title>Yahoo! Weather - Error</title> <description>Yahoo! Weather Error</description> <item> <title>City not found</title> <description> Invalid Input /forecastrss?p=60642&amp;u=F</description> </item> </channel> </rss><!-- api2.weather.ac4.yahoo.com compressed/chunked Sun Jul 19 22 +:10:00 PDT 2009 -->
        I tied the same for other zipcode (60641) and got following
        <rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss +/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"> <channel> <title>Yahoo! Weather - Chicago, IL</title> <link>http://us.rd.yahoo.com/dailynews/rss/weather/Chicago__IL/*http:/ +/weather.yahoo.com/forecast/USIL0225_f.html</link> <description>Yahoo! Weather for Chicago, IL</description> <language>en-us</language> <lastBuildDate>Sun, 19 Jul 2009 11:51 pm CDT</lastBuildDate> <ttl>60</ttl> <yweather:location city="Chicago" region="IL" country="US"/> <yweather:units temperature="F" distance="mi" pressure="in" speed="mph +"/> <yweather:wind chill="64" direction="0" speed="0" /> <yweather:atmosphere humidity="70" visibility="10" pressure="30.13" ri +sing="0" /> <yweather:astronomy sunrise="5:32 am" sunset="8:21 pm"/> <image> <title>Yahoo! Weather</title> <width>142</width> <height>18</height> <link>http://weather.yahoo.com</link> <url>http://l.yimg.com/a/i/us/nws/th/main_142b.gif</url> </image> <item> <title>Conditions for Chicago, IL at 11:51 pm CDT</title> <geo:lat>41.84</geo:lat> <geo:long>-87.68</geo:long> <link>http://us.rd.yahoo.com/dailynews/rss/weather/Chicago__IL/*http:/ +/weather.yahoo.com/forecast/USIL0225_f.html</link> <pubDate>Sun, 19 Jul 2009 11:51 pm CDT</pubDate> <yweather:condition text="Partly Cloudy" code="29" temp="64" date="Sun +, 19 Jul 2009 11:51 pm CDT" /> <description><![CDATA[ ><img src="http://l.yimg.com/a/i/us/we/52/29.gif"/><br /> <b>Current Conditions:</b><br /> Partly Cloudy, 64 F<BR /> <BR /><b>Forecast:</b><BR /> Sun - Partly Cloudy. High: 71 Low: 54<br /> Mon - Sunny. High: 78 Low: 62<br /> <br /> <a href="http://us.rd.yahoo.com/dailynews/rss/weather/Chicago__IL/*htt +p://weather.yahoo.com/forecast/USIL0225_f.html">Full Forecast at Yaho +o! Weather</a><BR/><BR/> (provided by <a href="http://www.weather.com" >The Weather Channel</a> +)<br/> ]]></description> <yweather:forecast day="Sun" date="19 Jul 2009" low="54" high="71" tex +t="Partly Cloudy" code="29" /> <yweather:forecast day="Mon" date="20 Jul 2009" low="62" high="78" tex +t="Sunny" code="32" /> <guid isPermaLink="false">USIL0225_2009_07_19_23_51_CDT</guid> </item> </channel> </rss><!-- api2.weather.ac4.yahoo.com compressed/chunked Sun Jul 19 22 +:30:42 PDT 2009 -->
        If am not missing anything here the possible reason for the error is that yahoo is not returning any data for zip=60642 and there is no code to handle this condition therefore "$nodeset->get_node($index);" returns a undef value.
        I tried the same with "http://weather.yahooapis.com/forecastrss" and got the same results (no data for 60642), therefore I don't think changing URL will help. What you need is to handle the condition in the code.
        Regards,
        Ashish
Re: Can't call method "getAttribute"
by jbt (Chaplain) on Jul 20, 2009 at 02:39 UTC
    You probably want to download the newer version at http://code.google.com/p/yweather/

    I was able to get the script working by changing line 24 to:

    my $scripthome = "/home/jim/yweather-dir/";
    create the "yweather-dir" and execute the command:

    yweather.pl -ct && ./yweather.pl -ut
      followed your advise, still get the same error, still no sure of how to execute the command you listed
      again, noob, sorry. You created a folder named yweather-dir?

      and what do you mean by execute the command?

      also i believe that i do have the lastest version 0.7.8

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://781506]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-19 01:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found