Skip to content

Merged GPX file fails validation #63

Closed

Description

@KronosTheLate

Merging two files that are valid produces a resulting file that has the following errors:

S4s-elt-character: Non-whitespace Characters Are Not Allowed In Schema Elements Other Than 'xs:appinfo' And 'xs:documentation'. Saw 'Document Moved'., Line '1', Column '28'.
The Markup In The Document Following The Root Element Must Be Well-formed., Line '2', Column '2'.
The Markup In The Document Following The Root Element Must Be Well-formed.

I used this page for validation, as reccomended here.

File 1 contents
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="Colota" xmlns="http://www.topografix.com/GPX/1/1">
  <metadata>
    <name>Colota Location Export</name>
    <time>2026-05-20T22:04:53.000Z</time>
  </metadata>
  <trk>
    <name>Colota Track Export</name>
    <trkseg>
      <trkpt lat="62.424161" lon="6.274748">
        <ele>78</ele>
        <time>2026-05-20T10:14:42.000Z</time>
        <extensions>
          <accuracy>19.296001434326172</accuracy>
          <speed>0</speed>
          <battery>35</battery>
        </extensions>
      </trkpt>
      <trkpt lat="62.423844" lon="6.275863">
        <ele>87</ele>
        <time>2026-05-20T20:06:47.000Z</time>
        <extensions>
          <accuracy>68.60800170898438</accuracy>
          <speed>0.6600000262260437</speed>
          <battery>12</battery>
        </extensions>
      </trkpt>
    </trkseg>
  </trk>
</gpx>
File 2 contents
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="Colota" xmlns="http://www.topografix.com/GPX/1/1">
  <metadata>
    <name>Colota Location Export</name>
    <time>2026-05-20T12:27:43.000Z</time>
  </metadata>
  <trk>
    <name>Colota Track Export</name>
    <trkseg>
      <trkpt lat="62.424161" lon="6.274748">
        <ele>78</ele>
        <time>2026-05-20T10:14:42.000Z</time>
        <extensions>
          <accuracy>19.296001434326172</accuracy>
          <speed>0</speed>
          <battery>35</battery>
        </extensions>
      </trkpt>
      <trkpt lat="62.424104" lon="6.275333">
        <ele>63</ele>
        <time>2026-05-20T10:17:32.000Z</time>
        <extensions>
          <accuracy>254.0640106201172</accuracy>
          <speed>0</speed>
          <battery>34</battery>
        </extensions>
      </trkpt>
    </trkseg>
  </trk>
</gpx>
Merged file contents
<?xml version='1.0' encoding='utf-8'?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" creator="https://github.com/sgraaf/gpx">
  <trk>
    <name>Colota Track Export</name>
    <trkseg>
      <trkpt lat="62.424161" lon="6.274748">
        <ele>78</ele>
        <time>2026-05-20T10:14:42Z</time>
        <extensions>
          <accuracy>19.296001434326172</accuracy>
          <speed>0</speed>
          <battery>35</battery>
        </extensions>
      </trkpt>
      <trkpt lat="62.423844" lon="6.275863">
        <ele>87</ele>
        <time>2026-05-20T20:06:47Z</time>
        <extensions>
          <accuracy>68.60800170898438</accuracy>
          <speed>0.6600000262260437</speed>
          <battery>12</battery>
        </extensions>
      </trkpt>
    </trkseg>
  </trk>
  <trk>
    <name>Colota Track Export</name>
    <trkseg>
      <trkpt lat="62.424161" lon="6.274748">
        <ele>78</ele>
        <time>2026-05-20T10:14:42Z</time>
        <extensions>
          <accuracy>19.296001434326172</accuracy>
          <speed>0</speed>
          <battery>35</battery>
        </extensions>
      </trkpt>
      <trkpt lat="62.424104" lon="6.275333">
        <ele>63</ele>
        <time>2026-05-20T10:17:32Z</time>
        <extensions>
          <accuracy>254.0640106201172</accuracy>
          <speed>0</speed>
          <battery>34</battery>
        </extensions>
      </trkpt>
    </trkseg>
  </trk>
