Element Tree doesn't load a Google Earth-exported KML
Question: I have a problem related to a Google Earth exported KML, as it doesn't seem to
work well with Element Tree. I don't have a clue where the problem might lie,
so I will explain how I do everything.

Here is the relevant code:

    
    
        kmlFile = open( filePath, 'r' ).read( -1 ) # read the whole file as text
        kmlFile = kmlFile.replace( 'gx:', 'gx' )   # we need this as otherwise the Element Tree parser
                                                   # will give an error
    
        kmlData = ET.fromstring( kmlFile )
        document = kmlData.find( 'Document' )
    

With this code, ET (Element Tree object) _creates_ an Element object
accessible via variable kmlData. It points to the root element ('kml' tag).
However, when I run a search for the sub-element 'Document', it returns None.
Although the 'Document' tag is present in the KML file!

Are there any other discrepancies between KMLs and XMLs apart from the 'gx:
smth' tags? I have searched through the KML files I am dealing with and found
nothing suspicious. Here is a simplified structure of an KML file the program
is supposed to deal with:

    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <kml xmlns="http://earth.google.com/kml/2.2">
    <Document>
       <name>UK.kmz</name>
       <Style id="sh_blu-blank">
        <IconStyle>
            <scale>1.3</scale>
            <Icon>
                <href>http://maps.google.com/mapfiles/kml/paddle/blu-blank.png</href>
            </Icon>
            <hotSpot x="32" y="1" xunits="pixels" yunits="pixels"/>
        </IconStyle>
        <ListStyle>
            <ItemIcon>
                <href>http://maps.google.com/mapfiles/kml/paddle/blu-blank-lv.png</href>
            </ItemIcon>
        </ListStyle>
      </Style>
        [other style tags...]
      <Folder>
        <name>UK</name>
        <Placemark>
            <name>1262 Crossness Pumping Station</name>
            <LookAt>
                <longitude>0.1329926667038817</longitude>
                <latitude>51.50303535104574</latitude>
                <altitude>0</altitude>
                <range>4246.539753518848</range>
                <tilt>0</tilt>
                <heading>-4.295161152207489</heading>
                <altitudeMode>relativeToGround</altitudeMode>
                <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
            </LookAt>
            <styleUrl>#msn_blu-blank15000</styleUrl>
            <Point>
                <coordinates>0.1389579668507301,51.50888923518947,0</coordinates>
            </Point>
        </Placemark>
             [other placemark tags...]
      </Folder>
    </Document>
    </kml>
    

Do you have an idea why I can't access any sub-elements of 'kml'? By the way,
Python version is 2.7.


Answer: The KML document is in the `http://earth.google.com/kml/2.2` namespace, as
indicated by

    
    
    <kml xmlns="http://earth.google.com/kml/2.2">
    

This means that the name of the `Document` element is in fact
`{http://earth.google.com/kml/2.2}Document`.

Instead of this:

    
    
    document = kmlData.find('Document')
    

you need this:

    
    
    document = kmlData.find('{http://earth.google.com/kml/2.2}Document')
    

However, there is a problem with the XML file. There is an element called
`gx:altitudeMode`. The `gx` bit is a namespace prefix. Such a prefix needs to
be declared, but the declaration is missing.

You have worked around the problem by simply replacing `gx:` with `gx`. But
the proper way to do this would be to add the namespace declaration. Based on
<https://developers.google.com/kml/documentation/altitudemode>, I take it that
`gx` is associated with the `http://www.google.com/kml/ext/2.2` namespace. So
for the document to be well-formed, the root element start tag should read

    
    
    <kml xmlns="http://earth.google.com/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
    

Now the document can be parsed:

    
    
    In [1]: from xml.etree import ElementTree as ET
    
    In [2]: kmlData = ET.parse("kml2.xml")
    
    In [3]: document = kmlData.find('{http://earth.google.com/kml/2.2}Document')
    
    In [4]: document
    Out[4]: <Element '{http://earth.google.com/kml/2.2}Document' at 0x1895810>
    
    In [5]:
    

