| Author: | Tom Kralidis |
|---|---|
| Contact: | tom.kralidis at ec.gc.ca |
| Release: | 2.0.0 |
| Date: | $Date: 2010-06-29 09:23:23 -0400 (Tue, 29 Jun 2010) $ |
The CGDI Postal Code Lookup Service provides an XML-encoded web service, which returns geometries for known forward sortation area (FSA) postal codes.
The service provides point geometries for FSAs as per point data obtained from Statistics Canada. The service returns record(s) for matching FSAs with point geometry, encoded as GML.
Below is a diagram of how the service derives feature geometry for postal code records.
The CGDI Postal Code Lookup Service software can be easily installed on any OS with an existing HTTP server environment (such as Apache httpd).
The software requires a Python interpreter. Your HTTP server must be able to support Python CGI scripts.
Installation is easy; unpack the source code into a web accessible directory:
$ tar zxf postalcode-2.0.0.tar.gz
Edit the following variables in default.cfg:
[server]
[service]
[provider]
At this point, you should be able to run requests on the command line:
$ ./postalcode.cgi "version=2.0.0&request=GetCapabilities"
.. lots of XML output
$ ./postalcode.cgi "version=2.0.0&request=DescribePostalCode"
.. lots of XML output
$ ./postalcode.cgi "version=2.0.0&request=GetPostalCode&code=m9c"
.. lots of XML output
The service will be located at http://host/path/to/postalcode/postalcode.cgi This URL must match the server.url parameter in default.cfg.
The CGDI Postal Code Lookup Service accepts both HTTP GET and HTTP POST. Keyword parameters are case insensitive, however value parameters are case sensitive unless otherwise specified.
The service supports three (3) operations:
- GetCapabilities
- DescribePostalCode
- GetPostalCode
The purpose of the GetCapabilities operation is to provide general information about the service itself and specific information about the name sources used. The output is XML as per the OWS Common standard [OWS].
| Request Parameter | Required / Optional | Description |
|---|---|---|
| VERSION=2.0.0 | Required | Request version |
| REQUEST=GetCapabilities | Required | Request name |
Sample request: http://host/path/to/postalcode/postalcode.cgi?version=2.0.0&request=GetCapabilities
The purpose of the DescribePostalCode operation is to return the GML application schema for the FSA content model.
| Request Parameter | Required / Optional | Description |
|---|---|---|
| VERSION=2.0.0 | Required | Request version |
| REQUEST=DescribePostalCode | Required | Request name |
Sample request: http://host/path/to/postalcode/postalcode.cgi?version=2.0.0&request=DescribePostalCode
The purpose of the GetPostalCode operation is to return the geometries for a placename inputted by a request.
| Request Parameter | Required / Optional | Description |
|---|---|---|
| VERSION=2.0.0 | Required | Request version |
| REQUEST=GetPostalCode | Required | Request name |
| CODE=fsa | Required | FSA code, case insensitive |
Below is the content model returned by a GetPostalCode response:
Sample request: http://host/path/to/postalcode/postalcode.cgi?version=2.0.0&request=GetPostalCode&code=m9c
Response:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<PostalCodeLookup xmlns="http://www.cgdi.ca/postalcode" version="2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.cgdi.ca/postalcode http://devgeo.cciw.ca/postalcode/postalcode.cgi?version=2.0.0&request=DescribePostalCode">
<gml:boundedBy>
<gml:Null>inapplicable</gml:Null>
</gml:boundedBy>
<PostalCodeResultSet sortArea="FSA">
<PostalCode>
<gml:name>M9C</gml:name>
<Placename>Etobicoke</Placename>
<ProvinceOrTerritory>ON</ProvinceOrTerritory>
<gml:centerOf>
<gml:Point srsName="urn:ogc:def:crs:EPSG:6.6:4326" srsDimension="2">
<gml:pos>43.642063 -79.575493</gml:pos>
</gml:Point>
</gml:centerOf>
</PostalCode>
</PostalCodeResultSet>
</PostalCodeLookup>
The service will return OGC ExceptionReport documents on invalid requests, as per OWS Common [OWS].
<?xml version="1.0" encoding="ISO-8859-1"?>
<ExceptionReport xmlns="http://www.opengis.net/ows/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ows/2.0 http://schemas.opengis.net/ows/2.0/owsExceptionReport.xsd" version="2.0.0" xml:lang="en-CA">
<Exception locator="request" exceptionCode="InvalidParameterValue">
<ExceptionText>Invalid value for request: invalidrequestname</ExceptionText>
</Exception>
</ExceptionReport>
Since the CGDI Postal Code Lookup Service is a Web Service, any programming language which can make HTTP requests and parse XML can be used.
Here’s a simple Python script to fetch FSA ‘m9c’:
#!/usr/bin/python
import urllib2
from lxml import etree
url = 'http://host/path/to/postalcode/postalcode.cgi?version=2.0.0&request=GetPostalCode&code=m9c'
content = urllib2.urlopen(url)
doc = etree.parse(content)
postalcode = doc.find('{http://www.cgdi.ca/postalcode}PostalCodeResultSet/{http://www.cgdi.ca/postalcode}PostalCode')
code = postalcode.find('{http://www.opengis.net/gml}name').text
placename = postalcode.find('{http://www.cgdi.ca/postalcode}Placename').text
provterr = postalcode.find('{http://www.cgdi.ca/postalcode}ProvinceOrTerritory').text
coords = postalcode.find('{http://www.opengis.net/gml}centerOf/{http://www.opengis.net/gml}Point/{http://www.opengis.net/gml}pos').text
# ...
Here’s a simple JavaScript function using jQuery (note that a proxy wrapper script is required [proxy_url]):
jQuery(document).ready(function(){
// set up an HTML form element with id="postalForm" and input text box with id="postal"
jQuery('#postalForm').submit(zoomToPostalCode);
// ...
function zoomToPostalCode() {
var proxy_url = 'http://host/path/to/proxy';
var url = proxy_url +
escape('http://host/path/to/postalcode/postalcode.cgi?version=2.0.0&request=GetPostalCode&code=') + jQuery('input#postal').val();
jQuery.get(url,{},function(xml){
jQuery('PostalCode',xml).each(function(i) {
var code = jQuery(this).find('gml\\:name').text();
var placename = jQuery(this).find('Placename').text();
var provterr = jQuery(this).find('ProvinceOrTerritory').text();
var coords = jQuery(this).find('gml\\:pos').text();
// ...
});
});
return false;
}
Here’s a simple example of local interaction with the Python module:
$ cd /path/to/postalcode
$ python
Python 2.6.2 (r262:71600, Aug 21 2009, 12:22:21)
[GCC 4.4.1 20090818 (Red Hat 4.4.1-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from postalcode import fsa
>>> help(fsa)
... help text
>>> fsa.getfsa('/path/to/postalcode/data/fsa.csv','m9c')
{'placename': 'Etobicoke', 'code': 'M9C', 'success': True, 'sortarea': 'FSA', 'longitude': '-79.575493', 'provinceorterritory': 'ON', 'latitude': '43.642063'}
>>> fsa.getfsa('/path/to/postalcode/data/fsa.csv','invalidcode')
{'locator': 'code', 'code': 'InvalidParameterValue', 'success': False, 'text': 'Invalid code value: INVALIDCODE'}
>>>
| [GML] | Open Geospatial Consortium, 2004, OpenGIS Geography Markup Language (GML) Encoding Standard 3.1.1, http://portal.opengeospatial.org/files/?artifact_id=4700. |
| [OWS] | (1, 2) Open Geospatial Consortium, 2010, OGC Web Service Common Implementation Specification 2.0.0, http://portal.opengeospatial.org/files/?artifact_id=38867. |