You have seen how to send WPS request with the process builder, but what if you want to incorporate WPS capabilities in an external program?
In this recipe, you will create requests with XML and send them to GeoServer using the Python programming language and a shell utility cURL. Python is a programming language known for its simplicity and code readability, and is therefore very easy to use when creating small programs.
The cURL project is a library and a command-line tool that can easily be incorporated in simple shell scripts (it can also be used as a library by developers).
Both tools allow users to concentrate on what the program should do, rather than be distracted by a complex syntax.
In this chapter, it is assumed that you have a working installation of Python and cURL. If you are using a Linux box, it is quite probable you have both already installed and configured, or you can rely on your distribution package system to install a recent release.
For Windows, you can get Python from the project site at http://python.org/.
cURL is available as a source for those who are brave or as a binary packages from http://curl.haxx.se/download.html.
In order to make your experience with Python more smooth, you will use the Requests
library. It is a powerful HTTP protocol library and you can use it inside any Python program, leveraging on its powerful objects to interact with the HTTP protocol.
query.xml
.query.xml
file. Use cURL to send this request to GeoServer and save the result in an XML file called results.xml
.$ curl -XPOST -H 'Content-type: text/xml' -d @query.xml http://localhost/geoserver/wps -o results.xml
results.xml
file with an editor and look at its content. It should be a GML containing a line feature for the M11 highway, as shown in the following fragment:<feature:geom><gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:lineStringMember><gml:LineString><gml:coordinates>0.129189167383835,51.70460802098098 0.14964133470251184,51.75797266063622 0.16842512784744912,51.85780385442065 0.17149353629286423,51.86688366002006 0.19242696539243198,51.904635000808085 0.1941740914939558,51.909010107907065 0.19534662019648152,51.91370313945523 0.19576663047798348,51.918463255978914 0.1954574562429876,51.92808265812053 0.19491494296271483,51.93195316953409 0.19387075073509408,51.93577117966247 0.17697408711884677,51.98231648571944 0.16511754688062297,52.04905728614528 0.16157954360658522,52.06182093192203 0.15678734296417218,52.07415581720307 0.15397560746856342,52.079397195507646 0.14318367662442455,52.09364837769804</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></feature:geom>
$ python Python 2.7.3 (default, Sep 26 2013, 20:03:06) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import requests >>> >>> myUrl = 'http://localhost/geoserver/wps' >>> file = open('query.xml','r') >>> payload = file.read() >>> headers = {'Content-type': 'text/xml'} >>> resp = requests.post(myUrl, auth=('',''), data=payload, headers=headers) >>> resp.status_code 200
response.text
method is what you are looking for, let's save the result in a file. The code is as follows:>>> file = open('results.xml','w') >>> file.write(resp.text) >>> file.close()
You have seen two examples on how to interact with WPS from an external application. For the sake of simplicity, we choose Python and cURL, but, of course, you can perform the same task from any programming or scripting language.
You always need to build an XML request, send it via HTTP to GeoServer, and then parse the result, which is usually again an XML file.
Some times, it is more useful to return the result in a different form, such as JSON for web development. Try, for instance, to execute a gs:Query
operation and change the process output type to application/zip
. You will be delivered a ZIP compressed archive containing a shapefile with the features extracted by your filter.
You're not limited in the number of process that can be chained, so let's try a more complex task.
You want to find which features from the populated places layer that are within a 10-km distance from the M11 highway in England.
We already performed a similar process; this time we need to create a buffer geometry, which we'll use to select features within a distance from the specified road.
Let's start with it. You need to create a new XML file for the request. You will use again the process builder. What are the operations required?
The first one is gs:Clip
, which extracts features from the NaturalEarth:populatedplaces
layer. So, set the clip geometry to SUBPROCESS and select JTS:Buffer.
The input geometry for the buffer operation is gs:CollectGeometries
.
The final operation is gs:Query
, which will perform the extraction from the NaturalEarth:roads
layer with the following where
clause:
routeraw = 'M11'
Don't forget to set the distance for the buffer operation, both layers contain the LAT-LONG
geometries, so set the distance to 0.3 degrees.
When you're done, you will have an XML file chaining all processes.
Save it in the buffer.xml
file and execute the process using the following command:
$ curl -XPOST -H 'Content-type: text/xml' -d @buffer.xml http://localhost/geoserver/wps -o results.xml
If you are successful, your result.xml
file should contain several features in a form that looks like the following snippet:
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:feature="http://www.naturalearthdata.com/" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"> <gml:boundedBy> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coord> <gml:X>-0.118667702475932</gml:X> <gml:Y>51.5019405883275</gml:Y> </gml:coord> <gml:coord> <gml:X>0.11662308615098</gml:X> <gml:Y>52.2003912547825</gml:Y> </gml:coord> </gml:Box> </gml:boundedBy> <gml:featureMember> … <feature:geom> <gml:Point> <gml:coord> <gml:X>0.11662308615098027</gml:X> <gml:Y>52.20039125478246</gml:Y> </gml:coord> </gml:Point> </feature:geom> </feature:populatedplaces> </gml:featureMember> <gml:featureMember> … </wfs:FeatureCollection>
3.142.42.176