Repository navigation
Fixed
- Parsing a track or route no longer takes quadratic time. Each closing
<trkpt>/<rtept>copied every point parsed so far, so a 20,000-point recording took seconds and an 80,000-point one took minutes; parse time is now linear in file size. - On Linux,
parse(_:)andparse(contentsOf:)no longer reject documents larger than 10 MB withGPXError.malformedXML. - Elements inside
<extensions>whose names match GPX structure (metadata,wpt,trk,link, …) no longer overwrite the document's own metadata or add phantom waypoints, tracks, and links. They are kept as custom extension data like any other element. - Structural elements are now only recognised under the parent the GPX schema gives them. An attribute-only
<email>or<bounds>inside an unknown wrapper no longer closes that wrapper early (leaking the wrapper's later children into its parent), and containers nested in unknown wrappers are ignored along with the wrapper. - Unknown children of a Garmin
TrackPointExtensionwrapper are no longer dropped — they land inGPXExtensions.customlike other unrecognised extension elements. - Integer extension and waypoint values written as decimals (
<hr>72.0</hr>,<sat>7.0</sat>) now parse instead of becomingnil. A known extension element whose text isn't a usable number is preserved incustomrather than discarded. - Childless custom extension elements (
<app:flag/>) are preserved with an empty value, soGPXCustomExtensionvalues with an emptyvaluenow round-trip. NaN/infare no longer accepted as numbers: inlat/lonthey raiseGPXError.invalidCoordinate, and in optional values (<ele>NaN</ele>,<bounds>) they becomenil. Previously they parsed into documents the serializer then refused to write.- An
<extensions>block that carries no data now parses asnilrather than an emptyGPXExtensions, matching what the serializer emits for it. - An XML document whose root element is not
<gpx>now raisesGPXError.malformedXMLinstead of parsing "successfully" into an empty document. - The serializer no longer emits malformed XML for text containing characters XML 1.0 cannot represent (most control characters) — they are dropped. Carriage returns, and tabs/newlines in attribute values, are written as character references so they survive a round trip instead of being normalized away by the reader.
GPXDocument.namespacesentries that would make the root element malformed — a prefix the serializer already declares (xsi, orgpxtpxwhen Garmin fields are present), a prefix that isn't a valid XML name, or an empty URI — are skipped instead of written.- Custom extension names containing characters an XML element name cannot hold are written with those characters replaced by
_instead of producing malformed XML. - Garmin
TrackPointExtensionchildren are now written in the order the Garmin schema requires (atemp,wtemp,depth,hr,cad,speed,course,bearing). validate()now reports non-finite values in route-, track-, and segment-level extensions, which the serializer already rejected.simplified(tolerance:)no longer keeps every point of a straight line that crosses the antimeridian.- Numbers that round to zero at 7 decimal places are written as
0, not-0.
Full changelog: CHANGELOG.md