Getting Started

Quick Example

Here is a quick example to get you started:

import simplekml
kml = simplekml.Kml()
kml.newpoint(name="Kirstenbosch", coords=[(18.432314,-33.988862)])  # lon, lat, optional height
kml.save("botanicalgarden.kml")

Concepts

With simplekml everything starts with creating an instance of the simplekml.Kml class:

kml = simplekml.Kml()

The compilation of the KML file will be done through this class. The base feature attached to this class is a document, all arguments passed to the class on creation are the same as that of a simplekml.Document. To change any properties after creation you can do so through the simplekml.Kml.document() property:

kml.document.name = "Test"

To create a fully fledged KML document a document tree is created via calls to various functions like:

kml.newpoint()

These calls build up a relationships between classes which will be converted into KML when a call to kml.save(), kml.savekmz() or kml.kml() is made. These relationships are created in the background and do not need direct manipulation.

There are three ways to go about using simplekml: property changes, property assignment and a mixture of property changes and assignment.

With property assignment, when you change the properties of the objects you are working with the class of the property (and thus th associated KML tag) gets activated. What is meant by this is when starting to build up your KML, the KML tags are kept to a minimum when generated by kml.save(), kml.savekmz() or kml.kml() and more and more tags are added as you assign values to properties. For example, below we create an kml object and attach a point to it and then print the result to screen:

import simplekml
kml = simplekml.Kml()
pnt = kml.newpoint(name="A Point")
print(kml.kml())

This is what is generated:

<?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">
    <Document id="feat_1">
        <Placemark id="feat_2">
            <name>A Point</name>
            <Point id="geom_0">
                <coordinates>0.0, 0.0, 0.0</coordinates>
            </Point>
        </Placemark>
    </Document>
</kml>

As you can see, only the least amount of KML is generated for it to be viewable in Google Earth. In this case we have a document containing a placemark containing a point and the point has the default coordinate of 0.0, 0.0, 0.0 and the name we gave it: A Point

Now we can add a description to our point after it was created:

pnt.description = "This is a description"

And the result:

<?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">
    <Document id="feat_1">
        <Placemark id="feat_2">
            <name>A Point</name>
            <description>This is a description</description>
            <Point id="geom_0">
                <coordinates>0.0, 0.0, 0.0</coordinates>
            </Point>
        </Placemark>
    </Document>
</kml>

You can see that the description tag was created that contains our description. This is what is meant by activating the KML tags. Here is a more complicated example where we are going to set the simplekml.Point.snippet() property:

pnt.snippet.content = "This is the content of the snippet"
pnt.snippet.maxlines = 1

The result:

<?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">
    <Document id="feat_1">
        <Placemark id="feat_2">
            <name>A Point</name>
            <description>This is a description</description>
            <Snippet maxLines="1">This is the content of the snippet</Snippet>
            <Point id="geom_0">
                <coordinates>0.0, 0.0, 0.0</coordinates>
            </Point>
        </Placemark>
    </Document>
</kml>

Above the snippet had two properties that we changed: content and maxlines. Again, notice the tags being generated. This is what is meant by the property changes method. This method is fine for one or two properties that have to be changed, but when we have the following, typing becomes repetitive and tedious:

pnt.lookat.gxaltitudemode = simplekml.GxAltitudeMode.relativetoseafloor
pnt.lookat.latitude = 0.0
pnt.lookat.longitude = 0.0
pnt.lookat.range = 3000
pnt.lookat.heading = 56
pnt.lookat.tilt = 78

The result:

<?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">
    <Document id="feat_1">
        <Placemark id="feat_2">
            <name>A Point</name>
            <description>This is a description</description>
            <LookAt>
                <longitude>18.356852</longitude>
                <latitude>-34.028242</latitude>
                <heading>56</heading>
                <tilt>78</tilt>
                <range>3000</range>
                <gx:altitudeMode>relativeToSeaFloor </gx:altitudeMode>
            </LookAt>
            <Snippet maxLines="1">This is the content of the snippet</Snippet>
            <Point id="geom_0">
                <coordinates>0.0, 0.0, 0.0</coordinates>
            </Point>
        </Placemark>
    </Document>
</kml>

In this case it would be easier to use the property assignment method. Here we are going to create an instance of the simplekml.LookAt class and then assign it to the lookat property of the point:

pnt.lookat = simplekml.LookAt(gxaltitudemode=simplekml.GxAltitudeMode.relativetoseafloor,
                              latitude=0.0, longitude=0.0,
                              range=3000, heading=56, tilt=78)

