Not to Hot for Mojo

I saw a post out in the Blogosphere today about getting weather info from NOAA (The United States National Weather Service). Oh! the horrors of using XML::LibXML or XML::DOM or those other hairy XML modules to get at the data.

The blogger didn't seem to keen on my quick and dirty Mojolicious solution:

$ perl -Mojo -E 'say g("")->dom("temp_f")->first->text'

I guess I was a bit too brief and off the point, so here's a nicer example:

NOAA provides an XML response that goes something like:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<?xml-stylesheet href="latest_ob.xsl" type="text/xsl"?>
<current_observation version="1.0"
        <credit>NOAA's National Weather Service</credit>
                <title>NOAA's National Weather Service</title>
        <suggested_pickup>15 minutes after the hour</suggested_pickup>
        <location>Burbank/Glendale, CA</location>
        <observation_time>Last Updated on Aug 11 2012, 1:53 am PDT</observation_time>
        <observation_time_rfc822>Sat, 11 Aug 2012 01:53:00 -0700</observation_time_rfc822>
        <temperature_string>76.0 F (24.4 C)</temperature_string>
        <wind_string>East at 3.5 MPH (3 KT)</wind_string>
        <pressure_string>1006.3 mb</pressure_string>
        <dewpoint_string>59.0 F (15.0 C)</dewpoint_string>

And Mojolicious has become my go-to tool for simple HTTP/HTML/XML/DOM/CSS voodoo. Here's a basic script to fetch the current temperature (°F):

#!/usr/bin/env perl
use strict;
use warnings;
use utf8::all;  # for °
use feature 'say';

use Mojolicious;

my $ua = Mojo::UserAgent->new;
my $dom = $ua->get('')->res->dom;
my $temp_f = $dom->find('current_observation temp_f:only-of-type')->first;
# or depending on how loose you want to play it.
#   $temp_f = $dom->find('temp_f')->[0]; 
say "It's currently ", $temp_f->text, "°F in Burbank.";
It's currently 76.0°F in Burbank.

That's just awesome, but wait, there's more. Mojolicious has the ojo module that imports a few handy functions like g() which does the whole Mojo::UserAgent->new->get()->res bit in one go. ojo makes it easy to do one-liners. How Perlish is that? And there's even a command line tool called mojo that makes things even easier:

$ mojo get temp_f 0 text

So do yourself a favor and check out Mojolicious, especially the Mojocasts. You'll probably stop using all those nasty XML modules unless you really have no other choice.


Oh! the horrors of using XML::LibXML or XML::DOM or those other hairy XML modules to get at the data.
Interesting article, but I think you're overstating the horror of the XML modules here. An XML::TreeBuilder equivalent is longer than your -Mojo example but should still be easy enough to follow:

perl -MLWP::Simple=get -MXML::TreeBuilder -E'my $xml = XML::TreeBuilder->new; $xml->parse(get ""); say "Temperature is " . $_->as_text . "°C" for $xml->look_down(_tag => "temp_c")'

Indeed. And for XML::LibXML...

perl -MXML::LibXML -E'say "Temperature is ", $_->textContent, "°C" for XML::LibXML->load_xml(location => "")->getElementsByTagName("temp_c")'

Leave a comment

About zengargoyle

user-pic I blog about Perl.