Accessing WFS Data ================== This is a brief explanation of using a WFS server. .. contents:: :local: 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: :samp:`?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 :samp:`TYPENAMES={feature-name}` and :samp:`OUTPUTFORMAT={format}` should be included. For example: * `...&TYPENAMES=wijken&OUTPUTFORMAT=geojson `_ * `...&TYPENAMES=wijken&OUTPUTFORMAT=csv `_ .. 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: * `...&PROPERTYNAME=app:naam,app:code `_ * `...&PROPERTYNAME=app:naam,app:code&OUTPUTFORMAT=geojson `_ .. tip:: This project also supports using ``PROPERTYNAME`` for nested elements (:samp:`{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: .. code-block:: xml ligt_in_stadsdeel/naam Centrum 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: .. code-block:: xml 4.58565 52.03560 5.31360 52.48769 status 1 The ``RESOURCEID`` parameter has a ```` equivalent which can appear several times in the filter: .. code-block:: xml Complex Filters ~~~~~~~~~~~~~~~ The WFS Filter Encoding Standaard (FES) supports many operators. These tags are all supported: .. list-table:: :header-rows: 1 * - Element - SQL equivalent - Description * - ```` - :samp:`{a} == {b}` - Values must be equal. * - ```` - :samp:`{a} != {b}` - Values must not be equal. * - ```` - :samp:`{a} < {b}` - Value 1 must be less than value 2. * - ```` - :samp:`{a} > {b}` - Value 1 must be greater than value 2. * - ```` - :samp:`{a} <= {b}` - Value 1 must be less than or equal to value 2. * - ```` - :samp:`{a} >= {b}` - Value 1 must be greater than or equal to value 2. * - ```` - :samp:`{a} BETWEEN {x} AND {y}` - Compares between ```` and ````, which both contain an expression. * - ```` - :samp:`{a} LIKE {b}` - Performs a wildcard comparison. * - ```` - :samp:`{a} IS NULL` - Value must be ``NULL`` (``xsi:nil="true"`` in XML). * - ```` - n.a. - Property may not exist (currently implemented as ````). * - ```` - :samp:`ST_Intersects({a}, {b})` - Geometry must be partly in value 2. The field name may be omitted to use the default. * - ```` - :samp:`ST_Contains({a}, {b})` - Geometry completely contains geometry 2, e.g. province contains city. * - ```` - :samp:`ST_Crosses({a}, {b})` - The geometries have some common interior points, e.g. two streets. * - ```` - :samp:`ST_Disjoint({a}, {b})` - The geometries are not connected in any way. * - ```` - :samp:`ST_Equals({a}, {b})` - The geometries are identical. * - ```` - :samp:`ST_Intersects({a}, {b})` - The geometries share some space. * - ```` - :samp:`ST_Touches({a}, {b})` - The edges of the geometries touch each other, e.g. country borders. * - ```` - :samp:`ST_Overlaps({a}, {b})` - The geometries overlap. * - ```` - :samp:`ST_Within({a}, {b})` - Geometry is completely contained within geometry 2, e.g. city within province. * - ```` - :samp:`ST_DWithin({a}, {b}, {d})` - The geometries are within a given distance of each other. * - ```` - :samp:`NOT ST_DWithin({a}, {b}, {d})` - The geometries are not within a given distance. * - ```` - :samp:`{a} AND {b} AND {c}` - The nested operators must all be true. * - ```` - :samp:`{a} OR {b} OR {c}` - Only one of the nested operators has to be true. * - ```` - :samp:`NOT {a}` - Negation of the nested operators. * - ```` - :samp:`table.id == {value}` / :samp:`table.id IN ({v1}, {v2}, ...)` - Searches for a feature as "type name.identifier". Combines multiple elements into an ``IN`` query. .. tip:: For the ```` 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 ````, ```` and ````), their mutual differences are particularly visible when comparing points with surfaces. Expressions in the Filter ~~~~~~~~~~~~~~~~~~~~~~~~~ Various expressions may be used as values: .. list-table:: :header-rows: 1 * - Expression - SQL equivalent - Description * - ```` - :samp:`"{field-name}"` - References a field. * - ```` - value - Literal value, can also be a GML-object. * - ```` - :samp:`{function-name}(..)` - Executes a function, such as ``abs``, ``sin``, ``strLength``. * - ```` - :samp:`{a} + {b}` - Addition (WFS 1 expression). * - ```` - :samp:`{a} - {b}` - Subtraction (WFS 1 expression). * - ```` - :samp:`{a} * {b}` - Multiplication (WFS 1 expression). * - ``
`` - :samp:`{a} / {b}` - Division (WFS 1 expression). This allows to create complex filters, such as: .. code-block:: xml status 1 container_type Other container_type Textile container_type Glass container_type Papier container_type Organic container_type Plastic .. _functions: Using Functions ~~~~~~~~~~~~~~~ Functions are executed in a ```` by using the tag ``..``. This can be used anywhere as an expression instead of a ```` or ````. Inside the function, the parameters are also given as expressions: a ````, ```` or new ````. As a simple example: .. code-block:: xml fieldname As expressions can be functions, the following filter is possible: .. code-block:: xml name 0 4 cafe Various functions are built-in available in the server, inspired by the filter functions found in `GeoServer `_: .. list-table:: String Functions :header-rows: 1 :widths: 40 30 30 * - Function - SQL equivalent - Description * - ``strConcat(string)`` - ``CONCAT()`` - Concatenates strings * - ``strIndexOf(string, substring)`` - ``STRPOS() - 1`` - Finds the text inside a string, 0-based index. * - ``strSubstring(string, begin, end)`` - ``SUBSTRING()`` - Removes characters before *begin* and after *end*. * - ``strSubstringStart(string, begin)`` - ``SUBSTRING()`` - Removes characters before *begin*, 0-based index. * - ``strToLowerCase(string)`` - ``LOWER()`` - Convert text to lowercase. * - ``strToUpperCase(string)`` - ``UPPER()`` - Convert text to uppercase. * - ``strTrim(string)`` - ``TRIM()`` - Remove white space at the beginning and end. * - ``strLength(string)`` - ``LENGTH()`` / ``CHAR_LENGTH()`` - Determines text length. * - ``length(string)`` - ``LENGTH()`` / ``CHAR_LENGTH()`` - Alias of ``strLength()``. .. list-table:: Math Number Functions :header-rows: 1 :widths: 40 30 30 * - Function - SQL equivalent - Description * - ``abs(number)`` - ``ABS()`` - Invert negative numbers. * - ``ceil(number)`` - ``CEIL()`` - Rounding up. * - ``floor(number)`` - ``FLOOR()`` - Rounding down. * - ``round(value)`` - ``ROUND()`` - Regular rounding. * - ``min(value1, value2)`` - ``LEAST()`` - Uses the smallest number. * - ``max(value1, value2)`` - ``GREATEST()`` - Uses the largest number. * - ``pow(base, exponent)`` - ``POWER()`` - Exponentiation * - ``exp(value)`` - ``EXP()`` - Exponent of 𝑒 (2,71828...; natural logarithm). * - ``log(value)`` - ``LOG()`` - Logarithm; inverse of an exponent. * - ``sqrt(value)`` - ``SQRT()`` - Square root, inverse of exponentiation. .. list-table:: Math Trigonometry Functions :header-rows: 1 :widths: 40 30 30 * - Function - SQL equivalent - Description * - ``acos(value)`` - ``ACOS()`` - Arccosine; inverse of cosine. * - ``asin(value)`` - ``ASIN()`` - Arcsine; inverse van sine. * - ``atan(value)`` - ``ATAN()`` - Arctangent; inverse of tangent. * - ``atan2(x, y)`` - ``ATAN2()`` - Arctangent, for usage outside the range of a circle. * - ``cos(radians)`` - ``COS()`` - Cosine * - ``sin(radians)`` - ``SIN()`` - Sine * - ``tan(radians)`` - ``TAN()`` - Tangent * - ``pi()`` - ``PI`` - The value of π (3,141592653...) * - ``toDegrees(radians)`` - ``DEGREES()`` - Conversion of radians to degrees. * - ``toRadians(degree)`` - ``RADIANS()`` - Conversion degrees to radians. .. list-table:: Geometric Functions :header-rows: 1 * - Function - SQL equivalent - Description * - ``area(geometry)`` - ``ST_Area()`` - Convert geometry to area. * - ``centroid(features)`` - ``ST_Centroid()`` - Return geometric center as "gravity point". * - ``difference(geometry1, geometry2)`` - ``ST_Difference()`` - Parts of geometry 1 that do not overlap with geometry 2. * - ``distance(geometry1, geometry2)`` - ``ST_Distance()`` - Minimum distance between 2 geometries. * - ``envelope(geometry)`` - ``ST_Envelope()`` - Convert geometry to bounding box. * - ``geomLength(geometry)`` - ``ST_Length()`` - The cartesian length for a linestring/curve. * - ``intersection(geometry1, geometry2)`` - ``ST_Intersection()`` - Parts of geometry 1 that overlap with geometry 2. * - ``isEmpty(geometry)`` - ``ST_IsEmpty()`` - Tests whether the geometry is empty. * - ``isValid(geometry)`` - ``ST_IsValid()`` - Tests whether the geometry is valid. * - ``numGeometries(geometry)`` - ``ST_NumGeometries()`` - Tests how many geometries are found in the collection. * - ``numPoints(geometry)`` - ``ST_NumPoints()`` - Tests how many points are found in a linestring. * - ``perimeter(geometry)`` - ``ST_Perimeter()`` - The 2D perimeter of the surface/polygon. * - ``symDifference(geometry1, geometry1)`` - ``ST_SymDifference()`` - Parts of geometry 1 and 2 that don't intersect. * - ``union(geometry1, geometry2)`` - ``ST_Union()`` - 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: .. code-block:: urlencoded ?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature &TYPENAMES=app:restaurant &FILTER=... &PROPERTYNAME=app:id,app:name,app:location &SORTBY=app:name ASC ...can also be defined as XML-encoded POST request: .. code-block:: xml app:id app:name app:location ... app:name ASC 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: .. code-block:: xml stadsdeel/naam Centrum When a geometry filter is included, this also requires the GML namespace: .. code-block:: xml 10 10 20 20 30 30 40 40 10 10 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 ```` instead of of ````. For compatibility this tag is also supported. The WFS 1 expressions ````, ````, ```` and ``
`` are also implemented to support arithmetic operations from QGis (addition, subtraction, multiplication and division).