Reputation: 199
Im a beginner to perl and i have a problem that I don't know how to solve. Im trying to fetch xml-data from a website and put the value of temperature in an array.
This is my code so far:
use strict;
use warnings;
# For parsing
use XML::Simple;
# For downloading
use LWP::Simple;
# For debug output
use Data::Dumper;
# Turn off output buffering
$|=1;
# Note, no error checking here!
sub main
{
print "\nDownloading ....";
my $data = get('http://www.yr.no/place/Norway/Telemark/Sauherad/Gvarv/forecast_hour_by_hour.xml');
my $parser = new XML::Simple;
print "\nParsing ...";
my $dom = $parser->XMLin($data);
print "\n\n";
# Debug output.
#print Dumper($dom->{'forecast'});
# Data structure is a hash containing one key, 'entry'.
# Get the hash value and cast to an array.
my @entries = $dom->{'forecast'}->{'tabular'}->{'time'};
# Go through each array 'entry' element.
foreach my $entry(@entries)
{
print Dumper($entry);
# Each element is a hash.
# The band name can be got from one hash key.
my $tabular = $entry->{'temperature'};
#print "$tabular\n";
print "\n\n";
}
}
main();
And the output that I get on my terminal is:
},
{
'temperature' => {
'unit' => 'celsius',
'value' => '26'
},
'windSpeed' => {
'name' => 'Light breeze',
'mps' => '1.9'
},
'to' => '2016-08-17T16:00:00',
'pressure' => {
'unit' => 'hPa',
'value' => '1014.1'
},
'from' => '2016-08-17T15:00:00',
'precipitation' => {
'value' => '0'
},
'symbol' => {
'numberEx' => '1',
'var' => '01d',
'number' => '1',
'name' => 'Clear sky'
},
'windDirection' => {
'name' => 'North',
'code' => 'N',
'deg' => '4.4'
}
},
{
'precipitation' => {
'value' => '0'
},
'from' => '2016-08-17T16:00:00',
'windDirection' => {
'name' => 'North-northeast',
'code' => 'NNE',
'deg' => '20.6'
},
'symbol' => {
'number' => '1',
'name' => 'Clear sky',
'var' => '01d',
'numberEx' => '1'
},
'temperature' => {
'unit' => 'celsius',
'value' => '27'
},
'pressure' => {
'value' => '1013.4',
'unit' => 'hPa'
},
'to' => '2016-08-17T17:00:00',
'windSpeed' => {
'mps' => '1.2',
'name' => 'Light air'
}
},
{
'symbol' => {
'numberEx' => '1',
'var' => '01d',
'name' => 'Clear sky',
'number' => '1'
},
'windDirection' => {
'name' => 'East',
'code' => 'E',
'deg' => '83.0'
},
'from' => '2016-08-17T17:00:00',
'precipitation' => {
'value' => '0'
},
'windSpeed' => {
'mps' => '0.7',
'name' => 'Light air'
},
'pressure' => {
'unit' => 'hPa',
'value' => '1012.8'
},
'to' => '2016-08-17T18:00:00',
'temperature' => {
'unit' => 'celsius',
'value' => '27'
}
}
];
Not a HASH reference at script.pl line 43.
Why do I get this error and how can i fetch the values of temperature? Thanks in advance!
Upvotes: 2
Views: 1820
Reputation: 53478
Much easier than you think - I will suggest XML::Twig
, because I think it has an easier learning curve:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use LWP::Simple;
my $twig = XML::Twig -> parse ( get('http://www.yr.no/place/Norway/Telemark/Sauherad/Gvarv/forecast_hour_by_hour.xml') );
#print the first temperature value:
print $twig -> get_xpath('//temperature',0 ) -> att('value'),"\n";
# all the temps in an array:
use Data::Dumper;
my @temps = map { $_ -> att('value') } $twig -> get_xpath('//temperature');
print Dumper \@temps;
here we make use of an xpath
search - which is a bit like a regular expression for XML. //
denotes "anywhere in the tree" so is effectively a search for "temperature" nodes. (Which seems to work with your XML, but you might want a more specific path in other scenarios).
Upvotes: 2
Reputation: 241738
XML::Simple tells you not to use it. Follow its advice.
Here's how to extract temperature using XML::LibXML:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use XML::LibXML;
my $dom = 'XML::LibXML'->load_xml(
location => 'http://www.yr.no/place/Norway/Telemark/Sauherad/Gvarv/forecast_hour_by_hour.xml');
for my $temperature ($dom->findnodes('//temperature/@value')) {
say $temperature->getValue;
}
With xsh, which is a wrapper around XML::LibXML, you can just write
open http://www.yr.no/place/Norway/Telemark/Sauherad/Gvarv/forecast_hour_by_hour.xml ;
for //temperature echo @value ;
Upvotes: 4