Search code examples
pythonpandaslxmlpykml

How to extract a LineString element color from a GE kml by using lmxl or pykml?


The GE kml file below do not make a elements color identification directly within the html code. How can I extract them in a csv file along with the name and its coordinates with a python extension.

I already got the name and the coordinates but the elements colors have not been able to. Is it impossible to extract this information?

I used several codes that I got here but the color of the element remains a mystery. One of them is this:

from pykml import parser
from pykml.factory import nsmap

namespace = {"ns": nsmap[None]}

with open('test.kml') as f:
  root = parser.parse(f).getroot()
  pms = root.xpath(".//ns:Placemark[.//ns:LineString]",   namespaces=namespace)

  for pm in pms:
      print(pm.name)
      print(pm.LineString.coordinates)

The expected result is a csv file with the fields: name; coordinates; color or a simple table with the same fields.

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
    <name>test.kml</name>
    <StyleMap id="inline93460">
        <Pair>
            <key>normal</key>
            <styleUrl>#inline169131</styleUrl>
        </Pair>
        <Pair>
            <key>highlight</key>
            <styleUrl>#inline37027</styleUrl>
        </Pair>
    </StyleMap>
    <Style id="inline8348">
        <LineStyle>
            <color>ff00ffff</color>
            <width>2</width>
        </LineStyle>
        <PolyStyle>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <StyleMap id="inline7838">
        <Pair>
            <key>normal</key>
            <styleUrl>#inline7066</styleUrl>
        </Pair>
        <Pair>
            <key>highlight</key>
            <styleUrl>#inline7746</styleUrl>
        </Pair>
    </StyleMap>
    <Style id="inline37027">
        <LineStyle>
            <color>ff00ffff</color>
            <width>2</width>
        </LineStyle>
        <PolyStyle>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <Style id="inline7746">
        <LineStyle>
            <color>ffff0000</color>
            <width>2</width>
        </LineStyle>
        <PolyStyle>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <Style id="inline7066">
        <LineStyle>
            <color>ffff0000</color>
            <width>2</width>
        </LineStyle>
        <PolyStyle>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <StyleMap id="inline55590">
        <Pair>
            <key>normal</key>
            <styleUrl>#inline8348</styleUrl>
        </Pair>
        <Pair>
            <key>highlight</key>
            <styleUrl>#inline5777</styleUrl>
        </Pair>
    </StyleMap>
    <Style id="inline5777">
        <LineStyle>
            <color>ff00ffff</color>
            <width>2</width>
        </LineStyle>
        <PolyStyle>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <Style id="inline169131">
        <LineStyle>
            <color>ff00ffff</color>
            <width>2</width>
        </LineStyle>
        <PolyStyle>
            <fill>0</fill>
        </PolyStyle>
    </Style>
    <Folder>
        <name>Cidade de Esmeraldas</name>
        <open>1</open>
        <Folder>
            <name>Aldeias do lago</name>
            <open>1</open>
            <Placemark>
                <name>Medida do caminho</name>
                <styleUrl>#inline93460</styleUrl>
                <LineString>
                    <tessellate>1</tessellate>
                    <coordinates>
                        -44.18468786850732,-19.7311490448918,0 -44.18476571351906,-19.73196615345114,0 -44.18516928457656,-19.73196209518785,0 
                    </coordinates>
                </LineString>
            </Placemark>
            <Placemark>
                <name>Medida do caminho</name>
                <styleUrl>#inline7838</styleUrl>
                <LineString>
                    <tessellate>1</tessellate>
                    <coordinates>
                        -44.18116177806758,-19.73104199822188,0 -44.18149124079289,-19.73002254245169,0 -44.18093826107535,-19.73172738045029,0 -44.1809508776952,-19.73186017013899,0 -44.18160756352079,-19.73204395759025,0 
                    </coordinates>
                </LineString>
            </Placemark>
            <Placemark>
                <name>Medida do caminho</name>
                <styleUrl>#inline55590</styleUrl>
                <LineString>
                    <tessellate>1</tessellate>
                    <coordinates>
                        -44.19110137765401,-19.72300828552742,0 -44.19173625397613,-19.72303182576567,0 -44.19283033803023,-19.72258037041406,0 -44.19316612473877,-19.72323246634359,0 
                    </coordinates>
                </LineString>
            </Placemark>
        </Folder>
    </Folder>
</Document>
</kml>

Solution

  • I am not familiar with pykml, but you can get what you want like this:

    from lxml import etree    
    import pandas as pd
    
    ns = {"xx":"http://www.opengis.net/kml/2.2"}
    rows =[]
    for su in root.xpath('//xx:Placemark/xx:styleUrl',namespaces=ns):
        name = su.xpath('./preceding-sibling::xx:name/text()',namespaces=ns)[0]
        coo = su.xpath('./following-sibling::xx:LineString/xx:coordinates/text()',namespaces=ns)[0].strip()
        sm = su.text.replace("#","")
        sy = doc.xpath(f'//xx:StyleMap[@id="{sm}"]//xx:Pair[./xx:key["normal"]]/xx:styleUrl',namespaces=ns)[0].text.replace("#","")
        color = doc.xpath(f'//xx:Style[@id="{sy}"]//xx:LineStyle/xx:color/text()',namespaces=ns)[0]
        rows.append([name,coo,color])
    columns = ['name','coordinates','color']
    df = pd.DataFrame(rows,columns=columns)
    df
    

    Output:

    name    coordinates     color
    0   Medida do caminho   -44.18468786850732,-19.7311490448918,0 -44.184...   ff00ffff
    1   Medida do caminho   -44.18116177806758,-19.73104199822188,0 -44.18...   ffff0000
    2   Medida do caminho   -44.19110137765401,-19.72300828552742,0 -44.19...   ff00ffff