Accessing WFS Data¶
This is a brief explanation of using a WFS server.
Using GIS Software¶
Commonly, a WFS server can is accessed by GIS-software, such as QGis.
The URL that’s configured inside urls.py can be used directly as WFS endpoint.
For example, add https://api.data.amsterdam.nl/v1/wfs/gebieden/ to QGis.
Everything, for querying and viewing can be done in QGis.
Tip
The parameters ?SERVICE=WFS&VERSION=2.0.0&REQUEST=.. are appended to the URL
by QGis. It’s not required to add these yourself.
Manual Access¶
The WFS server can also be accessed directly from a HTTP client (e.g. curl) or web browser. In such case, use the basic URL above, and include the query parameters:
?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAMES=featurename
The available feature types can be found in the GetCapabilities request:
?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities
The remaining part of this page assumes this manual access.
Tuning the Results¶
Export Formats¶
The following export formats are available:
GeoJSON
CSV
These can be queried by manually crafting a GetFeature request.
The parameters TYPENAMES=feature-name and OUTPUTFORMAT=format should be included.
For example:
Tip
In the example links above, a COUNT= parameter is included to activate pagination.
When this parameter is omitted, all objects will be returned in a single request.
For most datasets, the server is capable of efficiently delivering all results in a single response.
Reducing Returned Fields¶
The PROPERTYNAME parameter can be used to define which elements should be returned.
For example:
Tip
This project also supports using PROPERTYNAME for nested elements (parent/child).
The WFS 2.0 specification defines the PROPERTYNAME as a QName for top-level elements only.
Changing Geometry Projections¶
The exportlink can be extended with the SRSNAME parameter to define the geometry projection
of all geo data. For example, SRSNAME=urn:ogc:def:crs:EPSG::3857 activates the web-mercator projection
which is used by Google Maps. A common default is urn:ogc:def:crs:EPSG::4326, which is the
worldwide WGS 84 longitude-latitude.
Filtering Results¶
Simple Filters¶
The WFS protocol offers a powerful syntax to filter data.
Use the request REQUEST=GetFeature with a FILTER argument.
The filter value is expressed as XML.
For example, to query all neighbourhoods (typename buurten) of the central district (stadsdeel) in Amsterdam:
<Filter>
<PropertyIsEqualTo>
<ValueReference>ligt_in_stadsdeel/naam</ValueReference>
<Literal>Centrum</Literal>
</PropertyIsEqualTo>
</Filter>
This can be included in the request, for example:
…&TYPENAMES=wijken&OUTPUTFORMAT=geojson&FILTER=%3CFilter%3E%3CPropertyIsEqualTo%3E%3CValueReference…
The FILTER parameter replaces the separate BBOX and RESOURCEID parameters.
If you use these parameters as well, they should be included in the filter:
<Filter>
<And>
<BBOX>
<gml:Envelope srsName="EPSG:4326">
<gml:lowerCorner>4.58565 52.03560</gml:lowerCorner>
<gml:upperCorner>5.31360 52.48769</gml:upperCorner>
</gml:Envelope>
</BBOX>
<PropertyIsEqualTo>
<ValueReference>status</ValueReference>
<Literal>1</Literal>
</PropertyIsEqualTo>
</And>
</Filter>
The RESOURCEID parameter has a <ResourceId> equivalent which can appear several times in the filter:
<Filter>
<ResourceId rid="TYPENAME.123" />
<ResourceId rid="TYPENAME.4325" />
<ResourceId rid="OTHERTYPE.567" />
</Filter>
Complex Filters¶
The WFS Filter Encoding Standaard (FES) supports many operators. These tags are all supported:
Element |
SQL equivalent |
Description |
|---|---|---|
|
|
Values must be equal. |
|
|
Values must not be equal. |
|
|
Value 1 must be less than value 2. |
|
|
Value 1 must be greater than value 2. |
|
|
Value 1 must be less than or equal to value 2. |
|
|
Value 1 must be greater than or equal to value 2. |
|
|
Compares between |
|
|
Performs a wildcard comparison. |
|
|
Value must be |
|
n.a. |
Property may not exist (currently implemented as |
|
|
Geometry must be partly in value 2. The field name may be omitted to use the default. |
|
|
Geometry completely contains geometry 2, e.g. province contains city. |
|
|
The geometries have some common interior points, e.g. two streets. |
|
|
The geometries are not connected in any way. |
|
|
The geometries are identical. |
|
|
The geometries share some space. |
|
|
The edges of the geometries touch each other, e.g. country borders. |
|
|
The geometries overlap. |
|
|
Geometry is completely contained within geometry 2, e.g. city within province. |
|
|
The geometries are within a given distance of each other. |
|
|
The geometries are not within a given distance. |
|
|
The nested operators must all be true. |
|
|
Only one of the nested operators has to be true. |
|
|
Negation of the nested operators. |
|
|
Searches for a feature as “type name.identifier”.
Combines multiple elements into an |
Tip
For the <BBOX> operator the geometry field may be omitted.
The standard geometry field is then used as configured in the feature type.
Note
Although a number of geometry operators seem to be identical for surfaces
(such as <Intersects>, <Crosses> and <Overlaps>),
their mutual differences are particularly visible when comparing points with surfaces.
Expressions in the Filter¶
Various expressions may be used as values:
Expression |
SQL equivalent |
Description |
|---|---|---|
|
|
References a field. |
|
value |
Literal value, can also be a GML-object. |
|
|
Executes a function, such as |
|
|
Addition (WFS 1 expression). |
|
|
Subtraction (WFS 1 expression). |
|
|
Multiplication (WFS 1 expression). |
|
|
Division (WFS 1 expression). |
This allows to create complex filters, such as:
<Filter>
<And>
<PropertyIsEqualTo>
<ValueReference>status</ValueReference>
<Literal>1</Literal>
</PropertyIsEqualTo>
<Or>
<PropertyIsEqualTo>
<ValueReference>container_type</ValueReference>
<Literal>Other</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<ValueReference>container_type</ValueReference>
<Literal>Textile</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<ValueReference>container_type</ValueReference>
<Literal>Glass</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<ValueReference>container_type</ValueReference>
<Literal>Papier</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<ValueReference>container_type</ValueReference>
<Literal>Organic</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<ValueReference>container_type</ValueReference>
<Literal>Plastic</Literal>
</PropertyIsEqualTo>
</Or>
</And>
</Filter>
Using Functions¶
Functions are executed in a <Filter> by using the tag <Function name="..">..</Function>.
This can be used anywhere as an expression instead of a <ValueReference> or <Literal>.
Inside the function, the parameters are also given as expressions:
a <ValueReference>, <Literal> or new <Function>.
As a simple example:
<fes:Function name="sin">
<fes:ValueReference>fieldname</fes:ValueReference>
</fes:Function>
As expressions can be functions, the following filter is possible:
<Filter>
<PropertyIsEqualTo>
<Function name="strToLowerCase">
<Function name="strSubstring">
<ValueReference>name</ValueReference>
<Literal>0</Literal>
<Literal>4</Literal>
</Function>
</Function>
<Literal>cafe</Literal>
</PropertyIsEqualTo>
</Filter>
Various functions are built-in available in the server, inspired by the filter functions found in GeoServer:
Function |
SQL equivalent |
Description |
|---|---|---|
|
|
Concatenates strings |
|
|
Finds the text inside a string, 0-based index. |
|
|
Removes characters before begin and after end. |
|
|
Removes characters before begin, 0-based index. |
|
|
Convert text to lowercase. |
|
|
Convert text to uppercase. |
|
|
Remove white space at the beginning and end. |
|
|
Determines text length. |
|
|
Alias of |
Function |
SQL equivalent |
Description |
|---|---|---|
|
|
Invert negative numbers. |
|
|
Rounding up. |
|
|
Rounding down. |
|
|
Regular rounding. |
|
|
Uses the smallest number. |
|
|
Uses the largest number. |
|
|
Exponentiation |
|
|
Exponent of 𝑒 (2,71828…; natural logarithm). |
|
|
Logarithm; inverse of an exponent. |
|
|
Square root, inverse of exponentiation. |
Function |
SQL equivalent |
Description |
|---|---|---|
|
|
Arccosine; inverse of cosine. |
|
|
Arcsine; inverse van sine. |
|
|
Arctangent; inverse of tangent. |
|
|
Arctangent, for usage outside the range of a circle. |
|
|
Cosine |
|
|
Sine |
|
|
Tangent |
|
|
The value of π (3,141592653…) |
|
|
Conversion of radians to degrees. |
|
|
Conversion degrees to radians. |
Function |
SQL equivalent |
Description |
|---|---|---|
|
|
Convert geometry to area. |
|
|
Return geometric center as “gravity point”. |
|
|
Parts of geometry 1 that do not overlap with geometry 2. |
|
|
Minimum distance between 2 geometries. |
|
|
Convert geometry to bounding box. |
|
|
The cartesian length for a linestring/curve. |
|
|
Parts of geometry 1 that overlap with geometry 2. |
|
|
Tests whether the geometry is empty. |
|
|
Tests whether the geometry is valid. |
|
|
Tests how many geometries are found in the collection. |
|
|
Tests how many points are found in a linestring. |
|
|
The 2D perimeter of the surface/polygon. |
|
|
Parts of geometry 1 and 2 that don’t intersect. |
|
|
Merge Geometry 1 and 2. |
Using XML POST Requests¶
When the filter length exceeds the query-string limits, consider using an XML POST request instead of the KVP query-string format.
A GET request such as:
?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature
&TYPENAMES=app:restaurant
&FILTER=<Filter>...</Filter>
&PROPERTYNAME=app:id,app:name,app:location
&SORTBY=app:name ASC
…can also be defined as XML-encoded POST request:
<wfs:GetFeature service="WFS" version="2.0.0"
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:fes="http://www.opengis.net/fes/2.0"
xmlns:app="http://example.org/my-namespace">
<wfs:Query typeNames="app:restaurant">
<wfs:PropertyName>app:id</wfs:PropertyName>
<wfs:PropertyName>app:name</wfs:PropertyName>
<wfs:PropertyName>app:location</wfs:PropertyName>
<fes:Filter>
...
</fes:Filter>
<fes:SortBy>
<fes:SortProperty>
<fes:ValueReference>app:name</fes:ValueReference>
<fes:SortOrder>ASC</fes:SortOrder>
</fes:SortProperty>
</fes:SortBy>
</wfs:Query>
</wfs:GetFeature>
Support for Older Clients¶
Missing XML Namespaces¶
Strictly speaking, XML namespaces are required in the filter. Since many clients omit them, the server also supports requests without namespaces. For the sake of completeness, a request with namespaces included looks like this:
<fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/fes/2.0
http://schemas.opengis.net/filter/2.0/filterAll.xsd">
<fes:PropertyIsEqualTo>
<fes:ValueReference>stadsdeel/naam</fes:ValueReference>
<fes:Literal>Centrum</fes:Literal>
</fes:PropertyIsEqualTo>
</fes:Filter>
When a geometry filter is included, this also requires the GML namespace:
<fes:Filter
xmlns:fes="http://www.opengis.net/fes/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/fes/2.0
http://schemas.opengis.net/filter/2.0/filterAll.xsd
http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd">
<fes:BBOX>
<gml:Polygon gml:id="P1" srsName="http://www.opengis.net/def/crs/epsg/0/4326">
<gml:exterior>
<gml:LinearRing>
<gml:posList>10 10 20 20 30 30 40 40 10 10</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</fes:BBOX>
</fes:Filter>
According to the XML rules, the “fes” namespace alias can be renamed here
or omitted if only xmlns="..." is used instead of xmlns:fes="...".
Older Filter Syntax¶
Several existing clients still use other WFS 1 elements, such as <PropertyName> instead of
of <ValueReference>. For compatibility this tag is also supported.
The WFS 1 expressions <Add>, <Sub>, <Mul> and <Div> are also implemented
to support arithmetic operations from QGis (addition, subtraction, multiplication and division).