Keytree provides functions for reading and writing KML using the ElementTree API.
KML Placemark elements can be adapted to the Python geo interface and then used with packages like Shapely:
>>> data = """<?xml version="1.0" encoding="UTF-8"?>
... <kml xmlns="http://www.opengis.net/kml/2.2">
... <Document>
... <Placemark id="pm_1">
... <name>point</name>
... <Snippet>Point test</Snippet>
... <Point>
... <coordinates>
... -122.364383,37.824664,0
... </coordinates>
... </Point>
... </Placemark>
... </Document>
... </kml>
... """
>>> from xml.etree import ElementTree
>>> doc = ElementTree.fromstring(data)
>>> kmlns = doc.tag.split('}')[0][1:]
>>> placemarks = doc.findall('*/{%s}Placemark' % kmlns)
>>> p0 = placemarks[0]
>>> import keytree
>>> f = keytree.feature(p0)
>>> print f.id, f.properties.name, f.properties.snippet
pm_1, point, Point test
>>>
>>> from shapely.geometry import shape
>>> s = shape(f.geometry)
>>> print s.buffer(1.5).exterior.length
9.4209934708642571
Objects that provide the Python geo interface can also be converted to ElementTree API Elements:
>>> f = {
... 'id': 'pm_2',
... 'geometry': {
... 'type': 'Point',
... 'coordinates': (-122.364383, 37.824663999999999) },
... 'properties': {
... 'title': 'Feature 2',
... 'description': 'The second feature', }
The first argument to the keytree.element function is an XML context, the created element will have the same namespace as that element:
>>> data = """<?xml version="1.0" encoding="UTF-8"?>
... <kml xmlns="http://www.opengis.net/kml/2.2">
... <Document>
... </Document>
... </kml>
... """
>>> doc = ElementTree.fromstring(data)
>>> elem = element(doc, f)
>>> print elem
<Element {http://www.opengis.net/kml/2.2}Placemark at ...>
>>> pprint(list(elem))
[<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 ...>]
The created element is not automatically added to the KML context and must be appended to its proper Document or Folder:
>>> doc[0].append(elem)
>>> print etree.tostring(doc)
<ns0:kml xmlns:ns0="http://www.opengis.net/kml/2.2">
<ns0:Document>
<ns0:Placemark id="pm_2">
<ns0:name>Number 2</ns0:name>
<ns0:Snippet>Placemark number 2</ns0:Snippet>
<ns0:description />
<ns0:Point>
<ns0:coordinates>0.000000,0.000000,0.0</ns0:coordinates>
</ns0:Point>
</ns0:Placemark>
</ns0:Document>
</ns0:kml>
The keytree.kml module contains a few useful utility functions:
>>> from keytree.kml import kml_ns, findall_placemarks
>>> print kml_ns(doc)
{http://www.opengis.net/kml/2.2}
>>> findall_placemarks(doc)
[<Element {http://www.opengis.net/kml/2.2}Placemark at ...>]