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?

  • What are your requirements for the shapefile as far as attributes go? – blah238 Sep 11 '13 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 Sep 11 '13 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 Sep 12 '13 at 5:09
4

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)
  • 1
    +1 Nice, always good to see a sample put out to give others a good place to think from... – D.E.Wright Sep 11 '13 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 Sep 16 '13 at 7:30
  • How should they be included? I think you have enough to go on. If not, ask another question. – blah238 Sep 16 '13 at 9:00
  • @blah238 Maybe you can help with the encode here? – JJD Apr 11 '14 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, privacy policy and cookie policy

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