GPX: add support for importing older GPX version 1.0 files

Also takes care of slightly quirky GPX 1.1 files that contain extra spaces, XML comments or use floats instead of integers for cadence and heart rate.
This commit is contained in:
Thomas Kuehne
2026-03-25 23:17:42 +01:00
committed by José Rebelo
parent 3bb686a106
commit 6fcb07ea98
6 changed files with 310 additions and 110 deletions
@@ -1,4 +1,4 @@
/* Copyright (C) 2023-2025 José Rebelo, Thomas Kuehne
/* Copyright (C) 2023-2026 José Rebelo, Thomas Kuehne
This file is part of Gadgetbridge.
@@ -168,7 +168,9 @@ public class GpxParser {
if (text == null || text.length() < 1) {
return defaultDouble;
}
return Double.parseDouble(text);
// some GPX generators write NaN instead of an empty value
final double value = Double.parseDouble(text);
return Double.isNaN(value) ? defaultDouble : value;
}
private float getFloat(String attribute, float defaultFloat) {
@@ -176,7 +178,9 @@ public class GpxParser {
if (text == null || text.length() < 1) {
return defaultFloat;
}
return Float.parseFloat(text);
// some GPX generators write NaN instead of an empty value
final float value = Float.parseFloat(text);
return Float.isNaN(value) ? defaultFloat : value;
}
private int getInt(String attribute, int defaultInt) {
@@ -184,7 +188,13 @@ public class GpxParser {
if (text == null || text.length() < 1) {
return defaultInt;
}
return Integer.parseInt(text);
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
// some GPX generators write malformed cadence and HR values: "6.0" instead of "6"
return Math.round(getFloat(attribute, defaultInt));
}
}
private void parseGpx() throws Exception {
+131 -79
View File
@@ -3,12 +3,17 @@
xmlns:ax="http://www.garmin.com/xmlschemas/ActivityExtension/v1"
xmlns:g3="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
xmlns:gpx="http://www.topografix.com/GPX/1/1"
xmlns:gpxOld="http://www.topografix.com/GPX/1/0"
xmlns:tx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
xmlns:tx2="http://www.garmin.com/xmlschemas/TrackPointExtension/v2"
xmlns:w1="http://www.garmin.com/xmlschemas/WaypointExtension/v1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="ax g3 gpx tx tx2 w1"
exclude-result-prefixes="ax g3 gpx tx tx2 w1 gpxOld"
version="1.0">
<!--
This pre-processes GPX v1.0 and v1.1 and common extension for import by
Gadgedbridge's nodomain.freeyourgadget.gadgetbridge.util.gpx.GPXParser
-->
<xsl:output
encoding="UTF-8"
indent="yes"
@@ -16,122 +21,169 @@
version="1.0" />
<xsl:strip-space elements="*" />
<xsl:template match="/gpx:gpx">
<xsl:template match="/gpx:gpx | /gpxOld:gpx">
<gpx>
<xsl:if test="gpx:metadata/gpx:name"><xsl:attribute name="name"><xsl:value-of select="gpx:metadata/gpx:name" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:metadata/gpx:author/gpx:name"><xsl:attribute name="author"><xsl:value-of select="gpx:metadata/gpx:author/gpx:name" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:metadata/gpx:time"><xsl:attribute name="time"><xsl:value-of select="gpx:metadata/gpx:time" /></xsl:attribute></xsl:if>
<xsl:apply-templates select="gpx:wpt" />
<xsl:apply-templates select="gpx:trk" />
<xsl:choose>
<xsl:when test="gpx:metadata/gpx:name"><xsl:attribute name="name"><xsl:value-of select="gpx:metadata/gpx:name" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:name"><xsl:attribute name="name"><xsl:value-of select="gpxOld:name" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:metadata/gpx:author/gpx:name"><xsl:attribute name="author"><xsl:value-of select="gpx:metadata/gpx:author/gpx:name" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:name"><xsl:attribute name="author"><xsl:value-of select="gpxOld:author" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:metadata/gpx:time"><xsl:attribute name="time"><xsl:value-of select="normalize-space(gpx:metadata/gpx:time)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:time"><xsl:attribute name="time"><xsl:value-of select="normalize-space(gpxOld:time)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:apply-templates select="gpx:wpt | gpxOld:wpt" />
<xsl:apply-templates select="gpx:trk | gpxOld:trk" />
</gpx>
</xsl:template>
<xsl:template match="gpx:wpt">
<xsl:template match="gpx:wpt | gpxOld:wpt">
<wpt>
<xsl:call-template name="point" />
<xsl:choose>
<xsl:when test="gpx:extensions/g3:WaypointExtension/g3:Temperature">
<xsl:attribute name="temperature"><xsl:value-of select="gpx:extensions/g3:WaypointExtension/g3:Temperature" /></xsl:attribute>
<xsl:attribute name="temperature"><xsl:value-of select="normalize-space(gpx:extensions/g3:WaypointExtension/g3:Temperature)" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/w1:WaypointExtension/w1:Temperature">
<xsl:attribute name="temperature"><xsl:value-of select="gpx:extensions/w1:WaypointExtension/w1:Temperature" /></xsl:attribute>
<xsl:attribute name="temperature"><xsl:value-of select="normalize-space(gpx:extensions/w1:WaypointExtension/w1:Temperature)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:extensions/g3:WaypointExtension/g3:Depth">
<xsl:attribute name="depth"><xsl:value-of select="gpx:extensions/g3:WaypointExtension/g3:Depth" /></xsl:attribute>
<xsl:attribute name="depth"><xsl:value-of select="normalize-space(gpx:extensions/g3:WaypointExtension/g3:Depth)" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/w1:WaypointExtension/w1:Depth">
<xsl:attribute name="depth"><xsl:value-of select="gpx:extensions/w1:WaypointExtension/w1:Depth" /></xsl:attribute>
<xsl:attribute name="depth"><xsl:value-of select="normalize-space(gpx:extensions/w1:WaypointExtension/w1:Depth)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
</wpt>
</xsl:template>
<xsl:template match="gpx:trk">
<xsl:template match="gpx:trk |gpxOld:trk">
<trk>
<xsl:attribute name="name"><xsl:value-of select="gpx:name" /></xsl:attribute>
<xsl:if test="gpx:type"><xsl:attribute name="type"><xsl:value-of select="gpx:type" /></xsl:attribute></xsl:if>
<xsl:apply-templates select="gpx:trkseg" />
<xsl:choose>
<xsl:when test="gpx:name"><xsl:attribute name="name"><xsl:value-of select="gpx:name" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:name"><xsl:attribute name="name"><xsl:value-of select="gpxOld:name" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:type"><xsl:attribute name="type"><xsl:value-of select="normalize-space(gpx:type)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:type"><xsl:attribute name="type"><xsl:value-of select="normalize-space(gpxOld:type)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:apply-templates select="gpx:trkseg | gpxOld:trkseg" />
</trk>
</xsl:template>
<xsl:template match="gpx:trkseg">
<xsl:template match="gpx:trkseg | gpxOld:trkseg">
<trkseg>
<xsl:apply-templates select="gpx:trkpt" />
<xsl:apply-templates select="gpx:trkpt | gpxOld:trkpt" />
</trkseg>
</xsl:template>
<xsl:template match="gpx:trkpt">
<xsl:template match="gpx:trkpt | gpxOld:trkpt">
<trkpt>
<xsl:call-template name="point" />
<xsl:choose>
<xsl:when test="gpx:extensions/tx2:TrackPointExtension/tx2:atemp">
<xsl:attribute name="temperature"><xsl:value-of select="gpx:extensions/tx2:TrackPointExtension/tx2:atemp" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/tx:TrackPointExtension/tx:atemp">
<xsl:attribute name="temperature"><xsl:value-of select="gpx:extensions/tx:TrackPointExtension/tx:atemp" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/g3:TrackPointExtension/g3:Temperature">
<xsl:attribute name="temperature"><xsl:value-of select="gpx:extensions/g3:TrackPointExtension/g3:Temperature" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:extensions/tx2:TrackPointExtension/tx2:depth">
<xsl:attribute name="depth"><xsl:value-of select="gpx:extensions/tx2:TrackPointExtension/tx2:depth" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/tx:TrackPointExtension/tx:depth">
<xsl:attribute name="depth"><xsl:value-of select="gpx:extensions/tx:TrackPointExtension/tx:depth" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/g3:TrackPointExtension/g3:Depth">
<xsl:attribute name="depth"><xsl:value-of select="gpx:extensions/g3:TrackPointExtension/g3:Depth" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:extensions/tx2:TrackPointExtension/tx2:hr">
<xsl:attribute name="hr"><xsl:value-of select="gpx:extensions/tx2:TrackPointExtension/tx2:hr" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/tx:TrackPointExtension/tx:hr">
<xsl:attribute name="hr"><xsl:value-of select="gpx:extensions/tx:TrackPointExtension/tx:hr" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:extensions/tx2:TrackPointExtension/tx2:cad">
<xsl:attribute name="cad"><xsl:value-of select="gpx:extensions/tx2:TrackPointExtension/tx2:cad" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/tx:TrackPointExtension/tx:cad">
<xsl:attribute name="cad"><xsl:value-of select="gpx:extensions/tx:TrackPointExtension/tx:cad" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:extensions/tx2:TrackPointExtension/tx2:speed">
<xsl:attribute name="speed"><xsl:value-of select="gpx:extensions/tx2:TrackPointExtension/tx2:speed" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:extensions/ax:TrackPointExtension/ax:speed">
<xsl:attribute name="speed"><xsl:value-of select="gpx:extensions/ax:TrackPointExtension/ax:speed" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:apply-templates select="gpx:extensions | gpxOld:extensions" />
<xsl:if test="gpxOld:speed">
<xsl:attribute name="speed"><xsl:value-of select="normalize-space(gpxOld:speed)" /></xsl:attribute>
</xsl:if>
</trkpt>
</xsl:template>
<xsl:template match="gpx:extensions | gpxOld:extensions">
<xsl:choose>
<xsl:when test="tx2:TrackPointExtension/tx2:atemp">
<xsl:attribute name="temperature"><xsl:value-of select="normalize-space(tx2:TrackPointExtension/tx2:atemp)" /></xsl:attribute>
</xsl:when>
<xsl:when test="tx:TrackPointExtension/tx:atemp">
<xsl:attribute name="temperature"><xsl:value-of select="normalize-space(tx:TrackPointExtension/tx:atemp)" /></xsl:attribute>
</xsl:when>
<xsl:when test="g3:TrackPointExtension/g3:Temperature">
<xsl:attribute name="temperature"><xsl:value-of select="normalize-space(g3:TrackPointExtension/g3:Temperature)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="tx2:TrackPointExtension/tx2:depth">
<xsl:attribute name="depth"><xsl:value-of select="normalize-space(tx2:TrackPointExtension/tx2:depth)" /></xsl:attribute>
</xsl:when>
<xsl:when test="tx:TrackPointExtension/tx:depth">
<xsl:attribute name="depth"><xsl:value-of select="normalize-space(tx:TrackPointExtension/tx:depth)" /></xsl:attribute>
</xsl:when>
<xsl:when test="g3:TrackPointExtension/g3:Depth">
<xsl:attribute name="depth"><xsl:value-of select="normalize-space(g3:TrackPointExtension/g3:Depth)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="tx2:TrackPointExtension/tx2:hr">
<xsl:attribute name="hr"><xsl:value-of select="normalize-space(tx2:TrackPointExtension/tx2:hr)" /></xsl:attribute>
</xsl:when>
<xsl:when test="tx:TrackPointExtension/tx:hr">
<xsl:attribute name="hr"><xsl:value-of select="normalize-space(tx:TrackPointExtension/tx:hr)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="tx2:TrackPointExtension/tx2:cad">
<xsl:attribute name="cad"><xsl:value-of select="normalize-space(tx2:TrackPointExtension/tx2:cad)" /></xsl:attribute>
</xsl:when>
<xsl:when test="tx:TrackPointExtension/tx:cad">
<xsl:attribute name="cad"><xsl:value-of select="normalize-space(tx:TrackPointExtension/tx:cad)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="tx2:TrackPointExtension/tx2:speed">
<xsl:attribute name="speed"><xsl:value-of select="normalize-space(tx2:TrackPointExtension/tx2:speed)" /></xsl:attribute>
</xsl:when>
<xsl:when test="tx:TrackPointExtension/tx:speed">
<xsl:attribute name="speed"><xsl:value-of select="normalize-space(tx:TrackPointExtension/tx:speed)" /></xsl:attribute>
</xsl:when>
<xsl:when test="ax:TrackPointExtension/ax:speed">
<xsl:attribute name="speed"><xsl:value-of select="normalize-space(ax:TrackPointExtension/ax:speed)" /></xsl:attribute>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="point">
<xsl:attribute name="lat"><xsl:value-of select="@lat" /></xsl:attribute>
<xsl:attribute name="lon"><xsl:value-of select="@lon" /></xsl:attribute>
<xsl:if test="gpx:ele"><xsl:attribute name="ele"><xsl:value-of select="gpx:ele" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:time"><xsl:attribute name="time"><xsl:value-of select="gpx:time" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:name"><xsl:attribute name="name"><xsl:value-of select="gpx:name" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:desc"><xsl:attribute name="desc"><xsl:value-of select="gpx:desc" /></xsl:attribute></xsl:if>
<xsl:choose>
<xsl:when test="gpx:desc">
<xsl:attribute name="desc"><xsl:value-of select="gpx:desc" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:cmt">
<xsl:attribute name="desc"><xsl:value-of select="gpx:cmt" /></xsl:attribute>
</xsl:when>
<xsl:when test="gpx:ele"><xsl:attribute name="ele"><xsl:value-of select="normalize-space(gpx:ele)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:ele"><xsl:attribute name="ele"><xsl:value-of select="normalize-space(gpxOld:ele)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:time"><xsl:attribute name="time"><xsl:value-of select="normalize-space(gpx:time)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:time"><xsl:attribute name="time"><xsl:value-of select="normalize-space(gpxOld:time)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:name"><xsl:attribute name="name"><xsl:value-of select="gpx:name" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:name"><xsl:attribute name="name"><xsl:value-of select="gpxOld:name" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:desc"><xsl:attribute name="desc"><xsl:value-of select="gpx:desc" /></xsl:attribute></xsl:when>
<xsl:when test="gpx:cmt"><xsl:attribute name="desc"><xsl:value-of select="gpx:cmt" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:desc"><xsl:attribute name="desc"><xsl:value-of select="gpxOld:desc" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:cmt"><xsl:attribute name="desc"><xsl:value-of select="gpxOld:cmt" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:sym"><xsl:attribute name="sym"><xsl:value-of select="normalize-space(gpx:sym)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:sym"><xsl:attribute name="sym"><xsl:value-of select="normalize-space(gpxOld:sym)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:hdop"><xsl:attribute name="hdop"><xsl:value-of select="normalize-space(gpx:hdop)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:hdop"><xsl:attribute name="hdop"><xsl:value-of select="normalize-space(gpxOld:hdop)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:vdop"><xsl:attribute name="vdop"><xsl:value-of select="normalize-space(gpx:vdop)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:vdop"><xsl:attribute name="vdop"><xsl:value-of select="normalize-space(gpxOld:vdop)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="gpx:pdop"><xsl:attribute name="pdop"><xsl:value-of select="normalize-space(gpx:pdop)" /></xsl:attribute></xsl:when>
<xsl:when test="gpxOld:pdop"><xsl:attribute name="pdop"><xsl:value-of select="normalize-space(gpxOld:pdop)" /></xsl:attribute></xsl:when>
</xsl:choose>
<xsl:if test="gpx:sym"><xsl:attribute name="sym"><xsl:value-of select="gpx:sym" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:hdop"><xsl:attribute name="hdop"><xsl:value-of select="gpx:hdop" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:vdop"><xsl:attribute name="vdop"><xsl:value-of select="gpx:vdop" /></xsl:attribute></xsl:if>
<xsl:if test="gpx:pdop"><xsl:attribute name="pdop"><xsl:value-of select="gpx:pdop" /></xsl:attribute></xsl:if>
</xsl:template>
</xsl:stylesheet>
@@ -1,4 +1,4 @@
/* Copyright (C) 2023-2025 José Rebelo, Thomas Kuehne
/* Copyright (C) 2023-2026 José Rebelo, Thomas Kuehne
This file is part of Gadgetbridge.
@@ -200,4 +200,22 @@ public class GPXParserTest extends TestBase {
Assert.assertEquals(trackpoint.getTime(), activityPoint.getTime());
Assert.assertEquals(trackpoint.getVdop(), activityPoint.getLocation().getVdop(), 0.0);
}
// test import of old GPX v1.0
@Test
public void TestGpxImportOld() throws Exception {
final byte[] actual;
try (final InputStream gpx = getClass().getResourceAsStream("/TestGpxImportOld.gpx")) {
actual = GpxParser.transformGpx(gpx);
}
byte[] expected = readBinaryResource("/TestGpxImportOld.xml");
Assert.assertArrayEquals(expected, actual);
final GpxFile file1;
try (final InputStream gpx = getClass().getResourceAsStream("/TestGpxImportOld.gpx")) {
file1 = new GpxParser(gpx).getGpxFile();
}
Assert.assertNotNull(file1);
}
}
+26 -26
View File
@@ -17,18 +17,18 @@
</metadata>
<wpt lat="47.5048828125" lon="9.7393798828125">
<ele>-470.1</ele>
<time>2025-10-03T14:10:59Z</time>
<ele>-470.1 <!-- comment --></ele>
<time>2025-10-03T14:10:59Z <!-- comment --></time>
<name>Bregenz</name>
<desc>city in Österreich</desc>
<sym>Airport</sym>
<hdop>1.4</hdop>
<vdop>3.2</vdop>
<pdop>1.5</pdop>
<hdop>1.4 <!-- comment --></hdop>
<vdop>3.2 <!-- comment --></vdop>
<pdop>1.5 <!-- comment --></pdop>
<extensions>
<wpx:WaypointExtension>
<wpx:Temperature>9.1</wpx:Temperature>
<wpx:Depth>6.1</wpx:Depth>
<wpx:Temperature>9.1 <!-- comment --></wpx:Temperature>
<wpx:Depth>6.1 <!-- comment --></wpx:Depth>
</wpx:WaypointExtension>
</extensions>
</wpt>
@@ -41,8 +41,8 @@
<sym>Anchor</sym>
<extensions>
<ge:WaypointExtension>
<ge:Temperature>19.2</ge:Temperature>
<ge:Depth>16.2</ge:Depth>
<ge:Temperature>19.2 <!-- comment --></ge:Temperature>
<ge:Depth>16.2 <!-- comment --></ge:Depth>
</ge:WaypointExtension>
</extensions>
</wpt>
@@ -74,23 +74,23 @@
<name>Gadgetbridge import test track</name>
<trkseg>
<trkpt lat="47.5048828125" lon="9.7393798828125">
<ele>-440.2</ele>
<time>2025-10-03T15:10:59Z</time>
<ele>-440.2 <!-- comment --></ele>
<time>2025-10-03T15:10:59Z <!-- comment --></time>
<name>Tp1</name>
<desc>a description</desc>
<sym>Summit</sym>
<hdop>1.4</hdop>
<vdop>3.2</vdop>
<pdop>1.5</pdop>
<hdop>1.4 <!-- comment --></hdop>
<vdop>3.2 <!-- comment --></vdop>
<pdop>1.5 <!-- comment --></pdop>
<extensions>
<t1:TrackPointExtension>
<t1:atemp>28.3</t1:atemp>
<t1:depth>26.3</t1:depth>
<t1:hr>123</t1:hr>
<t1:cad>22</t1:cad>
<t1:atemp>28.3 <!-- comment --></t1:atemp>
<t1:depth>26.3 <!-- comment --></t1:depth>
<t1:hr>123 <!-- comment --></t1:hr>
<t1:cad>22 <!-- comment --></t1:cad>
</t1:TrackPointExtension>
<ax:TrackPointExtension>
<ax:speed>23.3</ax:speed>
<ax:speed>23.3 <!-- comment --></ax:speed>
</ax:TrackPointExtension>
</extensions>
</trkpt>
@@ -102,8 +102,8 @@
<sym>Water</sym>
<extensions>
<ge:TrackPointExtension>
<ge:Temperature>34.3</ge:Temperature>
<ge:Depth>10345</ge:Depth>
<ge:Temperature>34.3 <!-- comment --></ge:Temperature>
<ge:Depth>10345 <!-- comment --></ge:Depth>
</ge:TrackPointExtension>
</extensions>
</trkpt>
@@ -111,11 +111,11 @@
<time>2025-10-03T03:30:00-12:00</time>
<extensions>
<t2:TrackPointExtension>
<t2:atemp>40.4</t2:atemp>
<t2:depth>41.4</t2:depth>
<t2:hr>42</t2:hr>
<t2:cad>43</t2:cad>
<t2:speed>44.4</t2:speed>
<t2:atemp>40.4 <!-- comment --></t2:atemp>
<t2:depth>41.4 <!-- comment --></t2:depth>
<t2:hr>42 <!-- comment --></t2:hr>
<t2:cad>43 <!-- comment --></t2:cad>
<t2:speed>44.4 <!-- comment --></t2:speed>
</t2:TrackPointExtension>
</extensions>
</trkpt>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" ?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"
creator="GPSLogger 79 - http://gpslogger.mendhak.com/"
xmlns="http://www.topografix.com/GPX/1/0"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd"
xmlns:ns3="http://www.garmin.com/xmlschemas/TrackPointExtension/v1">
<name>Five Hikes in the White Mountains</name>
<desc>Five Hikes in the White Mountains!!</desc>
<author>Franz Wilhelmstötter</author>
<email>franz.wilhelmstoetter@gmail.com</email>
<url>https://github.com/jenetics/jpx</url>
<urlname>Visit my New Hampshire hiking website!</urlname>
<time>2016-08-21T12:24:27Z</time>
<keywords>Hiking, NH, Presidential Range</keywords>
<wpt lat="48.2033471" lon="16.3608048">
<time>2016-08-21T12:51:30Z <!-- comment -->
</time>
<name>khm</name>
<src>network</src>
<extensions><foo>asdf</foo><foo>asdf</foo></extensions>
</wpt>
<wpt lat="48.34067" lon="16.71754">
<ele>164.0 <!-- comment -->
</ele>
<name>Gänserndorf</name>
</wpt>
<trk>
<name>March 21</name>
<trkseg>
<trkpt lat="48.19949341" lon="16.40377444">
<ele>212.0 <!--comment-->
</ele>
<time>2016-08-21T12:24:27Z <!--comment-->
</time>
<course>341.6 <!--comment-->
</course>
<speed>0.67052215 <!--comment-->
</speed>
<src>gps <!--comment-->
</src>
<sat>14 <!--comment-->
</sat>
</trkpt>
<trkpt lat="-48.19948359" lon="16.40371021">
<ele>212.0 <ignoreBrokenXml /></ele>
<time>2016-08-21T12:24:31Z <!-- comment -->
</time>
<course>298.6 <!-- comment -->
</course>
<speed>0.7424285 <!-- comment -->
</speed>
<geoidheight>43.0 <!-- comment -->
</geoidheight>
<src>gps</src>
<sat>2</sat>
<hdop>0.7 <!-- comment -->
</hdop>
<vdop>0.8 <!-- comment -->
</vdop>
<pdop>1.1 <!-- comment -->
</pdop>
</trkpt>
<trkpt lat="45.589817" lon="-73.67511">
<ele>42.05 <!-- comment -->
</ele>
<time>2023-05-07T18:34:59Z <!-- comment -->
</time>
<name>Position 1</name>
<extensions>
<ns3:TrackPointExtension>
<ns3:speed>2.3255813 <!-- comment -->
</ns3:speed> <!-- comment -->
<ns3:cad>0.0 <!-- comment -->
</ns3:cad>
<ns3:hr>72 <!-- comment -->
</ns3:hr>
</ns3:TrackPointExtension>
</extensions>
</trkpt>
<trkpt lat="52.52543" lon="0.07307"><speed>NaN</speed></trkpt>
<trkpt lat="52.52483" lon="0.07329" />
</trkseg>
</trk>
<trk>
<trkseg>
<trkpt lat="52.53395" lon="0.07863">
<extensions />
</trkpt>
</trkseg>
<trkseg>
<trkpt lat="52.53667" lon="0.09328"></trkpt>
<trkpt lat="52.5367" lon="0.09352"></trkpt>
</trkseg>
</trk>
</gpx>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?><gpx name="Five Hikes in the White Mountains" author="Franz Wilhelmstötter" time="2016-08-21T12:24:27Z">
<wpt lat="48.2033471" lon="16.3608048" time="2016-08-21T12:51:30Z" name="khm"/>
<wpt lat="48.34067" lon="16.71754" ele="164.0" name="Gänserndorf"/>
<trk name="March 21">
<trkseg>
<trkpt lat="48.19949341" lon="16.40377444" ele="212.0" time="2016-08-21T12:24:27Z" speed="0.67052215"/>
<trkpt lat="-48.19948359" lon="16.40371021" ele="212.0" time="2016-08-21T12:24:31Z" hdop="0.7" vdop="0.8" pdop="1.1" speed="0.7424285"/>
<trkpt lat="45.589817" lon="-73.67511" ele="42.05" time="2023-05-07T18:34:59Z" name="Position 1" hr="72" cad="0.0" speed="2.3255813"/>
<trkpt lat="52.52543" lon="0.07307" speed="NaN"/>
<trkpt lat="52.52483" lon="0.07329"/>
</trkseg>
</trk>
<trk>
<trkseg>
<trkpt lat="52.53395" lon="0.07863"/>
</trkseg>
<trkseg>
<trkpt lat="52.53667" lon="0.09328"/>
<trkpt lat="52.5367" lon="0.09352"/>
</trkseg>
</trk>
</gpx>