GPX Parsing

GPX Parsing

[160] This specification defines how to parse GPX files.

[205] The original GPX specification does not define how to interpret GPX files.

Data model

[9] A data set has name, description, keywords, generator, timestamp, updated, author, license, minimum latitude, minimum longitude, maximum latitude, maximum longitude, and time-zone offset, which are initially null.

[19] A data set has waypoints, routes, tracks, and links, which are initially empty lists.

[26] A point has name, description, timestamp, latitude, longitude, elevation, geoid height, magnetic variation, comment, source, symbol name, type, fix, number of satellites, hdop, vdop, age of DGPS data, DGPS ID, speed, accuracy, temperature, water temperature, depth, cadence, distance, to distance, heartrate, point role, power, and road type, which are initially null.

[189] A route has links, which is initially an empty list.

[45] A route has name, description, comment, source, type, and number, which are initially null.

[62] A route has points and links, which are initially empty lists.

[72] A track has name, description, comment, source, type, and number, which are initially null.

[73] A track has segments and links, which are initially empty lists.

[74] A track segment has points, which is initially an empty list.

[43] A person has name and email, which are initially null.

[207] A person has links, which is initially an empty list.

[51] A license has holder, year, and URL, which are initially null.

[202] A link has URL, MIME type, and text, which are initially null.


[188] A track is a valid timestamped route if all of the following conditions are true:

Parsing

[206] An implementation MUST use an XML parser that implements XML5 to parse a GPX file. It MUST NOT fetch and process external entities.

[159] An implementation MUST use the steps to parse a GPX document to parse a Document as a GPX document.

[1] To parse a GPX document doc, run these steps:

  1. [2] Let element be doc's document element.
  2. [4] If element is an element whose local name is gpx:
    1. [6] Return the result of parsing a gpx element element.
  3. [11] Otherwise:
    1. [12] Return null.

[78] These steps ignore any duplicate link element. They also ignore any link content.

[10] To parse a gpx element element, run these steps:

  1. [79] Let data set be a data set.
  2. [17] Let creator be element's creator attribute value.
  3. [59] If creator is not null and is not the empty string:
    1. [71] Set data set's generator to creator.
  4. [179] Let tzoffset be element's tzoffset attribute value in the GPX extension namespace.
  5. [182] If tzoffset is not null and is not the empty string:
    1. [183] Let offset be the result of parsing a time-zone offset string tzoffset.
    2. [184] If offset is not nothing:
      1. [181] Set data set's time-zone offset to offset.
  6. [14] For each element child in element's children:
    1. [15] Switch by child's local name:
      metadata
      1. [29] For each element gc in child's children:
        1. [20] Process gc with data set, using the following table:
          l
          local name
          f
          Field
          r
          Rule
          l
          name
          f
          name
          r
          String
          l
          desc
          f
          description
          r
          String
          l
          keywords
          f
          keywords
          r
          String
          l
          link
          f
          links
          r
          Link
          l
          author
          f
          author
          r
          Person
          l
          copyright
          f
          license
          r
          License
        2. [30] If gc's local name is time:
          1. [83] If gc's namespace is http://www.topografix.com/GPX/gpx_modified/0/1:
            1. [88] If data set's updated is null:
              1. [85] Let text be gc's child text content.
              2. [86] Parse a global date and time string text.
              3. [87] If a time is returned, set data set's updated to the time.
          2. [84] Otherwise:
            1. [89] If data set's timestamp is null:
              1. [90] Let text be gc's child text content.
              2. [91] Parse a global date and time string text.
              3. [92] If a time is returned, set data set's timestamp to the time.
        3. [40] If gc's local name is bounds:
          1. [97] If data set's minimum latitude is null:
            1. [98] Set data set's minimum latitude be the result of applying the rules for parsing a latitude value to gc's minlat attribute value.
          2. [99] If data set's minimum longitude is null:
            1. [100] Set data set's minimum longitude be the result of applying the rules for parsing a longitude value to gc's minlon attribute value.
          3. [101] If data set's maximum latitude is null:
            1. [102] Set data set's maximum latitude be the result of applying the rules for parsing a latitude value to gc's maxlat attribute value.
          4. [103] If data set's maximum longitude is null:
            1. [104] Set data set's maximum longitude be the result of applying the rules for parsing a longitude value to gc's maxlon attribute value.
      wpt
      Append the result of parsing a point element child to data set's waypoints.
      rte
      Append the result of parsing a route element child to data set's routes.
      trk
      Append the result of parsing a track element child to data set's tracks.
  7. [115] Return data set.

