[GIS] Programmatically converting arbitrary XML data to shapefile

convertgeotoolsjavashapefilexml

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?

Best Answer

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)