00001
00002 #TODO In its infinite wisdom, the XML the NWS gives us (NWS-Satations.xml) is
00003 # not consistent wrt to lat lon. Some are in a +/- format, others in [NSEW]
00004 # format, also, some aren't even listed. It seems unlikely that the NWS doesn't
00005 # know that location of some of its weather stations and in fact they are on
00006 # their website, so maybe write a script to grab missing ones and massage them
00007 # all to a consistent format.
00008
00009 package NWSLocation;
00010 use strict;
00011 require Exporter;
00012 use base qw(XML::SAX::Base);
00013 use XML::Parser;
00014 use Data::Dumper;
00015
00016 our @ISA = qw(Exporter);
00017 our @EXPORT = qw(doSearch AddLatLonSearch AddStationIdSearch AddLocSearch);
00018 our $VERSION = 0.1;
00019
00020 my @latlonsearches;
00021 my @stationidsearches;
00022 my @locstrsearches;
00023 my @statesearches;
00024 my %currStation;
00025 my $searchresults;
00026
00027 sub doSearch {
00028
00029 my $parser = new XML::Parser( Style => 'Stream' );
00030 open(XML, 'NWS-Stations.xml') or die "cannot open file\n";
00031 $parser->parse(*XML);
00032 close(XML);
00033 return $searchresults;
00034 }
00035
00036 sub StartDocument {
00037 my $expat = shift;
00038
00039 $expat->{finish} = 0;
00040
00041 }
00042
00043 sub StartTag {
00044 my ($expat, $name, %atts) = @_;
00045
00046 if ($name eq 'station') {
00047 $expat->{CurrEntry} = {};
00048 $expat->{MatchFound} = 0;
00049 }
00050 }
00051
00052 sub Text {
00053
00054 my $expat = shift;
00055 my $text = $expat->{Text};
00056 my $search;
00057
00058 if ($expat->in_element('station_id')) {
00059 $expat->{CurrEntry}->{station_id} = $text;
00060 if (!$expat->{MatchFound}) {
00061 foreach $search (@stationidsearches) {
00062 if ($text =~ m/$search/i) {
00063 $expat->{MatchFound} = 1;
00064 return;
00065 }
00066 }
00067 }
00068 }
00069
00070 if ($expat->in_element('state')) {
00071 $expat->{CurrEntry}->{state} = $text;
00072 if (!$expat->{MatchFound}) {
00073 foreach $search (@statesearches) {
00074 if ($text =~ m/$search/i) {
00075 $expat->{MatchFound} = 1;
00076 return;
00077 }
00078 }
00079 }
00080 }
00081
00082 if ($expat->in_element('station_name')) {
00083 $expat->{CurrEntry}->{station_name} = $text;
00084 if (!$expat->{MatchFound}) {
00085 foreach $search (@locstrsearches) {
00086 if ($text =~ m/$search/i) {
00087 $expat->{MatchFound} = 1;
00088 return;
00089 }
00090 }
00091 }
00092 }
00093
00094 # annoyingly, the lat/lon format is not consistent in the XML file,
00095 # sometimes its in +/- format, other times N/S E/W, so we convert it right
00096 # off to be unifrom in +/-
00097 if ($expat->in_element('latitude')){
00098 $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[N]/+$1/ or
00099 $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[S]/-$1/;
00100 $expat->{CurrEntry}->{latitude} = $text;
00101 $expat->{currLat} = $text;
00102 return;
00103 }
00104
00105 if ($expat->in_element('longitude')) {
00106 $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[E]/+$1/ or
00107 $text =~ s/(\d{1,3}([.]\d{1,3})?)([.]\d{1,3})?[W]/-$1/;
00108 $expat->{CurrEntry}->{longitude} = $text;
00109 if (!$expat->{MatchFound}) {
00110 foreach $search (@latlonsearches) {
00111 if ($search->[0] eq $expat->{currLat} && $search->[1] eq $text) {
00112 $expat->{MatchFound} = 1;
00113 return;
00114 }
00115 }
00116 }
00117 }
00118 }
00119
00120 sub EndTag {
00121 my ($expat, $name) = @_;
00122
00123 if ($name eq 'station' && $expat->{MatchFound}) {
00124 push (@$searchresults, $expat->{CurrEntry});
00125 if ($expat->{finish}) {
00126 $expat->finish();
00127 return;
00128 }
00129 }
00130
00131 }
00132
00133 sub AddLatLonSearch {
00134 my ($lat, $lon) = @_;
00135 push (@latlonsearches, [$lat, $lon]);
00136 }
00137
00138 sub AddStationIdSearch {
00139 my $id = shift;
00140 push (@stationidsearches, $id);
00141 }
00142
00143 sub AddLocSearch {
00144 my $loc = shift;
00145 push (@locstrsearches, $loc);
00146 }
00147
00148 sub AddStateSearch {
00149 my $state = shift;
00150 push (@statesearches, $state);
00151 }
00152
00153 1;