tkrajina/gpxpy

Cannot parse files where the default namespace is http://www.garmin.com/xmlschemas/TrackPointExtension/v2

KennethEvans opened this issue · 3 comments

Normally the default namespace for a GPX file is http://www.topografix.com/GPX/1/1.

However it doesn't have to be. Many of my files have the default namespace as http://www.garmin.com/xmlschemas/TrackPointExtension/v2

(TrackPointExtension/v2 is a common way to include heart rate data.)

It is not under my control how they do this, and I believe it is perfectly valid. These files open and parse correctly in all the other GPX applications I use. They open but don't parse correctly in gpxpy. In particular, no tracks are found.

The difference is
Ok Files:

<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:ns2="http://www.garmin.com/xmlschemas/TrackPointExtension/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" creator="Polar Access Manager" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">

Not OK files:

<ns2:gpx xmlns="http://www.garmin.com/xmlschemas/TrackPointExtension/v2" xmlns:ns2="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" creator="Polar Access Manager" xsi:schemaLocation="http://www.topografix.com/GPX/1/1

gpx.nsmap gives:
Ok Files:

Namespaces:
    defaultns: http://www.topografix.com/GPX/1/1
    ns2: http://www.garmin.com/xmlschemas/TrackPointExtension/v2
    xsi: http://www.w3.org/2001/XMLSchema-instance

Not Ok files:

Namespaces:
    defaultns: http://www.garmin.com/xmlschemas/TrackPointExtension/v2
    ns2: http://www.topografix.com/GPX/1/1
    xsi: http://www.w3.org/2001/XMLSchema-instanc

Notice xsi is not all there.

Sample files:
gpxpy_issue.zip

Yes, it is definitely not handling the case where the default namespace is not http://www.topografix.com/GPX/1/1. That seems to be a bug to me. In fact, even ElementTree by default will use ns0 for http://www.topografix.com/GPX/1/1 and no default namespace. It is valid.

I fixed it by using ElementTree to parse the file after setting the default namespace to be http://www.topografix.com/GPX/1/1 and then passing the resulting XML to gpxpy.parse.

import xml.etree.ElementTree as ET

        # Ensure GPX/1/1 is the default namespace
        ET.register_namespace('', "http://www.topografix.com/GPX/1/1")
        tree = ET.parse(file_name)
        root = tree.getroot();
        xml = ET.tostring(root, encoding='unicode');
        # Parse the xml string
        gpx = gpxpy.parse(xml)

tve commented

I'm having a perhaps similar problem. Converting garmin fit files to gpx results in:

<gpx version="1.1" creator="GPSBabel - https://www.gpsbabel.org" xmlns="http://www.topografix.com/GP
X/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmi
n.com/xmlschemas/TrackPointExtension/v1">

and have trkpt looking like

      <trkpt lat="34.405181017" lon="-119.842143841">
        <ele>-4.200</ele>
        <time>2022-02-15T22:12:26Z</time>
        <extensions>
          <gpxtpx:TrackPointExtension>
            <gpxtpx:atemp>20.000000</gpxtpx:atemp>
            <gpxtpx:hr>153</gpxtpx:hr>
          </gpxtpx:TrackPointExtension>
        </extensions>
      </trkpt>

and after parsing segment points have an empty extensions field.

+1, OpenTracks saves the speed with gpxtpx even though the default namespace is the topografix 1.1 one, eg.:

<trkpt lat="12.34567" lon="12.34567">
<ele>72</ele>
<time>2024-05-04T00:00:00.000+01:00</time>
<extensions><gpxtpx:TrackPointExtension>
<gpxtpx:speed>1.3</gpxtpx:speed>
<opentracks:accuracy_horizontal>1.891</opentracks:accuracy_horizontal></gpxtpx:TrackPointExtension></extensions>

The extensions attribute of the GPXTrackPoint has one element with a tag '{http://www.garmin.com/xmlschemas/TrackPointExtension/v2}TrackPointExtension' and a text of '\n'.