As you can plainly see, that is far less typing. So, for the property assignment method, all you need to do is create an instance of the class you want to assign to the property with its properties filled out and then assign it.

And finally, you mix the two methods as you see fit. Each circumstance will require a different approach.

Note

If there is a property that needs to be removed from the tree, simply set it to None:

kml = simplekml.Kml(name="A name")  # Give the KML document a name
kml.document.name = None  # remove the name we gave above

This is useful to prevent an image from being displayed for a point. By default a point has the image of a yellow push pin (in Google Earth), but if you want to remove it you have to do this:

pnt.style.iconstyle.icon.href = None

This removes the href from the icon, thus nothing will be displayed in google earth, except the point’s text.

Also, if you access some properties without assigning to them, the KML tag is also created. For instance, if you print the snippet of a point without a having changed any of its properties, a blank snippet tag will be generated:

import simplekml
kml = simplekml.Kml()
print(kml.document.snippet)

The following will be generated when saving the KML:

<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
    <Document id="feat_1">
        <Snippet/>
    </Document>
</kml>

Creating a KML document

To create a KML document you just have to import simplekml and then create an instance of simplekml.Kml. Doing this will create a KML ‘file’ in memory and assign a simplekml.Document as the main feature:

import simplekml
kml = simplekml.Kml()

Saving a KML document

Simply call kml.save(“pathtomyfile.kml”) passing a path to the file you want to create. Alternatively you can call kml.savekmz(“pathtomyfile.kmz”) to save the KML as a KMZ, or even kml.kml() to get the KML as a string. See simplekml.Kml.save(), simplekml.Kml.savekmz() and simplekml.Kml.kml() for more details.

Creating a Point

A Point is a geographic location defined by longitude, latitude, and altitude.

Note

All coordinates in simplekml are in the order longitude, latitude and then an optional height.

Creating a simplekml.Point is quite simple and has been done in the section above. Once you have your simplekml.Kml object you have to ask it to create a new simplekml.Point for you by calling simplekml.Kml.newpoint(). If you call simplekml.Kml.newpoint() without any parameters a simplekml.Point is created at 0.0, 0.0 with no name. You can later change the name and location (among other things) by changing the attributes of the simplekml.Point instance that was returned to you by calling simplekml.Kml.newpoint(). Passing parameters to simplekml.Kml.newpoint() may be more convenient. All the attributes have to be set like so: attributename=value. See simplekml.Point for a list of possible parameters and attributes.

Here is an example:

pnt = kml.newpoint(name="Kirstenbosch", description="A botanical Garden",
                   coords=[(18.432314,-33.988862)])  # lon, lat optional height

The values of the above parameters can be changed later by directly assigning to them:

pnt.name = "Tree"
pnt.description = "A big plant."

Creating a LineString

A Linestring is a connected set of line segments.

A simplekml.LineString is created in a similar manner to a simplekml.Point, except you can have more than one coordinate. Just call simplekml.Kml.newlinestring(). See simplekml.LineString for a list of possible parameters and attributes.

Here is an example:

lin = kml.newlinestring(name="Pathway", description="A pathway in Kirstenbosch",
                        coords=[(18.43312,-33.98924), (18.43224,-33.98914),
                                (18.43144,-33.98911), (18.43095,-33.98904)])

Creating a Polygon

A Polygon is defined by an outer boundary and/or an inner boundary.

A simplekml.Polygon is created in a similar manner to a simplekml.LineString, except there is no coordinate parameter. Just call simplekml.Kml.newpolygon(). The coordinate parameter has been replaced with two others, simplekml.Polygon.outerboundaryis() and simplekml.Polygon.innerboundaryis(). The outer and inner boundaries describe the outside of the simplekml.Polygon and an inner opening. You pass a list of tuples to these parameters, as if it were a coordinate list. See simplekml.Polygon for a list of possible parameters and attributes.

Here is an example:

pol = kml.newpolygon(name="Atrium Garden",
                     outerboundaryis=[(18.43348,-33.98985), (18.43387,-33.99004),
                                      (18.43410,-33.98972), (18.43371,-33.98952),
                                      (18.43348,-33.98985)],
                     innerboundaryis=[(18.43360,-33.98982), (18.43386,-33.98995),
                                      (18.43401,-33.98974), (18.43376,-33.98962),
                                      (18.43360,-33.98982)])