<?php
detour@metalshell.comhttp://www.metalshell.com/
define('STATION_LIST_STATE', 'FL');
define('WEATHER_STATION', 'http://weather.gov/xml/current_obs/KRSW.xml');
try {
$weather = new weather();
echo "Getting weather stations for " . STATION_LIST_STATE . "\n---------------------\n";
$weather->show_weather_stations(STATION_LIST_STATE);
$station_obs = $weather->get_weather_data(WEATHER_STATION);
echo "\n\nGetting current weather observations\n---------------------\n";
foreach($station_obs as $k=>$v) {
echo "$k = $v\n";
}
} catch (Exception $e) {
echo "Error thrown: " . $e->getMessage();
}
class weather {
private $xml_parser, $state, $current_element, $element_depth = 0;
private $matched_stations = array(), $station_details = array();
private $station_obs = array(), $parent_elements = array();
private function start_element($parser, $name, $attribs) {
$this->current_element = $name;
$this->element_depth++;
$this->parent_elements[$this->element_depth] = $name;
}
private function end_element($parser, $name) {
$this->current_element = '';
$this->element_depth--;
}
private function station_parse($parser, $data) {
if($this->current_element) {
$parent_el = strtolower($this->parent_elements[$this->element_depth-1]);
if($parent_el == 'station') {
$this->station_details[$this->current_element] = $data;
} else if($parent_el == 'wx_station_index' && count($this->station_details)) {
$this->matched_stations[] = $this->station_details;
}
}
}
function __construct() {
}
function __destruct() {
if(is_resource($this->xml_parser)) xml_parser_free($this->xml_parser);
}
private function create_parser() {
if(is_resource($this->xml_parser)) xml_parser_free($this->xml_parser);
$this->xml_parser = xml_parser_create();
xml_set_object($this->xml_parser, $this);
}
public function get_weather_data($station_url) {
$this->create_parser();
xml_set_element_handler($this->xml_parser, "start_element", "end_element");
xml_set_character_data_handler($this->xml_parser, "current_obs_data");
$this->start_xml_parse($this->dl_xml($station_url));
return $this->station_obs;
}
private function current_obs_data($parser, $data) {
if($this->current_element) {
$parent_el = strtolower($this->parent_elements[$this->element_depth-1]);
if($parent_el == 'current_observation' && $this->current_element != 'IMAGE') {
$this->station_obs[$this->current_element] = $data;
}
}
}
public function show_weather_stations($state) {
if(strlen($state) != 2) throw new Exception("State should be 2 letter abbreviation. i.e. FL, CA");
$this->state = $state;
$this->create_parser();
xml_set_element_handler($this->xml_parser, "start_element", "end_element");
xml_set_character_data_handler($this->xml_parser, "station_parse");
$this->start_xml_parse($this->dl_xml('http://www.weather.gov/xml/current_obs/index.xml'));
if(count($this->matched_stations)) {
foreach($this->matched_stations as $k=>$detail) {
if(strtolower($detail["STATE"]) == strtolower($this->state)) {
echo "{$this->state} Station: {$detail["STATION_ID"]} ({$detail["STATION_NAME"]}) {$detail["XML_URL"]}\n";
}
}
} else {
throw new Exception("Unable to retrieve station list.");
}
}
private function start_xml_parse($data) {
if(!xml_parse($this->xml_parser, $data, true))
throw new Exception(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->xml_parser)),
xml_get_current_line_number($this->xml_parser)));
}
public function dl_xml($url) {
$buf = '';
$fd = fopen($url, "r");
if(!$fd) throw new Exception("Unable to open '$url'");
while(!feof($fd)) {
$buf .= fgets($fd, 4096);
}
fclose($fd);
return $buf;
}
}