[27] To parse a point element element, run these steps:

  1. [25] Let point be a point.
  2. [116] Set point's latitude to the result of applying the rules for parsing a latitude value to element's lat attribute value.
  3. [118] Set point's longitude to the result of applying the rules for parsing a latitude value to element's lon attribute value.
  4. [185] Let road be element's road attribute value in the GPX extension namespace.
  5. [186] If road is a valid road type string:
    1. [187] Set point's road type to road.
  6. [218] Let role be element's pointrole attribute value in the GPX extension namespace.
  7. [219] If role is a valid point role string:
    1. [220] Set point's point role to role.
  8. [21] Set to distance be element's todistance attribute value in the GPX extension namespace.
  9. [22] If to distance is not null:
    1. [32] Let number be the result of applying the rules for parsing floating-point number values to to distance.
    2. [31] If number is a number greater than or equal to 0:
      1. [33] Set point's to distance to number.
  10. [18] For each element child in element's children:
    1. [154] Process child with point, using the following table:
      l
      local name
      f
      Field
      r
      Rule
      l
      sat
      f
      number of satellites
      r
      Non-negative number
      l
      dgpsid
      f
      DGPS ID
      r
      Non-negative integer
      l
      ele
      f
      elevation
      r
      Number
      l
      geoidheight
      f
      geoid height
      r
      Number
      l
      hdop
      f
      hdop
      r
      Number
      l
      vdop
      f
      vdop
      r
      Number
      l
      pdop
      f
      pdop
      r
      Number
      l
      ageofdgpsdata
      f
      age of DGPS data
      r
      Number
      l
      speed
      f
      speed
      r
      Number
      l
      magvar
      f
      magnetic variation
      r
      Degree
      l
      time
      f
      timestamp
      r
      Time
      l
      name
      f
      name
      r
      String
      l
      desc
      f
      description
      r
      String
      l
      cmt
      f
      comment
      r
      String
      l
      src
      f
      source
      r
      String
      l
      sym
      f
      symbol name
      r
      String
      l
      type
      f
      type
      r
      String
      l
      fix
      f
      fix
      r
      String
      l
      link
      f
      links
      r
      Link
    2. [141] If child's local name is extensions:
      1. [143] For each element gc in child's children:
        1. [144] Process gc with point, using the following table:
          l
          local name
          f
          Field
          r
          Rule
          l
          cadence
          f
          cadence
          r
          Number
          l
          distance
          f
          distance
          r
          Number
          l
          hr
          f
          heartrate
          r
          Number
          l
          heartrate
          f
          heartrate
          r
          Number
          l
          power
          f
          power
          r
          Number
          l
          temp
          f
          temperature
          r
          Number
          l
          speed
          f
          speed
          r
          Number
          l
          accuracy
          f
          accuracy
          r
          Number
        2. [145] If gc's local name is TrackPointExtension:
          1. [146] For each element ggc in gc's children:
            1. [147] Process ggc with point, using the following table:
              l
              local name
              f
              Field
              r
              Rule
              l
              atemp
              f
              temperature
              r
              Number
              l
              wtemp
              f
              water temperature
              r
              Number
              l
              depth
              f
              depth
              r
              Number
              l
              hr
              f
              heartrate
              r
              Number
              l
              cad
              f
              cadence
              r
              Number
  11. [161] Return point.

[52] To parse a route element element, run these steps:

  1. [56] Let route be a route.
  2. [57] For each element child in element's children:
    1. [58] Process child with route, using the following table:
      l
      local name
      f
      Field
      r
      Rule
      l
      name
      f
      name
      r
      String
      l
      desc
      f
      description
      r
      String
      l
      cmt
      f
      comment
      r
      String
      l
      src
      f
      source
      r
      String
      l
      type
      f
      type
      r
      String
      l
      number
      f
      number
      r
      Non-negative number
      l
      link
      f
      links
      r
      Link
    2. [60] If child's local name is rtept:
      1. [61] Append the result of parsing a point element child to route's points.
  3. [162] Return route.

[63] To parse a track element element, run these steps:

  1. [64] Let track be a track.
  2. [65] For each element child in element's children:
    1. [66] Process child with track, using the following table:
      l
      local name
      f
      Field
      r
      Rule
      l
      name
      f
      name
      r
      String
      l
      desc
      f
      description
      r
      String
      l
      cmt
      f
      comment
      r
      String
      l
      src
      f
      source
      r
      String
      l
      type
      f
      type
      r
      String
      l
      number
      f
      number
      r
      Non-negative number
      l
      link
      f
      links
      r
      Link
    2. [67] If child's local name is trkseg:
      1. [70] Let segment be a track segment.
      2. [76] For each element gc in child's children:
        1. [77] If gc's local name is trkpt:
          1. [80] Append the result of parsing a point element gc to segment's points.
      3. [75] Append segment to track's segments.
  3. [163] Return track.