</gpx>

Activity

  1. KronosTheLate commented on May 30, 2026

    @KronosTheLate
    Author

    Note that a file created with the gpxpy python package has exactly the same issues, so I also raised this issue over there

  2. sgraaf commented on Jun 1, 2026

    @sgraaf
    Owner

    Hi there!

    Thank you for raising this issue. There are two different things going on here, I think:

    1. The two files (before merge) you shared are invalid GPX files themselves, as they make use of extension elements without a namespace prefix. As such, they are assumed to belong to the default namespace (http://www.topografix.com/GPX/1/1 in this case), which they do not.
    2. The XML validator you use apparently does not follow HTTP 301 permanent redirects. About 2,5 years ago, the people behind GPX made it so that HTTP requests for the GPX 1.1 schema are temporarily being 301-redirected to HTTPS "to surface any issues with GPX implementations or validation procedures [...]". Changing http://www.topografix.com/GPX/1/1/gpx.xsd to https://www.topografix.com/GPX/1/1/gpx.xsd in the xsi:schemaLocation directive of the root gpx element resolves the XML validation errors you report above, but does raise the errors of the two unmerged files mentioned above. In my opinion this is an issue with the XML validator you use, more so than with the output of this package.

    All told, I do think the merged GPX file produced by this package is valid, and that there is no "bug" to be fixed here. What I could do is raise a warning when a GPX file is read that contains invalid extensions elements as a UX improvement.

    Curious to read your thoughts should you feel differently.

  3. KronosTheLate commented on Jun 3, 2026

    @KronosTheLate
    Author

    Your comment is very educational, and I agree with all your sentiments. Also, big fan of the UX improvement you suggested!

  4. sgraaf commented on Jun 15, 2026

    @sgraaf
    Owner

    I just merged #66 that implements the UX improvement discussed:

    $ gpx merge --strict colota_1.gpx colota_2.gpx -o colota_merged.gpx 
    ⚠ colota_1.gpx: 6 warnings
      WARNING line 14  gpx > trk[0] > trkseg[0] > trkpt[0] > extensions > accuracy: <extensions> child <accuracy> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 15  gpx > trk[0] > trkseg[0] > trkpt[0] > extensions > speed: <extensions> child <speed> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 16  gpx > trk[0] > trkseg[0] > trkpt[0] > extensions > battery: <extensions> child <battery> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 23  gpx > trk[0] > trkseg[0] > trkpt[1] > extensions > accuracy: <extensions> child <accuracy> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 24  gpx > trk[0] > trkseg[0] > trkpt[1] > extensions > speed: <extensions> child <speed> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 25  gpx > trk[0] > trkseg[0] > trkpt[1] > extensions > battery: <extensions> child <battery> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
    ⚠ colota_2.gpx: 6 warnings
      WARNING line 14  gpx > trk[0] > trkseg[0] > trkpt[0] > extensions > accuracy: <extensions> child <accuracy> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 15  gpx > trk[0] > trkseg[0] > trkpt[0] > extensions > speed: <extensions> child <speed> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 16  gpx > trk[0] > trkseg[0] > trkpt[0] > extensions > battery: <extensions> child <battery> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 23  gpx > trk[0] > trkseg[0] > trkpt[1] > extensions > accuracy: <extensions> child <accuracy> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 24  gpx > trk[0] > trkseg[0] > trkpt[1] > extensions > speed: <extensions> child <speed> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
      WARNING line 25  gpx > trk[0] > trkseg[0] > trkpt[1] > extensions > battery: <extensions> child <battery> is in the GPX namespace (extension content must use a foreign namespace per GPX 1.1)
    Merged 2 files into: colota_merged.gpx
      Waypoints: 0
      Routes: 0
      Tracks: 2
  5. KronosTheLate commented on Jun 16, 2026

    @KronosTheLate
    Author

    Amazing! Thanks for this 😸

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions