"""
import sys
+from xml.sax.saxutils import escape
class KmlObject(object):
generate a closing tag. A call to render() generally returns the
element's text, and renders its children recursively.
"""
+
+ OPEN_TAG = ''
+ CLOSE_TAG = ''
def __init__(self, initial_text=''):
self.children = []
def to_kml(self):
- return self.render()
+ kml = self.OPEN_TAG
+ kml += self.render()
+ kml += self.CLOSE_TAG + "\n"
+ return kml
def render(self):
- kml = self.text
+ kml = escape(self.text)
for c in self.children:
kml += c.to_kml()
-
+
return kml
+ def print_kml(self):
+ print self.OPEN_TAG
+ self.render_to_stdout()
+ print self.CLOSE_TAG
+
+
+ def render_to_stdout(self):
+ if (len(self.text) > 0):
+ print escape(self.text)
+
+ for c in self.children:
+ c.print_kml()
+
+
class Color(KmlObject):
- def to_kml(self):
- kml = '<color>'
- kml += self.render()
- kml += "</color>\n"
- return kml
+ OPEN_TAG = '<color>'
+ CLOSE_TAG = '</color>'
-
class Document(KmlObject):
+
+ OPEN_TAG = """<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<kml xmlns=\"http://www.opengis.net/kml/2.2\">
+<Document>"""
+
+ CLOSE_TAG = """</Document>
+</kml>"""
def __init__(self, initial_text=''):
super(Document, self).__init__(initial_text)
self.styles = []
- def to_kml(self):
- kml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- kml += "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
- kml += "<Document>\n"
-
- kml += self.render()
-
- kml += "</Document>\n"
- kml += "</kml>\n"
-
- return kml
-
-
def render(self):
kml = ''
return kml
+ def render_to_stdout(self):
+ for s in self.styles:
+ s.print_kml()
+
+ for c in self.children:
+ c.print_kml()
+
+
class Description(KmlObject):
- def to_kml(self):
- kml = '<description>'
- kml += self.render()
- kml += "</description>\n"
- return kml
-
+ OPEN_TAG = '<description>'
+ CLOSE_TAG = '</description>'
-class Name(KmlObject):
-
- def to_kml(self):
- kml = '<name>'
- kml += self.render()
- kml += "</name>\n"
- return kml
+class Coordinates(KmlObject):
+ OPEN_TAG = '<coordinates>'
+ CLOSE_TAG = '</coordinates>'
-class Placemark(KmlObject):
- def to_kml(self):
- kml = "<Placemark>\n"
- kml += self.render()
- kml += "</Placemark>\n"
- return kml
+class LineString(KmlObject):
+ OPEN_TAG = '<LineString>'
+ CLOSE_TAG = '</LineString>'
+ @classmethod
+ def parse_linestrings(self, kml):
+ """
+ Parse each <LineString>...</LineString> block from the KML.
+ """
+ linestrings = []
-class PolyStyle(KmlObject):
+ search_idx = kml.find(self.OPEN_TAG, 0)
- def to_kml(self):
- kml = "<PolyStyle>\n"
- kml += self.render()
- kml += "</PolyStyle>\n"
- return kml
+ while (search_idx != -1):
+ # No reason to keep the tag around.
+ ls_start = search_idx + len(self.OPEN_TAG)
+ ls_tag_end = kml.find(self.CLOSE_TAG, ls_start)
+ ls = kml[ ls_start : ls_tag_end ]
+ linestrings.append(ls)
+ search_idx = kml.find(self.OPEN_TAG, (ls_tag_end + len(self.CLOSE_TAG)))
+
+ return linestrings
+
+
+ @classmethod
+ def parse_coordinates_from_linestrings(self, linestrings):
+ coords = []
+
+ for ls in linestrings:
+ c_tag_start = ls.find(Coordinates.OPEN_TAG)
+ c_start = c_tag_start + len(Coordinates.OPEN_TAG)
+ c_end = ls.find(Coordinates.CLOSE_TAG)
+ c = ls[ c_start : c_end ]
+ coords.append(c)
+
+ return coords
+
+
+ @classmethod
+ def tuples_from_kml(self, kml):
+ """
+ Parse one or more linestrings from a KML document.
+ Return a list of tuples.
+ """
+ ls = self.parse_linestrings(kml)
+ cs = self.parse_coordinates_from_linestrings(ls)
+
+ tuples = []
+
+ for c in cs:
+ pointstrings = c.strip().split()
+ for point in pointstrings:
+ components = point.strip().split(',')
+ if (len(components) >= 2):
+ # Project the three-dimensional vector onto the
+ # x-y plane. I don't think we're going to run
+ # in to any linestrings in 3d.
+ tuples.append( (float(components[0]), float(components[1])) )
+
+ return tuples
+
+
+class Name(KmlObject):
+
+ OPEN_TAG = '<name>'
+ CLOSE_TAG = '</name>'
+
+
+
+class Placemark(KmlObject):
+
+ OPEN_TAG = '<Placemark>'
+ CLOSE_TAG = '</Placemark>'
+
+
+class PolyStyle(KmlObject):
+
+ OPEN_TAG = '<PolyStyle>'
+ CLOSE_TAG = '</PolyStyle>'
+
class Style(KmlObject):
-
- def __init__(self, initial_text='', initial_id=None):
+
+ OPEN_TAG = "<Style id=\"%s\">"
+ CLOSE_TAG = '</Style>'
+
+ def __init__(self, initial_text='', initial_id=''):
super(Style, self).__init__(initial_text)
self.id = initial_id
def to_kml(self):
kml = ''
-
- if (self.id == None):
- kml += "<Style>\n"
- else:
- kml += ("<Style id=\"%s\">\n" % self.id)
-
+ kml += (self.OPEN_TAG % self.id + "\n")
kml += self.render()
- kml += "</Style>\n"
+ kml += self.CLOSE_TAG + "\n"
return kml
+ def print_kml(self):
+ print (self.OPEN_TAG % self.id)
+ self.render_to_stdout()
+ print self.CLOSE_TAG
-class StyleUrl(KmlObject):
-
- def to_kml(self):
- kml = '<styleUrl>'
- kml += self.render()
- kml += "</styleUrl>\n"
- return kml
+
+class StyleUrl(KmlObject):
+
+ OPEN_TAG = '<styleUrl>'
+ CLOSE_TAG = '</styleUrl>'
+
class RawText(KmlObject):
- pass
+
+ def to_kml(self):
+ return self.text
+
+ def print_kml(self):
+ if (len(self.text) > 0):
+ print self.text