-
Notifications
You must be signed in to change notification settings - Fork 7
/
kml.py
125 lines (108 loc) · 4.75 KB
/
kml.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""
Functions and factories for KML elements
"""
def kml_ns(element):
return element.tag.split('}')[0][1:]
def findall_placemarks(element):
return element.findall('*/{%s}Placemark' % kml_ns(element))
def element(context, ob, **kw):
"""Make a KML element from an object that provides the Python geo
interface.
Calls context.makeelement and fleshes out the new element using properties
of the object or keyword arguments.
KML Placemark names derive from object 'title' properties or a 'name'
argument. Snippets derive from object 'summary' properties or a 'snippet'
argument. Descriptions derive from object 'content' properties or a
'description' argument.
Example:
>>> kml = '<kml xmlns="http://www.opengis.net/kml/2.2"><Document></Document></kml>'
>>> from xml.etree import ElementTree
>>> tree = ElementTree.fromstring(kml)
>>> doc = tree[0]
>>> doc # doctest: +ELLIPSIS
<Element {http://www.opengis.net/kml/2.2}Document at ...>
First, with a geometry:
>>> from keytree.kml import element
>>> from keytree.model import Geometry
>>> g = Geometry('Point', (0.0, 0.0))
>>> elem = element(doc, g)
>>> import pprint
>>> pprint.pprint((elem.tag, elem.text, list(elem))) # doctest: +ELLIPSIS
('{http://www.opengis.net/kml/2.2}Point',
None,
[<Element {http://www.opengis.net/kml/2.2}coordinates at ...>])
Placemark:
>>> from keytree.model import Feature
>>> f = Feature('1', geometry=g, title='Feature 1', summary='The first feature', content='Blah, blah, blah.')
>>> elem = element(doc, f)
>>> import pprint
>>> pprint.pprint((elem.tag, elem.text, list(elem))) # doctest: +ELLIPSIS
('{http://www.opengis.net/kml/2.2}Placemark',
None,
[<Element {http://www.opengis.net/kml/2.2}name at ...>,
<Element {http://www.opengis.net/kml/2.2}Snippet at ...>,
<Element {http://www.opengis.net/kml/2.2}description at ...>,
<Element {http://www.opengis.net/kml/2.2}Point at ...>])
>>> pprint.pprint(list((e.tag, e.text, list(e)) for e in elem)) # doctest: +ELLIPSIS
[('{http://www.opengis.net/kml/2.2}name', 'Feature 1', []),
('{http://www.opengis.net/kml/2.2}Snippet', 'The first feature', []),
('{http://www.opengis.net/kml/2.2}description', 'Blah, blah, blah.', []),
('{http://www.opengis.net/kml/2.2}Point',
None,
[<Element {http://www.opengis.net/kml/2.2}coordinates at ...>])]
"""
ns = context.tag.split('}')[0][1:]
geo = getattr(ob, '__geo_interface__', ob)
if geo.has_key('id') or geo.has_key('geometry'): # is a feature
elem = placemark_element(context, ns, geo, **kw)
elif geo.has_key('type'): # is a geometry
elem = geometry_element(context, ns, geo)
return elem
def subelement(parent, ob, **kw):
"""Append new element to the parent element.
"""
parent.append(element(parent, ob, **kw))
def coords_to_kml(geom):
gtype = geom['type']
if gtype == 'Point':
coords = (geom['coordinates'],)
elif gtype == 'Polygon':
coords = geom['coordinates'][0]
else:
coords = geom['coordinates']
if len(coords[0]) == 2:
tuples = ('%f,%f,0.0' % tuple(c) for c in coords)
elif len(coords[0]) == 3:
tuples = ('%f,%f,%f' % tuple(c) for c in coords)
else:
raise ValueError, "Invalid dimensions"
return ' '.join(tuples)
def geometry_element(context, ns, ob):
gtype = ob['type']
geom_elem = context.makeelement('{%s}%s' % (ns, gtype), {})
if gtype in ['Point', 'LineString']:
sub_coords_elem = context.makeelement('{%s}coordinates' % ns, {})
sub_coords_elem.text = coords_to_kml(ob)
else:
pass
geom_elem.append(sub_coords_elem)
return geom_elem
def placemark_element(context, ns, ob, **kw):
pm_elem = context.makeelement('{%s}Placemark' % ns, {})
pm_elem.attrib['id'] = ob.get('id') or kw.get('id')
sub_name_elem = context.makeelement('{%s}name' % ns, {})
sub_name_elem.text = kw.get('name') or ob.get(
'properties', {}).get('title')
pm_elem.append(sub_name_elem)
sub_snippet_elem = context.makeelement('{%s}Snippet' % ns, {})
sub_snippet_elem.text = kw.get('snippet') or ob.get(
'properties', {}).get('description')
pm_elem.append(sub_snippet_elem)
sub_description_elem = context.makeelement('{%s}description' % ns, {})
sub_description_elem.text = kw.get('description') or ob.get(
'properties', {}).get('content')
pm_elem.append(sub_description_elem)
if ob.has_key('geometry'):
sub_geom_elem = geometry_element(context, ns, ob.get('geometry'))
pm_elem.append(sub_geom_elem)
return pm_elem