跳转到内容

XQuery/Google 地理编码

来自维基教科书,开放的书籍,开放的世界

您有一个或多个地理名称,并且想要创建这些位置的地图。

我们将使用 Google RESTful 网络服务从地名列表中返回地理数据。Google 提供了一个基于 HTTP 的 地理编码服务。这需要为 API 密钥注册一个站点,并且对使用此 API 存在限制。结果可以以 XML 或 JSON 格式返回。

查询 Google 的 API

[编辑 | 编辑源代码]

以下脚本接受一个位置并返回来自服务的 xml

let $key := "apikey"
let $location := request:get-parameter("location",())
let $location := escape-uri($location,false())
let $url := concat("https://maps.googleapis.com/maps/api/geocode/xml?address=",$location,"&key=",$key)
let $response := doc($url)
return 
   $response
</source >

==== Examples ====
Single City Examples:

* [http://kitwallace.co.uk/xqbook/geo/googlegeocode.xq?location=Minneapolis Minneapolis] - example using a single city with no country
* [http://kitwallace.co.uk/xqbook/geo/googlegeocode.xq?location=Bristol,UK  Bristol,UK] - example using a city and country

Multiple matches may be returned:
* [http://kitwallace.co.uk/xqbook/geo/googlegeocode.xq?location=Bristol Bristol]
* or a false positive: [http://kitwallace.co.uk/xqbook/geo/googlegeocode.xq?location=Santas+House  Santa's House]

In the UK, this service will geocode postcodes:
* [http://kitwallace.co.uk/xqbook/geo/googlegeocode.xq?location=BS3+4EA Bristol Hackspace]

== Response as KML ==
The XML response can be reformated as a  KML file.  Note the addition of the relevant media-type for KML .

<syntaxhighlight lang="xml">
let $key := "my apikey"
let $location := request:get-parameter("location",())
let $location := escape-uri($location,false())
let $url := concat("https://maps.googleapis.com/maps/api/geocode/xml?address=",$location,"&amp;key=",$key)
let $response := doc($url)/GeocodeResponse
return 
   if ($response/status="OK")
   then 
      let $x := response:set-header('Content-disposition',concat('inline;filename="',$location,'.kml";'))
      let $result := $response/result[1]
      let $serialize := util:declare-option("exist:serialize", "method=xml media-type=application/vnd.google-earth.kml+xml  indent=yes")
      return
 <kml>
   <Folder>
      <name>{$location}</name>
       {for $result in $response/result
        return
         <Placemark>
           <name>{string($result/formatted_address)}</name>
           <Point>
              <coordinates>{$result/geometry/location/lng/string()},{$result/geometry/location/lat/string()},0</coordinates>
           </Point>
         </Placemark>
        }
   </Folder>
 </kml>
   else $response

如果您有 GoogleEarth,它应该加载一个叠加层,显示多个布里斯托尔位置:布里斯托尔 KML

GoogleMap

[编辑 | 编辑源代码]

查看生成的 kml 的一种简单方法是使用 GoogleMaps。此脚本只需构建使用上述脚本的相关 URL,然后重定向到该 URL

let $location := request:get-parameter("location",())
let $wikiurl := escape-uri(concat("http:/kitwallace.co.uk/geocodekml.xq?location=",$location),false())
let $url := concat("http://maps.google.co.uk/maps?q=",$wikiurl)
return 
   response:redirect-to(xs:anyURI($url))

遗憾的是,这种方法不再适用于 GoogleMap - 请参阅 支持丢失 布里斯托尔

另一种方法是使用 GoogleMap 的 JavaScript API。请注意,要嵌入 JavaScript 需要将 { 复制,因此通常将 JavaScript 放入单独的文件中更容易。这种方法利用任何现有的 kml 叠加层,更简单,但比使用 JavaScript API 实现地图更受限制

declare option exist:serialize "method=xhtml media-type=text/html";

let $location := request:get-parameter("location",())
let $url := escape-uri(concat("http://kitwallace.co.uk/xqbook/geo/geocodekml.xq?location=",$location),false())
return
<html>
   <head>
     <script src="https://maps.googleapis.com/maps/api/js?v=3&amp;key=myapikey"></script> 
     <script type="text/javascript">
function initialize(url) {{
  var map = new google.maps.Map(document.getElementById("map_canvas"));

  var kmlLayer = new google.maps.KmlLayer({{
    url: url,
    map:map
  }}); 
}}    
      </script>
    </head>
    <body  onload="initialize('{$url}')">
       <h2>Map of {$location}</h2>
       <div id="map_canvas" style="height: 80%;width: 80%; margin: 0px; padding: 0px">
       </div>
    </body>
</html>


*  Bristol
*  London

[设置缩放级别似乎不起作用]

叠加数据

[编辑 | 编辑源代码]

通常,位置在数据文件中定义。以下脚本读取一个本地文件(威士忌酒厂的样本)并创建一个 KML 叠加层。

let $key := "apikey"
let $locations := doc("/db/apps/xqbook/geo/whisky.xml")
let $serialize := util:declare-option("exist:serialize", "method=xml media-type=application/vnd.google-earth.kml+xml") 
let $x := response:set-header('Content-disposition','inline;filename=whisky.kml')
return
 <kml>
   <Folder>
      <name>Distilleries</name>
      {for $location in $locations//Whisky
       let $url := concat("https://maps.googleapis.com/maps/api/geocode/xml?address=",$location/Postcode,"&amp;key=",$key)
       let $response := doc($url)/GeocodeResponse
       let $result := $response/result[1]
       return
      <Placemark>
           <name>{$location/Brand/string()}</name>
           <description>{$location/Address/string()}</description>
           <Point>
              <coordinates>{$result/geometry/location/lng/string()},{$result/geometry/location/lat/string()},0</coordinates>
           </Point>
      </Placemark>
      }
   </Folder>
 </kml>

威士忌叠加层

以及 JavaScript 的修改版本,可以使用输出创建 威士忌地图

华夏公益教科书