Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

i am wondering whether there's Python open-source GIS lib which has APIs to support call WMS/WFS from another GIS server (e.g., GeoServer) and then save the response data(WMS Basemap and WFS layer) as pictures.

any recommendations?

thanks for any inputs!

UPDATE:

what I am trying to do is a Map Printing service, by using OpenLayers as the front-end and Django as the server; Client user set the extent and layers and then send the print request (which refers to the parameters, i.e., map extent, names of layers) to server, then server takes over this request and call WMS/WFS again by using request parameters, save the response as PDF, export this PDF link to client.

The difficult part is that how the server call WMS/WFS and combine/overlay these responses together (i.e., put these map/layers together, since WMS is usually the base map, WFS points to the feature layers), finally save this combined object as Image.

in current answers, urllib seems a good one, but i am not sure how to combine these responses (WMS, WFSs) together; OWSLib also seems another good option, but it indicates it's a client programming tool, I am a little confused that whether it's appropriate for my use...

any other further inputs???

appreciate!

share|improve this question
    
I don't think there is, but its a good idea! –  OptimizePrime Nov 16 '11 at 21:54
    
Just noticed the updated question is a related to my question about combining WMS into PDF. –  MarkJ Nov 15 '12 at 18:04

4 Answers 4

up vote 12 down vote accepted

There is OWSLib which should provide exactly what you need.

OWSLib is a Python package for client programming with Open Geospatial Consortium (OGC) web service (hence OWS) interface standards, and their related content models.

OWSLib provides a common API for accessing service metadata and wrappers for numerous OGC Web Service interfaces.

Documentation and examples here. Client in this context means it is a client application to a WMS/WFS server - it can be run on a server if required.

After you added more details to your answer it looks like the MapFish print application fits your needs exactly. It is a Java application that can be integrated with OpenLayers and stitches tiles, WMS, WFS etc. together and produces a PDF.

As it is a command line application it can be manipulated with a Python wrapper. See following links for more details:

http://geographika.co.uk/mapfish-print-module-for-iis

https://github.com/amercader/MapFish-Print-IIS

share|improve this answer
1  
Thanks for the pointer to OWSLib, I'd never heard of it. –  Luke Nov 18 '11 at 0:55

You can use the python urllib library to call a WMS directly and write the response out to a file. There is a decent example of using urllib in this answer. Just replace the URL with one for a WMS, e.g. http://some.wms.service?request=GetMap&VERSION=1.1.1&BBOX=141.00,-29.00,141.80,-28.40&SRS=EPSG:4326&LAYERS=LANDSAT_MOSAIC&WIDTH=800&HEIGHT=600&FORMAT=image/png.

You can also use the GDAL library to access WMS (http://www.gdal.org/frmt_wms.html) and the OGR library to access WFS (http://www.gdal.org/ogr/drv_wfs.html)

If you wanted to create a picture of the WFS, you could use the gdal.RasterizeLayer function to create a jpg. There is an example here.

share|improve this answer

You could use GeoTools to fetch the data from WMS/WFS servers and render to a Java graphics object. Then something like iText can convert to a pdf.

If you really have to use Python I expect you could use a wrapper to manage it all.

share|improve this answer
    
thanks. but i just want to use Python... –  Simon Nov 17 '11 at 16:16

Here Is a simple example. On server side:

def get_wfs():
    '''
    Get data from wfs server. Example url is:
    http://192.168.0.1:8080/geoserver/wfs?request=GetFeature&version=1.0.0&service=WFS&typeName=ChistaWS:Chista_new_POIs&maxfeatures=20&srsname=EPSG:4326&outputFormat=json
    We can add CQL filter like this:
    CQL_FILTER=name LIKE 'A%25'
    or
    CQL_FILTER=type=1913

    '''
    cql = ''
    if request.vars.cql:
        cql = urllib.quote_plus(request.vars.cql)
    req = 'GetFeature' # request
    version = '1.0.0'
    service = 'WFS'
    typeName = 'Test:Test_Places'
    maxfeatures = 200000
    if request.vars.mf:
        maxfeatures = request.vars.mf
    srsname = 'EPSG:4326'
    outputFormat = 'json'   
    # format_options = 'callback:getLayerFeatures_MY'
    wfs_url = '%s?request=%s&version=%s&service=%s&typeName=%s&maxfeatures=%s&srsname=%s&outputFormat=%s' % \
                (wfs_server, req, version, service, typeName,\
                 maxfeatures, srsname, outputFormat)
    if cql:
        # print cql
        wfs_url += '&CQL_FILTER=%s'%cql
    # print wfs_url
    try:
        jsonp = urllib2.urlopen(wfs_url).read()  # Get the raw server data
    except urllib2.HTTPError:
        return 'WFS Server <a target="_new" href="%s">%s</a> is down!' % (wfs_server, wfs_server)
    # return jsonp
    # try:
        # apijson = jsonp[ jsonp.index("(") + 1 : jsonp.rindex(")") ]
    # except ValueError:
    apijson = jsonp
    try:
        data = sj.loads(apijson)
    except sj.JSONDecodeError:
        return 'Can not parse data. No JSON! here is the data: <pre>%s</pre>' % apijson
    # return data
    features =[{
            'name':i['properties']['name'],
            'type':i['properties']['type'],
            'coordinates':i['geometry']['coordinates'],
            } for i in data['features']]
    # features =[i for i in data['features']]
    # return dict(features=features)
    return {'result':features, 'length':len(features)}

And in client side using jquery:

$.ajax({
dataType : 'json',
url: wfsurl,
success  : function (response) {
if (response.length>0){
$('#'+subitem).empty();
for (var i = 0, len = response.length; i < len; i++) {
name = response.result[i].name;
lng = response.result[i].coordinates[0];
lat = response.result[i].coordinates[1];
// console.log(name, lng, lat)
html = '<li class="li-subitem"><a onclick="lazyview($(this));" lat="'+lat+'" lng="'+lng+'">'+name+'</a></li>';
$('#'+subitem).append(html);
}}
else{
$('#'+subitem).toggle(100);
}}});
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.