Code covered by the BSD License  

Highlights from
Yahoo Weather - GUI

image thumbnail
from Yahoo Weather - GUI by Aravind Seshadri
A GUI to get the latest weather information (Based on yweather() by A. Belani)

yweather(location,unit)
function [data,err] = yweather(location,unit)

%YWEATHER Get location specific weather data from Yahoo! Weather.
%
% YWEATHER(LOCATION) queries the Yahoo! Weather RSS feed for the specified
% location, and returns a struct containing the queried information.
%
% LOCATION can be a (U.S.) ZIP Code or a Location ID, and it must be a
% string. To determine Location ID(s), visit http://weather.yahoo.com/ and
% browse or search for the relevant location(s).
%
% The second argument UNIT is optional, and can be either 'f' for
% English or 'c' for metric units. Yahoo! Weather's default value for UNIT 
% is 'f'.
%
% For more information about the RSS feeds and the data contained within
% them, visit http://developer.yahoo.com/weather/.
%
% Data is acquired in XML format, after which it is converted into a struct
% using the xml_parse function. This function is available in the XML
% Toolbox by Marc Molinari on the MATLAB Central File Exchange (File ID 
% 4278). The URL to it is:
%   http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=4278&objectType=file
%
% EXAMPLES:
%
%   Example 1: Using a ZIP Code.
%   yweather('10001') returns a 1x1 struct having fields (among others):
%
%           yweather_location.city: 'New York'
%     yweather_atmosphere.humidity: 50
%       yweather_astronomy.sunrise: '6:06 am'
%     item.yweather_condition.temp: 35
%     item.yweather_condition.date: 'Thu, 16 Mar 2006 2:51 am EST'
%
%   Example 2: Using a Location ID and (optional) unit.
%   yweather('UKXX0085','c') returns a 1x1 struct.
%
%   Example 3: Using a cell array of three locations.
%   cellfun(@yweather,{'90028';'14850';'CAXX0301'}) returns a 3x1 struct.
%
%   Example 4: Using a char array of two ZIP Codes.
%   cellfun(@yweather,cellstr(['56711';'33040'])) returns a 2x1 struct.
%
%   Example 5: Using a cell array of three locations, in degrees Celsius.
%   locations={'98381';'USCA0715';'04652'};
%   units=repmat({'c'},size(locations));
%   cellfun(@yweather,locations,units) returns a 3x1 struct.
%
% REMARKS:
%
%   - This function does not include any caching features, so conservative
%     use of the service, perhaps no more than once per hour
%     per location, is warranted. Refer to the corresponding
%     'ttl' field values and documentation.
%   - As the feed layout is updated by Yahoo! over time, the layout of
%     the output struct should automatically be correspondingly updated.
%     Unexpected changes to the feed may however prevent this function from
%     working predictably.
%   - This function has been tested with version 2005-04-20 of the XML
%     Toolbox.
%
% VERSION: 20060321
% MATLAB VERSION: 7.1.0.246 (R14) Service Pack 3
%
% See also URLREAD, REGEXP, REGEXPREP, CELLFUN, STRUCTFUN.

%{
VERSION HISTORY:
20060317: - Original version by A. Belani
http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=10414&objectType=file

20060321: - Modified slightly to be used with a GUI.

KEYWORDS:
atmosphere, climate, meteorology, temperature, weather, yahoo
%}

%--------------------------------------------------------------------------

%% Declare URL and parameters
% Error handling flag
err = 0; % If this flag stays zero then no error exists.

%Declare url
url='http://xml.weather.yahoo.com/forecastrss';

%Conditionally declare parameters
switch nargin
    case 1
        params={'p',location};
    case 2
        params={'p',location,'u',unit};
end
clear unit

%--------------------------------------------------------------------------

%% Resiliently read URL

tries_max=3;
wait_time_base=.75;

for tries=1:tries_max;
    [data,status]=urlread(url,'get',params);
    if status==1
        break
    end
    if tries==tries_max
        err = 1; % This means that unable to connect to internet.
        return
    end
    pause(tries*wait_time_base)
end
clear tries* status wait_time_base ...
      url params

%--------------------------------------------------------------------------

%% Check for invalid returned data

if ~isempty(strfind(data,'<title>City not found</title>'))
    err = 2; % This mean the city is not found.
    return
end
clear location

%--------------------------------------------------------------------------

%% Convert yweather code to XML (for convenient parsing to struct)

expr='<yweather:(?<category>\w+) (?<keys_values>[^>]+)/>';
data=regexprep(data,expr,'<yweather:$1>$2</yweather:$1>');

expr='<yweather:\w+>(?<keys_values>[^>]+)</yweather:\w+>';
dc1=regexp(data,expr,'match');

expr='(?<key>\w+)="(?<value>[^"]+)" ';
dc2=regexprep(dc1,expr,'<$1>$2</$1>');

data=regexprep(data,dc1,dc2);
clear expr dc*

%--------------------------------------------------------------------------

%% Parse and store <description> CDATA value correctly

expr='<description><!\[CDATA\[(?<description>.+)]]></description>';
description=regexp(data,expr,'names','once');
clear expr
description=description.description;

%--------------------------------------------------------------------------

%% Preprocess XML for parsing

%Rename <item> tag to something else (<itemdata>) to prevent parsing error
data=regexprep(data,'<(?<slash>[/]?)item>','<$1itemdata>');

%Replace colon in relevant (yweather* and geo*) tags to underscore for
%compatibility with struct field naming conventions
expr='<(?<slash>[/]?)(?<tag_left_part>\w+):(?<tag_right_part>\w+)>';
data=regexprep(data,expr,'<$1$2_$3>');
clear expr

%Convert multiple <yweather_forecast> sets into a single set
data=regexprep(data,'</yweather_forecast>\n{1}<yweather_forecast>','');

%% Parse XML to struct

%Disable warning, and parse
wstate=warning('off','all');
data=xml_parse(data);
warning(wstate);
clear wstate

%--------------------------------------------------------------------------

%% Postprocess struct

%Simplify struct
data=data.channel;

%Rename <itemdata> back to <item> (in struct)
data.item=data.itemdata;
data=rmfield(data,'itemdata');

%Store previously parsed <description> CDATA value correctly in struct
data.item.description=description;
clear description

%--------------------------------------------------------------------------

%% Convert numbers from strings to doubles

% Comment this cell to prevent numbers from being converted to doubles

data=structfun(@cnsd,data,'UniformOutput',false);

%**************************************************************************

%% Subfunction to convert numbers from strings to doubles

function[field]=cnsd(field)

if ischar(field) && ~isnan(str2double(field))
    field=str2double(field);
elseif isstruct(field)
    for i=1:numel(field)
        field(i)=structfun(@cnsd,field(i),'UniformOutput',false);
    end
end

%**************************************************************************

Contact us at files@mathworks.com