Skip to content

Instantly share code, notes, and snippets.

@mfn
Last active January 9, 2021 15:45
Show Gist options
  • Save mfn/c94447215dd28c2956e7174402d71808 to your computer and use it in GitHub Desktop.
Save mfn/c94447215dd28c2956e7174402d71808 to your computer and use it in GitHub Desktop.
Convert endomondo json tracking data to gpx
<?php declare(strict_types=1);
/*
Usage: php endomondo_json2gpx.php <path_to_file.json> […<path_to_other_file.json>]
The endomondo json format parsed here; only the fields actually used by this converted:
[
{"sport": "…"},
{"points": [
[
{"location": [[
{"latitude": …},
{"longitude": …}
]]},
{"altitude": …},
{"timestamp": "…"}
],
which will be converted to
<?xml version="1.0" encoding="UTF-8"?>
<gpx creator="endomondo_json2gpx.php">
<trk>
<type>…</type>
<trkseg>
<trkpt lat="…" lon="…">
<time>…</time>
<ele>…</ele>
</trkpt>
*/
$script = array_shift($argv);
$jsonFiles = $argv;
if (!$jsonFiles) {
echo "ERROR: No *.json files given\n\n";
echo "Usage: $script <1.json> ... <n.json>\n";
exit(1);
}
foreach ($jsonFiles as $jsonFile) {
echo "Loading $jsonFile ...\n";
$data = json_decode(file_get_contents($jsonFile), true);
$json = transformJson($data);
$xml = convertJsonToGpx($json);
if (!$xml) {
echo "WARNING: no usable points found, skipping file\n";
continue;
}
$gpxFile = str_replace('.json', '.gpx', $jsonFile);
echo "Writing $gpxFile ...\n";
$xml->save($gpxFile);
}
function convertJsonToGpx(array $json): ?DOMDocument
{
$xml = new DOMDocument();
$xml->encoding = 'UTF-8';
$xml->formatOutput = true;
$gpx = $xml->createElement('gpx');
$xml->appendChild($gpx);
$gpx->setAttribute('creator', 'endomondo_json2gpx.php');
$trk = $xml->createElement('trk');
$gpx->appendChild($trk);
$type = $xml->createElement('type', strtolower($json['sport']));
$trk->appendChild($type);
$trkseg = $xml->createElement('trkseg');
$trk->appendChild($trkseg);
$pointsAdded = 0;
foreach ($json['points'] as $point) {
$point = transformJson($point);
if (!isset($point['location'])) {
continue;
}
$pointsAdded++;
$location = transformJson($point['location'][0]);
$altitude = $point['altitude'] ?? null;
$timestamp = new DateTimeImmutable($point['timestamp']);
$trkpt = $xml->createElement('trkpt');
$trkseg->appendChild($trkpt);
$trkpt->setAttribute('lat', (string) $location['latitude']);
$trkpt->setAttribute('lon', (string) $location['longitude']);
$time = $xml->createElement('time', $timestamp->format(DateTimeInterface::ATOM));
$trkpt->appendChild($time);
if ($altitude) {
$ele = $xml->createElement('ele', (string) $altitude);
$trkpt->appendChild($ele);
}
}
if (!$pointsAdded) {
return null;
}
return $xml;
}
function transformJson(array $data): array
{
$json = [];
foreach ($data as $datum) {
$key = array_key_first($datum);
$json[$key] = $datum[$key];
}
return $json;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment