diff --git a/MAVProxy/modules/lib/kmlread.py b/MAVProxy/modules/lib/kmlread.py index acc4f43000..2c09000345 100644 --- a/MAVProxy/modules/lib/kmlread.py +++ b/MAVProxy/modules/lib/kmlread.py @@ -1,7 +1,10 @@ #!/usr/bin/env python +import lxml.etree as etree +from io import BytesIO as SIO from zipfile import ZipFile -from xml.dom.minidom import parseString + +namespaces = {'kml': 'http://www.opengis.net/kml/2.2'} def readkmz(filename): '''reads in a kmz file and returns xml nodes''' @@ -9,7 +12,7 @@ def readkmz(filename): filename.strip('"') #Open the zip file (as applicable) if filename[-4:] == '.kml': - fo = open(filename, "r") + fo = open(filename, "rb") fstring = fo.read() fo.close() elif filename[-4:] == '.kmz': @@ -22,38 +25,56 @@ def readkmz(filename): raise Exception("Could not find kml file in %s" % filename) else: raise Exception("Is not a valid kml or kmz file in %s" % filename) - - #send into the xml parser - kmlstring = parseString(fstring) - - #get all the placenames - nodes=kmlstring.getElementsByTagName('Placemark') - - return nodes - + + parser = etree.XMLParser(encoding='utf-8', recover=True) + tree = etree.parse(SIO(fstring), parser) + xpath = xpath = ".//kml:Placemark" + + return tree.findall(xpath, namespaces) + +def find_tag(node, tagname): + for c in node.getchildren(): + if c.tag == "{" + namespaces['kml'] + "}" + tagname: + return c + return None + +def find_tag_recursive(node, tagname): + for c in node.getchildren(): + if c.tag == "{" + namespaces['kml'] + "}" + tagname: + return c + if hasattr(c, 'getchildren'): + ret = find_tag_recursive(c, tagname) + if ret is not None: + return ret + return None + + def readObject(innode): '''reads in a node and returns as a tuple: (type, name, points[])''' #get name - names=innode.getElementsByTagName('name')[0].childNodes[0].data.strip() - - #get type - pointType = 'Unknown' - if len(innode.getElementsByTagName('LineString')) == 0 and len(innode.getElementsByTagName('Point')) == 0: - pointType = 'Polygon' - elif len(innode.getElementsByTagName('Polygon')) == 0 and len(innode.getElementsByTagName('Point')) == 0: - pointType = 'Polygon' - elif len(innode.getElementsByTagName('LineString')) == 0 and len(innode.getElementsByTagName('Polygon')) == 0: - pointType = 'Point' - - #get coords - coords = innode.getElementsByTagName('coordinates')[0].childNodes[0].data.strip() - coordsSplit = coords.split() - ret_s = [] - for j in coordsSplit: - jcoord = j.split(',') - if len(jcoord) == 3 and jcoord[0] != '' and jcoord[1] != '': - #print("Got lon " + jcoord[0] + " and lat " + jcoord[1]) - ret_s.append((float(jcoord[1]), float(jcoord[0]))) - - #return tuple - return (str(pointType), str(names), ret_s) + name = find_tag(innode, 'name') + if name is None: + return None + point = find_tag(innode, 'Point') + if point is not None: + coordinates = find_tag(point, 'coordinates') + if coordinates is None: + return None + s = coordinates.text.split(',') + return ("Point", name.text, [(float(s[1]), float(s[0]))]) + + coordinates = find_tag_recursive(innode, 'coordinates') + if coordinates is not None: + latlon = [] + for c in coordinates.text.split(): + s = c.split(',') + latlon.append((float(s[1]), float(s[0]))) + return ("Polygon", name.text, latlon) + + return ('Unknown', None, None) + +if __name__ == '__main__': + import sys + nodes = readkmz(sys.argv[1]) + for n in nodes: + print(readObject(n))