简体   繁体   中英

How to access kml/xml attributes after filtering in python(lxml)?

I have looked around a bit and can't seem to find a solution to my problem. My underlying problem is that I need to find the name of all KML elements whose child polygons contain points with a given lat/lon.

Looking around I found that using keytree, shapely, and lxml I can filter all of the KML elements down to the polygons in question and then access their parents. When I try to access the parent's attributes, however, I keep getting an empty list. I have tried the following:

def __init__(self):
    root=etree.fromstring(open("Example.kml", "r").read())
    kmlns = root.tag.split("}")[0][1:]
    polygons=root.findall(".//{%s}Polygon"%kmlns)
    p = Point(-128.1605,52.474)  #this point exists in one of the polygons
    hits = filter(
        lambda e: shape(keytree.geometry(e)).contains(p),
        polygons)

    print hits
    hit_parent=hits[0].getparent()
    print hit_parent.attrib#this prints {}

I was able to find the row where the polygon was by using the debugger in pycharm; according to that, hits[0] had a sourceline attribute and when I went to that line number in my KML document the polygon did indeed contain the point. Scrolling up to the polygon's parent I found that it had attributes(ie not an empty list). I am new to xml and kml parsing; am I looking in the wrong place? Here is the polygon and its parent from the kml:

<Placemark>
            <name>THIS IS THE NAME</name>
            <visibility>0</visibility>
            <styleUrl>#falseColor184010</styleUrl>
            <ExtendedData>
                <SchemaData schemaUrl="#S_AL_TA_BC_2_41_eng_SSSSISSSSSSSSSSSSSSSSSSSSS10">
                    <SimpleData name="ACQTECH">Computed</SimpleData>
                    <SimpleData name="METACOVER">Partial</SimpleData>
                    <SimpleData name="CREDATE">20030416</SimpleData>
                    <SimpleData name="REVDATE">20130504</SimpleData>
                    <SimpleData name="ACCURACY">-1</SimpleData>
                    <SimpleData name="PROVIDER">Federal</SimpleData>
                    <SimpleData name="DATASETNAM">BC</SimpleData>
                    <SimpleData name="SPECVERS">1.1</SimpleData>
                    <SimpleData name="NID">7103157bba3511d892e2080020a0f4c9</SimpleData>
                    <SimpleData name="ALCODE">07876</SimpleData>
                    <SimpleData name="LANGUAGE1">English</SimpleData>
                    <SimpleData name="NAME1">NEEKAS 4</SimpleData>
                    <SimpleData name="LANGUAGE2">French</SimpleData>
                    <SimpleData name="NAME2">NEEKAS NO 4</SimpleData>
                    <SimpleData name="LANGUAGE3">No Language</SimpleData>
                    <SimpleData name="NAME3">NULL</SimpleData>
                    <SimpleData name="LANGUAGE4">No Language</SimpleData>
                    <SimpleData name="NAME4">NULL</SimpleData>
                    <SimpleData name="LANGUAGE5">No Language</SimpleData>
                    <SimpleData name="NAME5">NULL</SimpleData>
                    <SimpleData name="JUR1">BC</SimpleData>
                    <SimpleData name="JUR2"></SimpleData>
                    <SimpleData name="JUR3"></SimpleData>
                    <SimpleData name="JUR4"></SimpleData>
                    <SimpleData name="ALTYPE">Indian Reserve</SimpleData>
                    <SimpleData name="WEBREF">http://clss.nrcan.gc.ca/map-carte/mapbrowser-navigateurcartographique-eng.php?cancode=07876</SimpleData>
                </SchemaData>
            </ExtendedData>
            <Polygon>
                <outerBoundaryIs>
                    <LinearRing>
                        <coordinates>
                            -128.1615722,52.47385589999999,0 -128.1618475,52.47338730000003,0 -128.1623126999999,52.47275560000004,0 -128.1622705,52.47253640000001,0 -128.162017,52.47243320000002,0 -128.1619326,52.4722527,0 -128.1618904,52.4721108,0 -128.161827,52.47202060000003,0 -128.1615523,52.47204629999998,0 -128.1613199,52.47211069999996,0 -128.1607705,52.47205899999999,0 -128.1604538,52.47172369999999,0 -128.1600750999999,52.47149440000001,0 -128.1600821,52.47510580000001,0 -128.1615621,52.47510469999996,0 -128.1615294999999,52.474926,0 -128.1615508,52.47452629999999,0 -128.1615298,52.47416529999997,0 -128.1615722,52.47385589999999,0 
                        </coordinates>
                    </LinearRing>
                </outerBoundaryIs>
            </Polygon>

I want to get "THIS IS THE NAME" from the parent of the polygon.

Your target text is not attribute of any element. Given <Polygon> as context element, you want to go to parent element <Placemark> and then get its child element <name> . This can be done in a single line using XPath :

....
print hits
hit_parent = hits[0].find("./../{%s}name"%kmlns)
print hit_parent.text

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM