0

Does anyone have an idea how to convert gml to geojson (with attributes) using Python with ogr bindings?

It should be possible to transform geometries to different coordinate system.

I can not use external ogr2ogr, but pure Python (no fiona).

closed as off-topic by PolyGeo Jun 23 '18 at 5:47

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "When seeking help to debug/write/improve code always provide the desired behavior, a specific problem/error and the shortest code (as formatted text, not pictures) needed to reproduce it in the question body. Providing a clear problem statement and a code attempt helps others to help you." – PolyGeo
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    Do you have a sample GML file? Are the attribute names always the same or are they dynamic? – ustroetz Nov 19 '13 at 17:55
  • How can you use OGR's Python bindings (which are not pure Python, they involve a C extension module) but not ogr2ogr? – sgillies Nov 19 '13 at 20:10
1

The following code does the geometry conversion task. You have to specify the input and out filename, as well as their EPSGs.

import ogr,os,osr

def main(inputGMLfn,inputEPSG,outputGeoJSONfn,outputEPSG):
    inputDs = ogr.Open(inputGMLfn)
    inLayer = inputDs.GetLayer() 

    outDriver = ogr.GetDriverByName('GeoJSON')

    if os.path.exists(outputGeoJSONfn):
        outDriver.DeleteDataSource(outputGeoJSONfn)

    outputDs = outDriver.CreateDataSource(outputGeoJSONfn)
    outLayer = outputDs.CreateLayer(outputGeoJSONfn, geom_type=ogr.wkbLineString )

    # create the input SpatialReference
    sourceSR = osr.SpatialReference()
    sourceSR.ImportFromEPSG(inputEPSG)  

    # create the output SpatialReference
    targetSR = osr.SpatialReference()
    targetSR.ImportFromEPSG(outputEPSG)

    # create transform    
    coordTrans = osr.CoordinateTransformation(sourceSR,targetSR)

    # Get the output Layer's Feature Definition
    featureDefn = outLayer.GetLayerDefn()

    # loop through the input features
    inFeature = inLayer.GetNextFeature()
    while inFeature:

        # get the input geometry
        geom = inFeature.GetGeometryRef()
        # reproject the geometry
        geom.Transform(coordTrans)

        # create a new feature
        outFeature = ogr.Feature(featureDefn)

        # set new geometry
        outFeature.SetGeometry(geom)
        # Add new feature to output Layer
        outLayer.CreateFeature(outFeature)

        # Get the next input feature
        inFeature = inLayer.GetNextFeature()



if __name__ == "__main__":
    inputEPSG = 2964
    outputEPSG = 4326
    inputGMLfn = 'test.gml'
    outputGeoJSONfn = 'test.geojson'

    main(inputGMLfn,inputEPSG,outputGeoJSONfn,outputEPSG)
  • A few pointers. Using Destroy does nothing, but never use Destroy(). Also, you are missing some imports. – Mike T Nov 19 '13 at 18:57
  • Thanks @MikeToews for those hints. I couldn't get the inLayer.GetSpatialRef() to work. I returned None even though my test.gml has a spatial reference. Do you know why? – ustroetz Nov 19 '13 at 19:23
1

It is much easier since the ogr module has the function feature.ExportToJson() (= GeoJSON)

So we can apply the the geo_interface (GeoJSON-like) protocol proposed by Sean Gillies (see also Python geo_interface Applications for other modules as Shapely, PyShp (shapefile), PySAL, PyQGIS, ...)

def records(file):  
    # generator 
    reader = ogr.Open(file)
    layer = reader.GetLayer()
    for i in range(layer.GetFeatureCount()):
        feature = layer.GetFeature(i)
        yield json.loads(feature.ExportToJson())

from osgeo import ogr
elem = records('test.gml')
elem.next()
{u'geometry': {u'type': u'LineString', u'coordinates': [[-0.95694033573220805, -0.290284677254464], [-0.28378378378378399, 0.33648648648648599], [0.39729729729729701, -0.064864864864864993], [0.99324324324324298, 0.48648648648648701]]}, u'type': u'Feature', u'properties': {u'id': None, u'fid': u'test.0'}, u'id': 0}

Write the GeoJSON file:

# all features of the GML file:
features = [feat for feat in records("test.gml')]
# creation of the dictionary  
my_layer = {
    "type": "FeatureCollection",
     "features": features}
print my_layer
{'type': 'FeatureCollection', 'features': [{u'geometry': {u'type': u'LineString', u'coordinates': [[-0.95694033573220805, -0.290284677254464], [-0.28378378378378399, 0.33648648648648599], [0.39729729729729701, -0.064864864864864993], [0.99324324324324298, 0.48648648648648701]]}, u'type': u'Feature', u'properties': {u'id': None, u'fid': u'essai.0'}, u'id': 0}, {u'geometry': {u'type': u'LineString', u'coordinates': [[0.51422274119435496, 0.55873852866636098], [0.41724639928901802, 0.392759789636073], [0.32586484633975898, 0.39648964894012401], [0.21583399687024199, 0.366650774507713], [0.219563856174294, 0.30324316633883902]]}, u'type': u'Feature', u'properties': {u'id': None, u'fid': u'essai.1'}, u'id': 1}, {u'geometry': {u'type': u'LineString', u'coordinates': [[-0.37907856212595797, -0.028714311721736999], [-0.22428940100782399, -0.19842291005607601], [-0.10679883293020501, -0.32523812639382399], [-0.034066576501201998, -0.19469305075202401], [0.018151453755517001, -0.142475020495305], [0.083423991576417, -0.20215276936012699]]}, u'type': u'Feature', u'properties': {u'id': None, u'fid': u'essai.2'}, u'id': 2}, {u'geometry': {u'type': u'LineString', u'coordinates': [[-0.58235589419676004, 0.37597542276784202], [-0.37534870282190602, 0.52143993562584701], [-0.23361404926795301, 0.467356975717101], [-0.047121084065381999, 0.40021950824417601], [0.075964272968313998, 0.493465990845461]]}, u'type': u'Feature', u'properties': {u'id': None, u'fid': u'essai.3'}, u'id': 3}]}

import json
# json features
print json.dumps(my_layer)
'{"type": "FeatureCollection",.....

# write the GeoJSON file
with open("test.geojson", "w") as outfile:
    json.dump(my_layer,outfile)

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