Web Feature Service - WFS
A WFS is a method to access a database via the Web, and also to display geographical maps.
There are many ways to use a WFS. The first method below displays maps. The other four methods retrieve data. You control the rows and columns you want to see from the tables in the database. The data retrieved is returned in various formats; in XML (Extendable Markup Language), GML3 (Geography Markup Language, version 3), KML (Keyhole Markup Language), SHAPE (ESRI Shapefile), MIF (MapInfo Mid/Mif format), application/json (Javascript Object Notation), RSS (Really Simple Syndication), ATOM (Atom Syndication Format), etc, and these formats may be displayed within your own web pages and applications.
- Opening the WFS into a GIS software
- Pasting a WFS request into the cwpost CubeWerx Utility
- Pasting a WFS request as a URI into your browser
- Displaying a WFS output into your web page or application
- Using files of WFS requests
- WFS Reference Manuals
These methods are described below.
1- Opening the WFS in GIS software
There are many free and commercial softwares available over the Web that display maps using WFS. Simply paste the following URI into the GIS:
http://geonames.nrcan.gc.ca/wfs/cubeserv.cgi?service=wfs&datastore=cgns
Some GIS have difficulty with the above URI because of the CRS (Coordinates Reference System) used, in which case one should use the following URI:
Some GIS software asks the user to enter a URI containing request=getCapabilities and the Version. In which case one should use the following URI:
http://geonames.nrcan.gc.ca/wfs/cubeserv.cgi?service=wfs&datastore=cgns &request=getCapabilities&version=1.1.0
or
http://geonames.nrcan.gc.ca/wfs/cubeserv.cgi?service=wfs&datastore=cgns &srsname=urn::ogc:def:crs:EPSG::4326&request=getCapabilities&version=1.1.0
When we click on the above links that contains "request=getCapabilities" the WFS returns a file that describes its capabilities. Some important portions of the file will be explained later below.
If you are not familiar with WFS and want to make tests, we encourage you to use the following development test sites:
http://cgns-dev.nrcan.gc.ca/wfs/cubeserv.cgi?service=wfs&datastore=cgns
or
2- Pasting a WFS request into the cwpost CubeWerx Utility
The CGNDB database can be queried through the WFS using the cwpost Utility found here. In the server URL box, enter:
http://geonames.nrcan.gc.ca/wfs/cubeserv.cgi?service=wfs&datastore=cgns
All you have to do is to paste your XML request and hit the Submit button. Various XML examples are given in the following section, including querying a geographical area.
3- Pasting a WFS request as a URI into your browser
This section shows many examples of how to retrieve data using the WFS. You build queries that use XML, and paste it into your browser, or into the cwpost Utility explained in Section 2 above.
When you click on one of the links in Section 1 above, the WFS provides you with its capabilities (request=getCapabilities). The file returned shows the line <ows:Parameter name="TypeName"> and the lines that follow it are the tables in the database made available through the WFS. Here are some of these tables:
- GEONAMES
- CGNS_CODES
- GENERIC_CODES
- GEONAMES_POINTS
- MAPS
- MAPS_PRINTED_E
- MAPS_PRINTED_F
- PANCAN
The examples below use the table GEONAMES that contains the geographical names. The other tables are mainly tables of codes which you can also query as explained in our GeoNames Code Information Service.
The following describeFeatureType request returns the columns (also called the attributes) of the table (also called the class).
You may query (1) the tables you want, (2) the columns you want, and (3) restrict the rows you want using the Filter parameter.
Searching using the Geographical Name (referred to as geoname)
Here is an example of a WFS URI that queries a geographical name from the database table Geonames.
The following example is equivalent to the above query but is the browser proof translation of the first using URL encoded characters for special characters such as the opening (<) and closing (>) brackets. Many characters are misinterpreted by browsers so it is safer to use their hexadecimal encoded version.
These URI can be pasted in the browser or inserted into an HTML file, a Java file, a PHP file, a PL/SQL script or a Visual Basic file, etc.
The following filter is equivalent to the above filter but written in a way that is easy to read. This filter is in the format that can be pasted in the cwpost Utility mentioned in Section 2 above.
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<Filter>
<PropertyIsEqualTo>
<PropertyName>GEONAME</PropertyName>
<Literal>Toronto</Literal>
</PropertyIsEqualTo>
</Filter>
</Query>
</GetFeature>
Searching using Name_key and the Wildcard
To simplify the search of names, the GeoNames table contains the field Name_key. The Name_key field stores the geoname written in upper case, without any blank spaces and without any special characters.
Querying using Name_key has the advantage of not having to enter special characters. For example, if we are not sure if the name contains accent, period, dash, etc, as in 'Montreal' or 'Montréal', 'Saint ', 'Saint.', 'Saint-', 'Sainte ', 'Sainte-', 'Sainte.', 'St ', 'St.', 'St-', 'Ste ', 'Ste-', or 'Ste.', then it is preferable to use "MONTREAL" or 'S%T%'.
Heres an example of a query using Name_key like 'S%T%THERESECREEK'. Here the percents will returns 'Ste.-Thérèse Creek'. Another query using Name_key like '%ALBERT' would return 'Prince Albert' and 'Mount Albert'.
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This query uses the LIKE function... -->
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<PropertyName>GEONAME</PropertyName>
<PropertyName>CGNDB_KEY</PropertyName>
<PropertyName>FEATURE_ID</PropertyName>
<PropertyName>HISTORY</PropertyName>
<PropertyName>REGION_NAME</PropertyName>
<PropertyName>REGION_ABBR</PropertyName>
<PropertyName>REGION_CODE</PropertyName>
<PropertyName>CONCISE_CODE</PropertyName>
<PropertyName>GENERIC_TERM</PropertyName>
<PropertyName>NTS_MAP</PropertyName>
<PropertyName>GEOMETRY</PropertyName>
<Filter>
<PropertyIsLike>
<PropertyName>NAME_KEY</PropertyName>
<Literal>S%T%THERESECREEK</Literal>
</PropertyIsLike>
</Filter>
</Query>
</GetFeature>
Note: The lines <PropertyName> before the tag <Filter> allow to obtain only the fields desired.
Searching by CGNDB key
When one specific record of a name is desired, one may query using the unique key called the CGNDB Key:
<<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<Filter>
<PropertyIsEqualTo>
<PropertyName>CGNDB_KEY</PropertyName>
<Literal>EHHUN</Literal>
</PropertyIsEqualTo>
</Filter>
</Query>
</GetFeature>
Searching by Feature Id
When all the names (French, English and Aboriginal) of a geographic features are desired, one may search using the Feature Id. The Feature Id links all the names of a feature together.
Note: The Feature Id also links the former names to official name, but presently, not all former names have been linked to their new official names through the Feature Id. Alternately, one may search for former names using the Related Key field.
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<Filter>
<PropertyIsEqualTo>
<PropertyName>FEATURE_ID</PropertyName>
<Literal>4d00fe4cba2011d892e2080020a0f4c9</Literal>
</PropertyIsEqualTo>
</Filter>
</Query>
</GetFeature>
Searching only the Official Names (and using "And")
The database contains both official names and formerly official names. To retrieve only the current official names use History = '2-Official Name', together with your other request. To query only former names, use History = '3-Former Name'
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<Filter>
<And>
<PropertyIsEqualTo>
<PropertyName>HISTORY</PropertyName>
<Literal>2-Official Name</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<PropertyName>FEATURE_ID</PropertyName>
<Literal>33e24964c6ce11d892e2080020a0f4c9</Literal>
</PropertyIsEqualTo>
</And>
</Filter>
</Query>
</GetFeature>
Searching using RS_value (relevance of name upon map scale)
The popular names are seen on Atlas maps of Canada at scales of say 1:42 million or 1:15 million, thus one may use the RS_value or relevance_at_scale values:
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<PropertyName>GEONAME</PropertyName>
<PropertyName>HISTORY</PropertyName>
<Filter>
<And>
<PropertyIsEqualTo>
<PropertyName>HISTORY</PropertyName>
<Literal>2-Official Name</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<PropertyName>RELEVANCE_AT_SCALE</PropertyName>
<Literal>42000000</Literal>
</PropertyIsEqualTo>
</And>
</Filter>
</Query>
</GetFeature>
or
Searching in a specific Province or Territory (and using "And" and "Or")
One may restrict the search to names approved by a Province or a Territory. Use the two-digit Region Code shown here:
NL - 10
PE - 11
NS - 12
NB - 13
QC - 24
ON - 35
MB - 46
SK - 47
AB - 48
BC - 59
YT - 60
NT - 61
NU - 62
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<PropertyName>GEONAME</PropertyName>
<PropertyName>HISTORY</PropertyName>
<Filter>
<And>
<Or>
<PropertyIsEqualTo>
<PropertyName>REGION_CODE</PropertyName>
<Literal>46</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<PropertyName>REGION_CODE</PropertyName>
<Literal>47</Literal>
</PropertyIsEqualTo>
</Or>
<PropertyIsLike>
<PropertyName>NAME_KEY</PropertyName>
<Literal>MONTREAL%</Literal>
</PropertyIsLike>
</And>
</Filter>
</Query>
</GetFeature>
Downloading the whole database - Searching by Region Code and BBox
There are about 350,000 names in the database, and the maximum number of records returned by one query is currently limited to 10,000. To download the whole database, 41 queries would be required.
Note : The database is easily available in its entirety in files updated weekly as described in our Digital Data section in the left menu above.
Here is a query combining the region (code) and a geographic area (bounding box) in the searching criteria. Some provinces have more than 10,000 records, and thus would require to be cut into many areas (using the BBOX parameter).
QC = region_code = 24 requires 12 queries,
ON = region_code = 35 requires 6 queries,
BC = region_code = 59 requires 5 queries,
NL = region_code = 10 requires 3 queries,
NS = region_code = 12 requires 3 queries,
NB = region_code = 13 requires 2 queries,
MB = region_code = 46 requires 2 queries,
SK = region_code = 47 requires 2 queries,
regionCode = 11, 48, 60, 61, 62 and 73 require 1 query.
Example of querying a geographic area, i.e., within a Bounding Box (BBOX).
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<PropertyName>GEONAME</PropertyName>
<PropertyName>HISTORY</PropertyName>
<Filter>
<BBOX>
<PropertyName>GEOMETRY</PropertyName>
<Envelope srsName="EPSG:4326">
<lowerCorner>43.7 -79.4</lowerCorner>
<upperCorner>43.8 -79.35</upperCorner>
</Envelope>
</BBOX>
</Filter>
</Query>
</GetFeature>
Example of querying a geographic area (BBOX) mixed with "And" or "Or".
Note : The BBOX must be the last constraint:
<And>
<PropertyIsEqualTo>
<PropertyName>GENERIC_CODE</PropertyName>
<Literal>1</Literal>
</PropertyIsEqualTo>
<BBOX>
<PropertyName>GEOMETRY</PropertyName>
<Envelope srsName="EPSG:4326">
<lowerCorner>43.7 -79.4</lowerCorner>
<upperCorner>43.8 -79.35</upperCorner>
</Envelope>
</BBOX>
</And>
Using isLess or isGreather
<PropertyIsLessThan>
<PropertyName>GENERIC_CODE</PropertyName>
<Literal>2</Literal>
</PropertyIsLessThan>
Using isLessThanOrEqualTo or is GreatherThanOrEqualTo
<PropertyIsLessThanOrEqualTo>
<PropertyName>GENERIC_CODE</PropertyName>
<Literal>1</Literal>
</PropertyIsLessThanOrEqualTo>
Using isNull
<PropertyIsNull>
<PropertyName>FEATURE_ID</PropertyName>
</PropertyIsNull>
Using isBetween
<PropertyIsBetween>
<PropertyName>GENERIC_CODE</PropertyName>
<LowerBoundary>0</LowerBoundary>
<UpperBoundary>2</UpperBoundary>
</PropertyIsBetween>
or
<Between>
<PropertyName>MODIFIED_DATE</PropertyName>
<LowerBoundary>
<Literal>2001-01-15T20:07:48.11</Literal>
</LowerBoundary>
<UpperBoundary>
<Literal>2001-03-06T12:00:00.00</Literal>
</UpperBoundary>
</Between>
Choosing output columns
The amount of information returned may be limited to the selected columns. In the following example, the line <PropertyName>GEONAME</PropertyName> requests that only the column Geoname be returned from the database.
Note: If no column is defined with PropertyName tags, all the columns are returned.
Note: If only one column is defined, the WFS will return it along with all the columns that are defined as mandatory information in the database. This complies with the WFS specifications stating that a WFS returns an XML document that validates against the database schema. Thus, every database columns defined as "not null" will be returned.
<?xml version="1.0" encoding="UTF-8" ?>
<GetFeature srsName="EPSG:4326">
<Query typeName="GEONAMES">
<PropertyName>GEONAME</PropertyName>
<Filter>
<PropertyIsEqualTo>
<PropertyName>CGNDB_KEY</PropertyName>
<Literal>EHHUN</Literal>
</PropertyIsEqualTo>
</Filter>
</Query>
</GetFeature>
Here's a list of the fields in the Geonames database. Again the getCapabilities explained in section 1 above provides the latest list of columns.
<PropertyName>CGNDB_KEY</PropertyName>
<PropertyName>CONCISE_CODE</PropertyName>
<PropertyName>CONCISE_GAZ_FLAG</PropertyName>
<PropertyName>COORDINATE_ACCURACY</PropertyName>
<PropertyName>DATE_CREATED</PropertyName>
<PropertyName>DATE_MODIFIED</PropertyName>
<PropertyName>DECISION_DATE</PropertyName>
<PropertyName>DECISION_DATE</PropertyName>
<PropertyName>DISPLAY_PRIORITY</PropertyName>
<PropertyName>EFFECTIVE_DATE</PropertyName>
<PropertyName>EFFECTIVE_DATE</PropertyName>
<PropertyName>ELEVATION</PropertyName>
<PropertyName>FONT_COLOR</PropertyName>
<PropertyName>FONT_SIZE</PropertyName>
<PropertyName>FONT_TYPE</PropertyName>
<PropertyName>GENERIC_CODE</PropertyName>
<PropertyName>GENERIC_TERM</PropertyName>
<PropertyName>GEOMETRY</PropertyName>
<PropertyName>GEONAME</PropertyName>
<PropertyName>HISTORY</PropertyName>
<PropertyName>HYPER_LINK</PropertyName>
<PropertyName>LANGUAGE</PropertyName>
<PropertyName>LATDEC</PropertyName>
<PropertyName>LIST</PropertyName>
<PropertyName>LOCATION</PropertyName>
<PropertyName>LONDEC</PropertyName>
<PropertyName>MAPPING_CATEGORY</PropertyName>
<PropertyName>NAME_KEY</PropertyName>
<PropertyName>NTS_MAP</PropertyName>
<PropertyName>ORIGINAL_APPROVAL_DATE</PropertyName>
<PropertyName>PC_NAME_LANG</PropertyName>
<PropertyName>PRIMARY_RELATED_KEY</PropertyName>
<PropertyName>PRIMARY_RELATED_NAME</PropertyName>
<PropertyName>REGION_ABBR</PropertyName>
<PropertyName>REGION_CODE</PropertyName>
<PropertyName>REGION_NAME</PropertyName>
<PropertyName>RELATED_KEY</PropertyName>
<PropertyName>RELEVANCE_AT_SCALE</PropertyName>
<PropertyName>RS_VALUE</PropertyName>
<PropertyName>SOURCE_CREATED</PropertyName>
<PropertyName>SOURCE_FEATURE_ID</PropertyName>
<PropertyName>SOURCE_MODIFIED</PropertyName>
<PropertyName>SOURCE_RECORD_ID</PropertyName>
<PropertyName>STATUS_CODE</PropertyName>
<PropertyName>SYNONYM_KEY</PropertyName>
Possible output formats
<GetFeature srsName="EPSG:4326" outputFormat="BXFS">
<GetFeature srsName="EPSG:4326" outputFormat="GML0">
<GetFeature srsName="EPSG:4326" outputFormat="GML2">
<GetFeature srsName="EPSG:4326" outputFormat="GML3">
<GetFeature srsName="EPSG:4326" outputFormat="GML3L0">
<GetFeature srsName="EPSG:4326" outputFormat="GML3L1">
<GetFeature srsName="EPSG:4326" outputFormat="KML">
<GetFeature srsName="EPSG:4326" outputFormat="SHAPE">
<GetFeature srsName="EPSG:4326" outputFormat="MIF">
<GetFeature srsName="EPSG:4326" outputFormat="RSS">
<GetFeature srsName="EPSG:4326" outputFormat="ATOM">
<GetFeature srsName="EPSG:4326" outputFormat="application/json">
Note: To the exception of KML, most of the formats support srsName="urn::ogc:def:crs:epsg::4326" to obtain coordinates ordered in Latitude/Longitude.
4- Displaying a WFS output in your web page or application
The results of a WFS query may be inserted into your web page or application. The URI explained in the previous section 3 may be inserted into your web pages. Because the data returned is formatted into XML, it is convenient to use XSL to format the result in the way you desire.
5- Using files of WFS requests
One may find it convenient to create files containing WFS requests (as explained in section 3 above). Create a file with extension .html (e.g., WFS_CGNS.html) which contains the following code.
<html><head><title>WFS CGNS</title></head>
<body><h3>WFS CGNS</h3>
<form action="http://geonames.nrcan.gc.ca/wfs/cubeserv.cgi?service=wfs&datastore=cgns"
enctype="multipart/form-data" method=post>
<input type=file size=50 name="filename">
<input type="submit" value="Submit">
<input type="reset">
</form></br></body></html>
Double clicking on the html filename opens the html file in the browser. Browse for the file that contains your WFS request (similar to one of section 3). Click on Submit, and the result is returned.
WFS Reference Manuals
More examples are found here under Standard and Filter Encoding. Use the latest version. Reference manuals for WFS are found on the same website, under Standard and then Web Feature Service.