<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Out of my mind...: Geocoding, REXML and the Missing Method</title>
    <link>http://blog.fredjean.net/articles/2006/02/20/geocoding-rexml-and-the-missing-method</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Frederic Jean's Random Thoughts</description>
    <item>
      <title>Geocoding, REXML and the Missing Method</title>
      <description>&lt;a href="http://www.davisworld.org/"&gt;Scott Davis&lt;/a&gt; introduces the audience of his &lt;a href="http://www.davisworld.org/presentations/realWorldWebMapping.zip"&gt;Real World Mapping presentation&lt;/a&gt; to the &lt;a href="http://geocoder.us/"&gt;geocoder.us&lt;/a&gt; web site, which allows anyone to transform US based addresses to longitude and latitude coordinates. There are many options beyond the web based UI, including SOAP, XML-RPC, and RESTful web services. We will be using the RESTful RDF service for this demonstration.&lt;/p&gt;

&lt;p&gt;The first step is to find (and URL encode) an address. For this demonstration, we will be using "Mission &amp; Valencia Sts, San Francisco CA" as the address. You will see the following XML document if you point a browser at &lt;a href="http://rpc.geocoder.us/service/rest?address=Mission+%26+Valencia+Sts%2C+San+Francisco+CA"&gt;http://rpc.geocoder.us/service/rest?address=Mission+%26+Valencia+Sts%2C+San+Francisco+CA&lt;/a&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;table class="typocode_linenumber"&gt;&lt;tr&gt;&lt;td class="lineno"&gt;
&lt;pre&gt;
1
2
3
4
5
6
7
&lt;/pre&gt;
&lt;/td&gt;&lt;td width="100%"&gt;&lt;pre&gt;&lt;code class="typocode_xml "&gt;&lt;notextile&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="namespace"&gt;rdf&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;RDF&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="namespace"&gt;geo&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;Point&lt;/span&gt; &lt;span class="namespace"&gt;rdf&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;nodeID&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;aid06646235&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="namespace"&gt;dc&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;Mission St and Valencia St, San Francisco CA 94110&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="namespace"&gt;dc&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;description&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="namespace"&gt;geo&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;long&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;-122.420082&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="namespace"&gt;geo&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;long&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="namespace"&gt;geo&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;lat&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;37.74533&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="namespace"&gt;geo&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;lat&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="namespace"&gt;geo&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;Point&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="namespace"&gt;rdf&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="tag"&gt;RDF&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is technically an RDF document. It can still be parsed as a regular XML document though. Let's define a Location class:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;table class="typocode_linenumber"&gt;&lt;tr&gt;&lt;td class="lineno"&gt;
&lt;pre&gt;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
&lt;/pre&gt;
&lt;/td&gt;&lt;td width="100%"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rexml/document&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;net/http&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Location&lt;/span&gt;
  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="constant"&gt;REXML&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;address&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;geocoder&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Net&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HTTP&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;rpc.geocode.us&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="number"&gt;80&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;query&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/service/rest?address=&lt;span class="expr"&gt;#{address}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;query&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub!&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt; &lt;/span&gt;&lt;span class="punct"&gt;/,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;+&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@entry&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Document&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="ident"&gt;geocoder&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;get&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;query&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;long&lt;/span&gt;
    &lt;span class="attribute"&gt;@entry&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;elements&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;//geo:long&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;text&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;lat&lt;/span&gt;
    &lt;span class="attribute"&gt;@entry&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;elements&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;//geo:lat&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;text&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;desc&lt;/span&gt;
    &lt;span class="attribute"&gt;@entry&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;elements&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;//dc:description&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;].&lt;/span&gt;&lt;span class="ident"&gt;text&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;From there, you can create a Location object and get the coordinates:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;table class="typocode_linenumber"&gt;&lt;tr&gt;&lt;td class="lineno"&gt;
&lt;pre&gt;
1
2
3
&lt;/pre&gt;
&lt;/td&gt;&lt;td width="100%"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;location&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Location&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Mission St and Valencia St, San Francisco CA 94110&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;location&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;lat&lt;/span&gt;
&lt;span class="ident"&gt;location&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;long&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;From there, you can use the location in a mapping application (such as a Google Maps mashup for example...)&lt;/p&gt; 

</description>
      <pubDate>Mon, 20 Feb 2006 02:35:48 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:bf5d3c0e400793148313cae5d8761bfb</guid>
      <author>fred@fredjean.net (Frederic Jean)</author>
      <link>http://blog.fredjean.net/articles/2006/02/20/geocoding-rexml-and-the-missing-method</link>
      <category>Ruby</category>
    </item>
  </channel>
</rss>
