lib/geokit/geocoders.rb in andre-geokit-1.2.3 vs lib/geokit/geocoders.rb in andre-geokit-1.2.4

- old
+ new

@@ -218,11 +218,10 @@ def self.add_ampersand(url) url && url.length > 0 ? "&" : "" end end - # Geocoder Us geocoder implementation. Requires the Geokit::Geocoders::GEOCODER_US variable to # contain true or false based upon whether authentication is to occur. Conforms to the # interface set by the Geocoder class. class UsGeocoder < Geocoder @@ -395,43 +394,61 @@ def self.xml2GeoLoc(xml) doc=REXML::Document.new(xml) if doc.elements['//kml/Response/Status/code'].text == '200' - res = GeoLoc.new - coordinates=doc.elements['//coordinates'].text.to_s.split(',') - - #basics - res.lat=coordinates[1] - res.lng=coordinates[0] - res.country_code=doc.elements['//CountryNameCode'].text if doc.elements['//CountryNameCode'] - res.provider='google' - - #extended -- false if not not available - res.city = doc.elements['//LocalityName'].text if doc.elements['//LocalityName'] - res.state = doc.elements['//AdministrativeAreaName'].text if doc.elements['//AdministrativeAreaName'] - res.full_address = doc.elements['//address'].text if doc.elements['//address'] # google provides it - res.zip = doc.elements['//PostalCodeNumber'].text if doc.elements['//PostalCodeNumber'] - res.street_address = doc.elements['//ThoroughfareName'].text if doc.elements['//ThoroughfareName'] - # Translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country - # For Google, 1=low accuracy, 8=high accuracy - # old way -- address_details=doc.elements['//AddressDetails','urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'] - address_details=doc.elements['//*[local-name() = "AddressDetails"]'] - accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0 - res.precision=%w{unknown country state state city zip zip+4 street address}[accuracy] - res.success=true - - return res + geoloc = nil + # Google can return multiple results as //Placemark elements. + # iterate through each and extract each placemark as a geoloc + doc.each_element('//Placemark') do |e| + extracted_geoloc = extract_placemark(e) # g is now an instance of Geoloc + if geoloc.nil? + # first time through, geoloc is still nill, so we make it the geoloc we just extracted + geoloc = extracted_geoloc + else + # second (and subsequent) iterations, we push additional + # geolocs onto "geoloc.all" + geoloc.all.push(extracted_geoloc) + end + end + return geoloc else logger.info "Google was unable to geocode address: "+address return GeoLoc.new end rescue logger.error "Caught an error during Google geocoding call: "+$! return GeoLoc.new end + + # extracts a single geoloc from a //placemark element in the google results xml + def self.extract_placemark(doc) + res = GeoLoc.new + coordinates=doc.elements['.//coordinates'].text.to_s.split(',') + + #basics + res.lat=coordinates[1] + res.lng=coordinates[0] + res.country_code=doc.elements['.//CountryNameCode'].text if doc.elements['.//CountryNameCode'] + res.provider='google' + + #extended -- false if not not available + res.city = doc.elements['.//LocalityName'].text if doc.elements['.//LocalityName'] + res.state = doc.elements['.//AdministrativeAreaName'].text if doc.elements['.//AdministrativeAreaName'] + res.full_address = doc.elements['.//address'].text if doc.elements['.//address'] # google provides it + res.zip = doc.elements['.//PostalCodeNumber'].text if doc.elements['.//PostalCodeNumber'] + res.street_address = doc.elements['.//ThoroughfareName'].text if doc.elements['.//ThoroughfareName'] + # Translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country + # For Google, 1=low accuracy, 8=high accuracy + address_details=doc.elements['.//*[local-name() = "AddressDetails"]'] + accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0 + res.precision=%w{unknown country state state city zip zip+4 street address building}[accuracy] + res.success=true + + return res + end end # ------------------------------------------------------------------------------------------- # IP Geocoders @@ -473,10 +490,11 @@ # Given an IP address, returns a GeoLoc instance which contains latitude, # longitude, city, and country code. Sets the success attribute to false if the ip # parameter does not match an ip address. def self.do_geocode(ip) + return Geoloc.new if '0.0.0.0' == ip return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip) url = "http://api.hostip.info/get_html.php?ip=#{ip}&position=true" response = self.call_geocoder_service(url) response.is_a?(Net::HTTPSuccess) ? parse_body(response.body) : GeoLoc.new rescue @@ -503,10 +521,10 @@ res.country_code.chop! res.success = !(res.city =~ /\(.+\)/) res end end - + # ------------------------------------------------------------------------------------------- # The Multi Geocoder # ------------------------------------------------------------------------------------------- # Provides methods to geocode with a variety of geocoding service providers, plus failover