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