Accessing xServer internet from Python

  • This section explains how to request xLocateServer with python inside QGIS. The result of the request will be displayed as a layer on the map.

Add Python HTTP Requests to QGIS

  • The xServer python script uses the requests extension to call xServer internet. You can get it from the GitHub repository https://github.com/kennethreitz/requests

    Just download it and add the folder requests to the QGIS Python folder, e.g. C:\Program Files\QGIS Brighton\apps\Python27

Add the script to the processing toolbox

  • You can start a script within QGIS by adding a .py file to the processing toolbox.

    • Paste the script code below to a file named xlocate_findaddress.py
    • Copy the file to the folder <User Folder>\.qgis2\processing\scripts
    • Open the processing toolbox under Processing->Toolbox
    • Now you can start the script by double-clicking on the item Scripts->[PTV scripts]->xlocate_findaddress in the tree.

Run the script and validate the result

  • Enter your token into the dialog, set the address and press Run. A new layer output_geoc is added to the map. The layer displays the result locations of the geocoding. You can also open the result as a table by right-clicking on the layer and opening the attribute table.

#a simple geocoding request that displays the result as a QGIS layer
##[PTV scripts]=group
##cluster=string eu-n-test
##token=string enter your token here
##country=string
##address=string Neustadt
##output_geoc=output vector

import fileinput
import sys, os, json, requests
from PyQt4.QtCore import *
from qgis.core import *
from qgis.utils import *
from requests.auth import HTTPBasicAuth

# our geocoding function
def findAddressByText(url, token, country, address):

        header = {'content-type': 'application/json'}
        request = { "address": address,
            "country": country,
            "options": [],
            "sorting": [],
            "additionalFields": [],
            "callerContext": {
                "properties": [{"key": "CoordFormat","value": "OG_GEODECIMAL"},{"key": "Profile","value": "default"},{"key": "ResponseGeometry", "value": "WKT"}
            ]}
        }

        jsondata = json.dumps(request)
        jsonresp = requests.post(url = url, data = jsondata, headers = header, auth = HTTPBasicAuth('xtok', token))

        if jsonresp.status_code == 200:
            pyresp = json.loads(jsonresp.text)
            jsonresponse = pyresp["resultList"]

            return jsonresponse
        else:
            raise Exception("Web error " + str(jsonresp.status_code))

# build url
url = "https://xlocate-" + cluster + ".cloud.ptvgroup.com/xlocate/rs/XLocate/findAddressByText"

# invoke the geocoding
jsonresponse = findAddressByText(url, token, country, address)

# build the fields collection
fields = QgsFields()                                  # 2: Integer 6: Float  10: String
fields.append(QgsField("id", 2,"Integer"))
fields.append(QgsField("country", 10, "String", 32))
fields.append(QgsField("state", 10,"String", 128))
fields.append(QgsField("postcode", 10,"String", 12))
fields.append(QgsField("city", 10,"String", 128))
fields.append(QgsField("city2", 10,"String", 128))
fields.append(QgsField("street", 10,"String", 128))
fields.append(QgsField("houseNumber", 10,"String", 32))
fields.append(QgsField("adminRegion", 10,"String", 128))
fields.append(QgsField("totalScore", 2,"Integer"))

# create the output layer
outputLayer = QgsVectorFileWriter(output_geoc, None, fields, QGis.WKBPoint,QgsCoordinateReferenceSystem(4326))

# fill the layer data
count=0
for resultList in jsonresponse:
    count+=1
    country=resultList["country"]
    state=resultList["state"]
    postcode=resultList["postCode"]
    city=resultList["city"]
    city2=resultList["city2"]
    street=resultList["street"]
    housenumber=resultList["houseNumber"]
    score=resultList["totalScore"]
    adminRegion=resultList["adminRegion"]
    geomwkt=resultList["coordinates"]["wkt"]

    outFeat = QgsFeature()
    outFeat.setGeometry(QgsGeometry.fromWkt(geomwkt))
    outFeat.setAttributes([count, country, state, postcode, city, city2, street, housenumber, adminRegion, score])

    outputLayer.addFeature(outFeat)

progress.setText("Geocoding matches: " + str(count))
progress.setText("---------------------------------------")
del outputLayer