[105] The rules for parsing a latitude value text are as given in the following algorithm:

  1. [106] Let number be the result of applying the rules for parsing floating-point number values to text.
  2. [107] If number is not a number, return null and abort these steps.
  3. [108] If number is greater than 90, or less than -90, return null and abort these steps.
  4. [109] Return number.

[110] The rules for parsing a longitude value text are as given in the following algorithm:

  1. [111] Let number be the result of applying the rules for parsing floating-point number values to text.
  2. [112] If number is not a number, return null and abort these steps.
  3. [113] If number is greater than 180, or less than -180, return null and abort these steps.
  4. [114] Return number.

[153] To process a value element element with object and table, run these steps:

  1. [156] Let row be a row in table, whose "local name" cell value is element's local name.
  2. [142] If row is null, abort these steps.
  3. [155] Let field be row's "Field" cell value.
  4. [164] If object's field's value is not null, abort these steps.
  5. [157] Let result be the result of switching by row's "Rule" cell value:
    String
    1. [149] Let text be element's child text content.
    2. [150] If text is not the empty string:
      1. [151] Return text.
    3. [148] Otherwise:
      1. [152] Return null.
    Non-negative number
    1. [135] Let text be element's child text content.
    2. [136] Let number be the result of applying the rules for parsing non-negative integers to text.
    3. [137] If number is a number:
      1. [138] Return number.
    4. [139] Otherwise:
      1. [140] Return null.
    Number
    1. [120] Let text be element's child text content.
    2. [121] Let number be the result of applying the rules for parsing floating-point number values to text.
    3. [122] If number is a number:
      1. [119] Return number.
    4. [128] Otherwise:
      1. [129] Return null.
    Degree
    1. [125] Let text be element's child text content.
    2. [126] Let number be the result of applying the rules for parsing floating-point number values to text.
    3. [127] If number is a number in the range [ 0, 360 ]:
      1. [124] Return number.
    4. [132] Otherwise:
      1. [133] Return null.
    Year
    1. [36] Let text be element's child text content.
    2. [37] If text is four or more ASCII digits:
      1. [38] Let year be the result of applying the rules for parsing non-negative integers to text.
      2. [41] If year is a positive integer:
        1. [39] Return year and abort these steps.
    3. [3] Return null.
    Time
    1. [16] Let text be element's child text content.
    2. [117] Parse a global date and time string text.
    3. [123] If a time is returned:
      1. [130] Return the time.
    4. [131] Otherwise:
      1. [134] Return null.
    URL Content
    1. [81] Let text be element's child text content.
    2. [82] If text is not the empty string, parse text relative to element's node document.
    3. [93] If parsed and not failed:
      1. [94] Return the resulting URL string.
    4. [95] Otherwise:
      1. [96] Return null.
    Link
    1. [190] Let href be element's href attribute value.
    2. [191] If href is not null, parse href relative to element's node document.
    3. [192] If parsed and not failed:
      1. [200] Let link be a new link.
      2. [201] Set link's URL to the resulting URL string.
      3. [203] For each element child in element's children:
        1. [204] Process child with link, using the following table:
          l
          local name
          f
          Field
          r
          Rule
          l
          text
          f
          text
          r
          String
          l
          type
          f
          MIME type
          r
          String
          l
          link
          f
          URL
          r
          URL
      4. [193] Return link.
    4. [194] Otherwise:
      1. [195] Return null.
    Person
    1. [42] Let person be a new person.
    2. [68] For each element child in element's children:
      1. [23] Process child with person, using the following table:
        l
        local name
        f
        Field
        r
        Rule
        l
        name
        f
        name
        r
        String
        l
        link
        f
        links
        r
        Link
      2. [69] If child's local name is email and person's email is null:
        1. [46] Let left be child's id attribute value.
        2. [47] Let right be child's domain attribute value.
        3. [48] If left and right are not null:
          1. [50] Let email be left followed by @ followed by right.
          2. [49] Set person's email to email.
    3. [44] Return person.
    License
    1. [55] Let license be a new license.
    2. [7] Let holder be element's author attribute value.
    3. [8] If holder is not null and is not the empty string:
      1. [54] Set license's holder to holder.
    4. [53] For each element child in element's children:
      1. [24] Process child with license, using the following table:
        l
        local name
        f
        Field
        r
        Rule
        l
        year
        f
        year
        r
        Year
        l
        license
        f
        URL
        r
        URL Content
    5. [28] Return license.
  6. [158] If result is not null:
    1. [196] If object's field field is a list:
      1. [199] Append result to object's field field's value.
    2. [197] Otherwise:
      1. [198] Set object's field field to result.

