== Shapefile Layers == [[TOC]] Upload a Shapefile to display on the map. Options: * Import Features * Can use the Python bindings for GDAL/OGR as we do for the [wiki:UserGuidelinesGISData#GADM GADM importer] * Option A: Import just to display as an overlay * Option B: Import into Native Tables via an XSL Transform * See below for code to convert SHP to an lxml.etree * Upload to !GeoServer co-app & add a layer which accesses this via WMS/WFS (although the UI should show in the 'Shapefiles layers' section) * http://docs.geoserver.org/2.0.0/user/extensions/rest/rest-config-examples-curl.html#uploading-a-shapefile * https://github.com/dwins/gsconfig.py We can include [http://thematicmapping.org/downloads/world_borders.php TM_WORLD_BORDERS-0.3.zip] as a useful base/sample Alternative options: * Integrate [http://featureserver.org FeatureServer] * Integrate [http://ogre.adc4gis.com Ogre] - convert to GeoJSON for easy import * Build a .map file for [http://mapserver.org MapServer] using [http://mapserver.org/mapscript Python MapScript] === Import to display as an Overlay === Work on this has started as gis_layer_shapefile in Trunk ==== !ToDo ==== * Needs styling * onaccept to write any modified data back to the attached shapefile === Import into native Tables === Paul Porthouse [2013-04-27 at the [http://mapaction.org MapAction] Hackathon]: Our idea is to use a basic web form with a file upload (similar to the Import from OpenStreetMap) where you can select which ShapeFile to use. You should also be able to set basic information including database connection details. This will then upload the shape and use OGR2OGR to convert the ShapeFile to geometry and import it into the specified database. A basic OGR2OGR which should accomplish the import is: {{{OGR2OGR -overwrite -f "PostgreSQL" PG:dbname=databaseconnection shapefile.sh}}} This could be called directly from Python by running it as a sub process. Alternatively, to use Python bindings, you could perform the import using GDAL which would allow more control over the import directly within Python, but should still handle the import into Postgres. {{{ ''' Dump the contents of a shapefile to an lxml etree object Assumes the shapefile is encoded in UTF-8 format Tested with TM_WORLD_BORDERS-0.3.shp ''' import sys import ogr import os from lxml import etree if len(sys.argv) != 2: print "Usage: importshape.py filename" sys.exit(0) shapefilename = sys.argv[1] layername = os.path.splitext(os.path.basename(shapefilename))[0] #Create the datasource ds = ogr.Open( shapefilename ) #Open the shapefile if ds is None: print "Open failed.\n" sys.exit(0) #Get the layer and iterate through the features lyr = ds.GetLayer(0) root = etree.Element("shapefile",name=layername) for feat in lyr: featurenode = etree.SubElement(root,"feature") feat_defn = lyr.GetLayerDefn() for i in range(feat_defn.GetFieldCount()): field_defn = feat_defn.GetFieldDefn(i) fieldnode = etree.SubElement(featurenode,field_defn.GetName()) if field_defn.GetType() == ogr.OFTInteger: fieldnode.text = str(feat.GetFieldAsInteger(i)) elif field_defn.GetType() == ogr.OFTReal: fieldnode.text = str(feat.GetFieldAsDouble(i)) elif field_defn.GetType() == ogr.OFTString: FieldString = str(feat.GetFieldAsString(i)) fieldnode.text = FieldString.decode(encoding='UTF-8',errors='strict') wktnode = etree.SubElement(featurenode,"wkt") geom = feat.GetGeometryRef() wktnode.text = geom.ExportToWkt() #Test the etree object xmlString = etree.tostring(root, pretty_print=True) f = open("test.xml","w") f.write(xmlString) }}} ---- [wiki:BluePrint/GIS GIS BluePrints]