3

Based on the answers below I decided to do some programming. I'll be using GEOtools for this, a java lib: http://www.geotools.org/

I have the following XML:

<shapes xmlns="http://www.meteogroup-maritime.com/spos/GISLayer" 
    name="Load line zones" transparency="50" onland="false">

 <shape id="0" description="SUMMER ZONE" color="#FFFFC90E">
   <polygon>
    <location lat="35" lon="-180"/>
       ....
    <location lat="-33" lon="-170"/>
    <location lat="-47" lon="-180"/>
   </polygon>

   <label lat="29" lon="-45" text="SUMMER ZONE" />
   <label lat="-30" lon="-153" text="SUMMER ZONE" />
 </shape>

  ...

</shapes>

I want to turn this data into a shapefile, preferably by using existing software, although I don't mind scripting.

How can I do this?

3
  • What are your requirements for the shapefile as far as attributes go?
    – blah238
    Commented Sep 11, 2013 at 17:01
  • Also do you have an example demonstrating how interior rings are handled, or are all the polygons in the source data simple, single-ringed polygons?
    – blah238
    Commented Sep 11, 2013 at 17:12
  • I clarified the question to focus more on the scripting aspect since no desktop software will accept arbitrary XML. It must conform to a supported schema, such as GML or KML.
    – blah238
    Commented Sep 12, 2013 at 5:09

2 Answers 2

5

If you are comfortable with Python, you could use ElementTree to parse the XML and pyshp to create the shapefile.

Here is something you can start with:

from xml.etree import ElementTree
import shapefile
import os

xml_file = 'input.xml'
shape_file = 'output.shp'
projection = 'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]'

tree = ElementTree.parse(xml_file)
w = shapefile.Writer(shapefile.POLYGON)

# create fields
w.field('ID', 'N', 6)
w.field('DESCRIP')

root = tree.getroot()
shapes = root.getchildren()

for shape in shapes:
    # assumes single-part, single-ring polygons
    part = []
    locations = shape[0].getchildren()
    for location in locations:
        # specify coordinates in X,Y order (longitude, latitude)
        part.append([float(location.get('lon')), float(location.get('lat'))])
    w.poly(parts=[part])

    # copy attributes
    w.record(int(shape.get('id')), shape.get('description'))
w.save(shape_file)

# create the PRJ file
with open(os.path.splitext(shape_file)[0] + os.extsep + 'prj', 'w') as prj:
    prj.write(projection)
4
  • 1
    +1 Nice, always good to see a sample put out to give others a good place to think from...
    – D.E.Wright
    Commented Sep 11, 2013 at 19:07
  • We decided to settle for pyshp after all. But could you shed some light about how to include the labels in the shapefile?
    – jorrebor
    Commented Sep 16, 2013 at 7:30
  • How should they be included? I think you have enough to go on. If not, ask another question.
    – blah238
    Commented Sep 16, 2013 at 9:00
  • @blah238 Maybe you can help with the encode here?
    – JJD
    Commented Apr 11, 2014 at 13:00
3

I wrote the reply at the same time as blah238 so I modified it consequently.

The problem is more complex because you need to:

  • "learn" the structure of the XML file to extract the data as:

    • lat="35" lon="-180" from the location tag = the vertices of the polygon (y, x);
  • rebuild the polygon in a text format with:

    • text or list: (-180, 35), (-170, -33),..., (-153, -30)
    • WKT: ('POLYGON ((-180 35, -170 -33, ..., -153 -30))' )
    • GeoJSON : ({"type": "Polygon", "coordinates": [[ [-180.0, 35.0], ..., [-153.0, -30.0]]]})

I do not know what application could do so. They generally process XML files with known schemas.

The only solution I see is with a Python script as blah238 propose:

  1. process the XML file with a module like ElementTree (see blah238 script above)

  2. build the geometry and create the shapefile with modules like:

Pyshp (another solution with directly a Polygon)

import shapefile
w = shapefile.Writer(shapefile.POLYGON)
# geometry
w.poly(parts=[[[-180, 35],[-170, -33],..,[-153, -30]]])
# fields
w.field('FIRST_FLD','C','40')
....
w.record('one', )
w.save('polygon')

Fiona and shapely or PyGeoif

import fiona
from shapely.geometry import Polygon, mapping
polygon = Polygon([(-180, 35), (-170, -33),..., (-153, -30)])
# schema of the shapefile
schema = {'geometry': 'Polygon','properties': {'FIRST_FLD': 'char'}}
# write the shapefile
with fiona.collection('polygon.shp', 'w', 'ESRI Shapefile', schema) as layer:
    feature = {}
    feature['geometry'] = mapping(polygon) 
    feature['properties'] = {'FIRST_FLD': ...}
    layer.write(feature)

Osgeo (GDAL/OGR)

see Python GDAL/OGR Cookbook 1.0 documentation

You have the choice

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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