MIME types

[166] A GPX MIME types is any MIME type whose essence is one of the following:

[168] When an implementation uses a MIME type to identify GPX, it MUST use application/gpx+xml.

[169] When an implementation interprets a MIME type, it MUST recognize any GPX MIME type as equivalent to application/gpx+xml.

[170] Therefore, any charset parameter is interpreted as an XML MIME type charset parameter.

Namespaces

[173] The GPX namespace is http://www.topografix.com/GPX/1/1.

[174] The GPX 1.0 namespace is http://www.topografix.com/GPX/1/0. The GPX 1.0 namespace MUST NOT be used.

[171] The GPX extension namespace is data:,gpx.

[13] Most of the parsing steps intentionally ignore namespaces of elements.

Definitions of extensions

[172] The gpx element in the GPX namespace MAY have a tzoffset attribute in the GPX extension namespace. If specified, its value MUST be a valid time-zone offset string. It is the time-zone offset that is appropriate as the default time-zone offset for rendering timestamps in the element.


[214] The wpt element in the GPX namespace MAY have a pointrole attribute in the GPX extension namespace. If specified, its value MUST be a valid point role string. It is the kind of the point in the context of a race (or similar) event described by the document.

[215] A valid point role string is one of followings:

String Description
globalStartThe first start point of the race.
globalGoalThe last goal point of the race.
partialStartThe start point of one of the subsections of the entire route of the race (which is not categorized as globalStart).
partialGoalThe goal point of one of the subsections of the entire route of the race (which is not categorized as globalGoal).
checkpoint One of intermediate points during the route of the race which serves a remarkable role in the race, typically known as aid station, checkpoint, or gate.
observerA point that does not belong to any other kind.

[216] How to use these roles, including how points are associated with the routes in the same document, are application dependent.

[217] An application might impose additional context-specific constraints for GPX document it handles. For example, an application might require that the first point in the route has to be the same location with the point whose pointrole is globalStart.


[175] The trkpt element in the GPX namespace MAY have a road attribute in the GPX extension namespace. If specified, its value MUST be a valid road type string. It is the kind or condition of the road at the point of the element.

[176] A valid road type string is one of followings:

String Description
pA road paved by e.g. concrete or asphalt
dA dirt road
uA completely unpaved path

[35] The trkpt element in the GPX namespace MAY have a todistance attribute in the GPX extension namespace. If specified, its value MUST be a valid floating-point number that parses to a number greater than or equal to 0. It is the distance between this and the previous points (i.e. the points represented by this and the nearest previous sibling trkpt elements in the GPX namespace), in meters. If there is no previous point, the number MUST be equal to 0. If the distance is not known, the attribute MUST NOT be specified.

[209] To determine the distance between track points point1 and point2, run these steps:

  1. [210] Assert: point1 and point2 are both contained in the points of the same track segment and point2 immediately follows point1 in the points.
  2. [211] If point2's to distance is not null:
    1. [212] Return point2's to distance.
  3. [213] Return the distance between points (point1's latitide, point1's longitude) and (point2's latitide, point2's longitude), determined by an implementation-dependent algorithm.

References

[208] The term meter https://www.bipm.org/en/publications/si-brochure/metre.html is defined by the SI Brochure: The International System of Units (SI).

[165] This specification depends on the Infra Standard. The terms list, append, contains, for each, size, and is empty, are defined by the Infra Standard.

[167] The terms MIME type and essence are defined by the MIME Sniffing Standard.

[5] The terms previous sibling, element, attribute, value, Document, document element, node document, children, local name, and namespace are defined by the DOM Standard.

[34] The terms ASCII digits, rules for parsing non-negative integers, valid floating-point number, rules for parsing floating-point number values, parse a global date and time string, child text content, valid time-zone offset string, parse a time-zone offset string, parse a URL, resulting URL string, and XML parser, are defined by the HTML Standard.

[178] Elements in the GPX namespace and its attributes are defined by the GPX specification https://www.topografix.com/gpx.asp.

Data and tests

[177] There are JSON data files:

[348] Test data are available at: https://github.com/wakaba/tests-web/tree/master/gpx/parsing.

License

[347] Per CC0 https://creativecommons.org/publicdomain/zero/1.0/, to the extent possible under law, the author of this specification has waived all copyright and related or neighboring rights to this specification.

Notes

[349] There are implementations: https://manakai.github.io/pod/Web/GPX/Parser (Perl), https://github.com/wakaba/js-gpx-parser (JavaScript).