Interactive specification
KML, minus the parts that draw.
KML is a presentation language — it describes how a map should look, and only incidentally where things are. Free flight uses the small part that carries positions: Placemark, Point, and a coordinate tuple whose field order catches everyone exactly once.
A drawing language with positions in it
KML — Keyhole Markup Language — was Google Earth's native format and became an OGC standard in 2008. Its subject is presentation: icons, line styles, balloon popups, camera positions, time sliders, ground overlays. Geographic positions are in there because you have to say where to draw things.
That framing explains everything awkward about using KML for waypoints. Free-flight tools want a list of named places; KML offers a tree of styled features that happens to contain some. The subset that carries what we want is small:
| Element | Role |
|---|---|
<Placemark> | A named feature. The waypoint. |
<Point> | Its geometry, when it is a single position. |
<coordinates> | The position itself — and the one thing on this page to get right. |
<name>, <description> | The two text slots. |
<Document>, <Folder> | Containers. They nest, arbitrarily deep. |
.kmz is a zipped KML plus its icons and overlays, with the KML conventionally at doc.kml. It is what Google Earth saves by default, so pilots hand it over constantly. It is not text — unzip first, or tell the pilot to export "KML" rather than "KMZ".lon,lat,ele — in that order
A KML coordinate tuple is comma-separated, longitude first:
<Point><coordinates>5.635000,44.278000,1320</coordinates></Point> ↑ longitude ↑ latitude ↑ elevation, metres
lat/lon attributes — and the same order as GeoJSON, which is where the convention comes from. Swap them and a French waypoint lands in Somalia. There is no hemisphere letter and no unit to catch it: both numbers are plausible on their own.| Position | Value | Range | Notes |
|---|---|---|---|
| 1 | Longitude | −180 … 180 | Signed decimal degrees, WGS84. |
| 2 | Latitude | −90 … 90 | Signed decimal degrees, WGS84. |
| 3 | Elevation | metres | Optional. Interpreted per <altitudeMode>; defaults to clampToGround, which ignores it entirely. |
Whitespace separates tuples, commas separate fields
A <LineString> holds many tuples in one element, separated by any whitespace — and real files wrap them across lines with generous indentation:
<LineString><coordinates> 5.635000,44.278000,1320 5.740000,44.285000,1834 5.715000,44.362000,1420 </coordinates></LineString>
So: split the element's text on whitespace to get tuples, then split each tuple on commas. Splitting on "comma or whitespace" in one pass works for a single point and silently scrambles a LineString.
Containers that nest
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <Document> <name>Chabre waypoints</name> <Folder> <name>Launches</name> <Placemark> <name>D01188</name> <description>Chabre launch</description> <Point><coordinates>5.635000,44.278000,1320</coordinates></Point> </Placemark> </Folder> <Placemark> <name>Landing field</name> <Point><coordinates>5.826000,44.319000,560</coordinates></Point> </Placemark> </Document> </kml>
<Document> and <Folder> are both containers, both optional, and both nest inside each other to any depth. A <Placemark> can sit at any level — including directly under <kml>.
<Placemark> that has a <Point> — a fixed kml → Document → Placemark path finds nothing in half of real files.Placemarks that are not waypoints
A <Placemark> can hold a <LineString>, a <Polygon>, a <MultiGeometry> or no geometry at all. For a waypoint importer, require <Point> and skip the rest — an airspace polygon or a drawn track is not a waypoint, and a Placemark with only a description is a text label.
The elements that carry meaning
KML defines several hundred elements. These are the ones that survive a waypoint round trip; everything else is presentation.
Two slots, and HTML in one of them
Like GPX and OziExplorer, KML gives a feature two text slots. The comp convention is the same:
| Element | Carries |
|---|---|
<name> | The code — B61130, D01188 |
<description> | The full name |
Promote <name> to a code when it is 2–8 alphanumeric characters with at least one digit and the description holds something different. The digit requirement stops Goal and Home being read as codes.
The KML-specific complication
<description> is rendered as HTML in Google Earth's balloon popup. So it frequently is HTML, usually wrapped in CDATA:
<description><![CDATA[ <b>Chabre launch</b><br/> Alt 1320 m · <a href="https://example.org">site guide</a> ]]></description>
Paste a KML, read the waypoints
The whole container tree is walked, every <Placemark> with a <Point> is decoded, and coordinates are shown in the order KML wrote them and the order you think in. Nothing is uploaded.
Where KML goes wrong
- Longitude comes first. Nothing in the file will tell you when you have it backwards.
- Commas separate fields, whitespace separates tuples. Two splits, in that order.
- Recurse into
DocumentandFolder, to any depth, and handle several of either at the same level. - Require
<Point>. Placemarks also hold LineStrings, Polygons and MultiGeometries. - Elevation is optional and often meaningless. The default
altitudeModeisclampToGround, which discards it — a third field of0usually means "not supplied". <description>is HTML in CDATA. Strip tags, bound the length, never render it raw.- KMZ is a zip. Unzip and read
doc.kml, or refuse it with a message that explains the difference. - Namespaces vary and
gx:extensions abound. Google'sgx:Track,gx:altitudeModeand friends sit in their own namespace. Match local names, ignore what you do not know.
What We-Fly reads and writes
| Surface | Reads | Writes |
|---|---|---|
| XC planner — collections | Every <Placemark> with a <Point>, at any depth | One <Document>, one <Placemark> per waypoint |
| XC planner — routes | — | — |
| Flight upload | — | — |
Parsing happens entirely in the browser; an imported collection is only stored when you explicitly save it. Files are written as KML 2.2 with six decimal places of coordinate precision (≈ 0.1 m), MIME type application/vnd.google-earth.kml+xml. Competition codes round-trip through the two text slots.
KML is never accepted as a flight track — even though instruments like Flymaster offer it. Every flight enters We-Fly as IGC, which carries pressure altitude and a security record that KML has no way to express. If a service only offers you KML for a flight, ask them for the original IGC; they almost always still have it.
The same collections also round-trip through the three .wpt dialects, GPX and SeeYou .cup.