Last active
August 27, 2023 11:27
-
-
Save postspectacular/f69a3b0899ec4212fa59c3410536ee85 to your computer and use it in GitHub Desktop.
#HowToThing #007 — Converting Google Maps Saved Places (exported via Google Takeout) to KML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { readJSON, writeText } from "@thi.ng/file-io"; | |
import { XML_PROC, serialize } from "@thi.ng/hiccup"; | |
// source path of the Google Takeout (GT) places | |
const path = "/Downloads/Takeout/Maps (your places)/Saved Places.json"; | |
// load GT places | |
const places = readJSON(path).features; | |
// FYI: partial structure of a GT place | |
interface Place { | |
geometry: { coordinates: number[] }; | |
properties: { | |
Title: string; | |
Published: string; // ISO8601 datetime | |
Location?: { | |
Address?: string; | |
"Business Name"?: string; | |
}; | |
}; | |
} | |
// convert a single GT place into a KML placemark in thi.ng/hiccup format | |
// (aka S-expression-like, tagged, nested, plain JS arrays) | |
// see thi.ng/hiccup readme for full details & options... | |
const convertPlace = ({ geometry, properties }: Place) => [ | |
"Placemark", | |
["Point", ["coordinates", geometry.coordinates.join(",")]], | |
["name", properties.Title], | |
["TimeStamp", ["when", properties.Published]], | |
// conditionally include address | |
// null values will be skipped later during serialization | |
properties.Location?.Address | |
? ["address", {}, properties.Location?.Address] | |
: null, | |
]; | |
// define a full KML document in hiccup format | |
const kmlDoc = [ | |
// XML processing instruction/header | |
XML_PROC, | |
[ | |
"kml", | |
{ xmlns: "http://www.opengis.net/kml/2.2" }, | |
[ | |
"Document", | |
["name", "Google Takeout"], | |
["visibility", 1], | |
...places.map(convertPlace), | |
], | |
], | |
]; | |
// output as UTF-8 file | |
writeText( | |
// write result in same place but with `.kml` extension | |
path.replace(/\.json$/, ".kml"), | |
// serialize hiccup document | |
// the `true` arg ensures, XML entities (e.g. &) are being auto-encoded | |
serialize(kmlDoc, null, true) | |
); | |
// resulting KML: | |
// <?xml version="1.0" encoding="UTF-8"?> | |
// <kml xmlns="http://www.opengis.net/kml/2.2"> | |
// <Document> | |
// <name>Google Takeout</name> | |
// <visibility>1</visibility> | |
// <Placemark> | |
// <Point> | |
// <coordinates>9.4286111,47.2866667</coordinates> | |
// </Point> | |
// <name>Talstation Luftseilbahn Wasserauen-Ebenalp AG</name> | |
// <TimeStamp> | |
// <when>2017-09-01T20:56:41Z</when> | |
// </TimeStamp> | |
// <address>Schwendetalstrasse 82, 9057 Wasserauen, Switzerland</address> | |
// </Placemark> | |
// ... | |
// </Document> | |
// </kml> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment