Swiftpack.co - Package - vincentneo/CoreGPX

Parse and generate GPX files easily on iOS, watchOS & macOS.

CI Status Swift Version GPX Version License Platform Version Carthage compatible Swift Package Manager compatible

What is CoreGPX?

CoreGPX is a port of iOS-GPX-Framework to Swift language.

CoreGPX currently supports all GPX tags listed in GPX v1.1 schema. It can generate and parse GPX v1.1 compliant files on iOS, macOS and watchOS.

As it makes use of XMLParser for parsing GPX files, CoreGPX is fully dependent on the Foundation API only.


  • ☑ Successfully outputs string that can be packaged into a GPX file
  • ☑ Parses GPX files using native XMLParser
  • ☑ Support for iOS, macOS & watchOS
  • (new) Supports Codable in essential classes
  • (new) Enhanced full support for GPXExtensions for both parsing and creating.
  • (new) Lossy GPX compression. Check out GPXCompressor for an implementation of this new feature.


CoreGPX is documented using jazzy.

Documentation Status

You can read the documentation here, which documents most of the important features that will be used for parsing and creating of GPX files.


CoreGPX supports CocoaPods, Carthage, as well as Swift Package Manager, such that you can install it, any way you want.

To install using CocoaPods, simply add the following line to your Podfile:

pod 'CoreGPX'

CoreGPX works with Carthage as well, simply add the following line to your Cartfile:

github "vincentneo/CoreGPX"

How to parse?

Parsing of GPX files is done by initializing GPXParser.

There are five ways of initializing GPXParser, and these are three main ways of initializing:

You can initialize with a URL:

guard let gpx = GPXParser(withURL: inputURL)?.parsedData() else { return }

With path:

guard let gpx = GPXParser(withPath: inputPath)?.parsedData() else { return } // String type

With Data:

let gpx = GPXParser(withData: inputData).parsedData()

.parsedData() returns a GPXRoot type, which contains all the metadata, waypoints, tracks, routes, and extensions(if any), which you can expect from a GPX file, depending on what that file contains.

Making use of parsed GPX data

guard let gpx = GPXParser(withURL: inputURL)?.parsedData() else { return // do things here when failed }
// waypoints, tracks, tracksegements, trackpoints are all stored as Array depends on the amount stored in the GPX file.
for waypoint in gpx.waypoints {  // for loop example, every waypoint is written
    print(waypoint.latitude)     // prints every waypoint's latitude, etc: 1.3521, as a Double object
    print(waypoint.longitude)    // prints every waypoint's latitude, etc: 103.8198, as a Double object
    print(waypoint.time)         // prints every waypoint's date, as a Date object
    print(waypoint.name)         // prints every waypoint's name, as a String
    print(gpx.metadata?.desc)    // prints description given in GPX file metadata tag
    print(gpx.metadata?.name)    // prints name given in GPX file metadata tag

How to create?

You will first start off with a GPXRoot.

Initializing GPXRoot

let root = GPXRoot(creator: "Your app name here!") // insert your app name here

Now, you can start adding things to your GPXRoot. This includes your metadata, waypoints, tracks, routes, as well as extensions(if any).

Adding waypoints to GPXRoot

root.add(waypoints: arrayOfWaypoints) // adds an array of waypoints
root.add(waypoint: singleWaypoint)    // adds a single waypoint

Adding tracks to GPXRoot

root.add(tracks: arrayOfTracks)       // adds an array of tracks
root.add(track: singleTrack)          // adds a single track

Adding routes to GPXRoot

root.add(routes: arrayOfRoutes)       // adds an array of routes
root.add(route: singleRoute)          // adds a single route

Adding metadata to GPXRoot

let metadata = GPXMetadata()
metadata.name = "Your Name Here"
metadata.desc = "Description of your GPX file"
root.metadata = metadata              // adds metadata stuff

Example of application of GPXRoot

let root = GPXRoot(creator: "Your app name here!")
var trackpoints = [GPXTrackPoint](https://raw.github.com/vincentneo/CoreGPX/blob/master/)

let yourLatitudeHere: CLLocationDegrees = 1.3521
let yourLongitudeHere: CLLocationDegrees = 103.8198
let yourElevationValue: Double = 10.724

let trackpoint = GPXTrackPoint(latitude: yourLatitudeHere, longitude: yourLongitudeHere)
trackpoint.elevation = yourElevationValue
trackpoint.time = Date() // set time to current date

let track = GPXTrack()                          // inits a track
let tracksegment = GPXTrackSegment()            // inits a tracksegment
tracksegment.add(trackpoints: trackpoints)      // adds an array of trackpoints to a track segment
track.add(trackSegment: tracksegment)           // adds a track segment to a track
root.add(track: track)                          // adds a track

print(root.gpx())				// prints the GPX formatted string

This would be what you get from root.gpx() in the above example:

<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="Your app name here!">
			<trkpt lat="1.352100" lon="103.819800">
  • .gpx() of GPXRoot outputs a String which can then be packaged as a .GPX file.
  • .OutputToFile(saveAt:fileName:) directly saves GPX contents to a URL specified.

Dealing with Extensions

Extensions in GPX files are represented as GPXExtensions in CoreGPX.

Accessing GPX Files's extensions

Once a GPX file is parsed, you can access the extensions, by using subscript, with the tag name.

  • Use extensions["tagNameHere"] to get a GPXExtensionElement, which will contain various data parsed. Alternatively, use get(from parent: String?) to get a dictionary of extension data parsed.

Writing GPX extensions

  • Firstly, initialize GPXRoot using init(withExtensionAttributes:, schemaLocation:) to initialize with extension schema information on the main gpx header tag.
  • Secondly, initialize GPXExtensions whenever needed, to be added to the GPXRoot/or other elements, when needed.
  • Use function append(at parent: String?, contents: [String : String]) to write extension data. If no parent, use nil.

To know more, please do read the documentation for GPXExtensions and GPXExtensionsElement.


To know in depth of what CoreGPX can bring, do check out the Example app. To run the example project, simply clone the repo, and try it out straight away!


Contributions to this project will be more than welcomed. Feel free to add a pull request or open an issue. If you require a feature that has yet to be available, do open an issue, describing why and what the feature could bring and how it would help you!

Like the project? Check out these too!

  • iOS-Open-GPX-Tracker, an awesome open-sourced GPS tracker for iOS and watchOS.
  • LocaleComplete, a small library to make Locale identifier hunting more easy and straightforward.


CoreGPX is available under the MIT license. See the LICENSE file for more info.


Stars: 65


Used By

Total: 0


The missing release... - 2020-05-06 13:54:23

This release holds a collection of fixes and enhancements from a wide period since late 2019. I was rather busy with other stuff and didn't collate it as a release. (Sorry @hsnetzer #75!)

  • Fix extension issues #71
  • Fix metadata issues #69
  • Fix route point parsing #73
  • Lossy compress GPX #56
  • Removal of 'Archived' file #59 (Applicable to SPM only)
  • use newer Xcode version for Travis CI

Special thanks to those involved, including @jearle1974, @Zakalicious, @lludo in notifying issues!

Fix parsing waypoint with link attributes - 2019-12-16 10:36:16

Fixes #67, where waypoint types with link attributes will still result in nil GPXLinks

Thanks @davetroy for noticing this issue!

Precision and bugs removal - 2019-11-14 13:39:54

This update brings slightly more value than the previous!

  • Waypoint types, including track point and route point is now encoded as double floating point precision (Double) instead of floating point precision (Float). This should result higher precision, more digits.
  • Fixes yet another GPXExtensions bug, #64, where extensions tagging will not be formatted correctly.
  • Remove older GPXExtensions unavailable methods totally.
  • Reduction of GPXElement's method, as it is repeated and redundant.

Special thanks for @andrijamilovanovic for notifying about issue #64! Contributions towards finding bugs such as those within the rather buggy GPXElement and its subclasses will make CoreGPX better! Thank you!

Minor Fixes - 2019-11-10 06:14:20

This release fixes an issue discussed in #58, where generation of gpx extensions element tags without a parent tag, would cause an unexpected parent tag to be generated, regardless.

Special thanks to @frogg for noticing a typo in the README example!

Swift Package Manager - 2019-10-26 15:25:41

This release removes obsolete files, for it to be compatible in with Swift Package Manager.

Special thanks to @lludo for notifying me about the issue!

Date formatting issue fixed - 2019-10-14 14:16:27

As reported in merlos/iOS-Open-GPX-Tracker issue #132, specific regions like Russia, may cause date creation in time attribute to not conform to ISO8601 standards.

This release fixes that, through forcing the DateFormatter to use Locale en_US_POSIX regardless of region.

Special thanks to @teran from reporting about this issue!

Revamp, Optimize, Extend. - 2019-09-11 12:31:18

This release is a more feature packed one... So what can be expected?

  • The GPX parser has been revamped. It should be more efficient, delivering marginal improvements.
  • Full Codable support across all GPX schema elements
  • Optional error handling support
  • Stable and optimised extensions
  • Access control changes
  • A GPXFix that makes sense
  • Fully documented

Special Thanks to @mrfeet for contributing towards the project's tests

Hope you will enjoy this release of CoreGPX! 🎉

Bug Removal - 2019-07-20 10:39:51

This update fixes an issue as there is a possibility that when parsing a GPX file with route extensions, it may crash.

Thanks @voynovia for noticing this behaviour, and correcting it through #44!

It's about time for Swift 5! - 2019-07-07 08:08:40

This update is a conversion to Swift 5 of the whole project.

As of conversion, there is zero code changes required, only project changes.

For those still using Swift 4.2, you may take a look at branch swift4.2. However, going forward, the Swift 4.2 branch will probably not be updated, and support will only be given for the latest swift version.

Some small changes... - 2019-07-06 14:34:46

This update includes the following:

  • Fix bug where GPXCopyright year may not parse correctly
  • Added a playground example, for possibly easier understanding of the library
  • Improvements to GPXEmail intended to simplify its use

That's about it! Thanks for your support!

Features Extended! - 2019-06-30 10:54:22

This update includes:

  • Basic Extensions parsing and creation (finally!) (Still lacks support for extensions in GPXRoot)
  • Merged date and year parsers to same class
  • Removal of certain unused components in library

Full extensions support should be coming soon. Probably in 0.7.0! Swift 5 support will be here very soon as well.

Bug Hunt - 2019-06-06 02:02:34

This release fixes the following:

  • GPXLink's type attribute not parsing correctly
  • GPXBounds & GPXCopyright failure to generate correct open tag

All open tags are now generated through an extension function for NSMutableString, which should fix all open tag issues, for all future releases.

Thanks to @INDAPP for spotting the issue!

Codable Support - 2019-05-12 14:05:54

Basic Codable support have been implemented for some classes, including:

  • GPXExtensions
  • GPXLink
  • GPXRoute
  • GPXWaypoint
  • GPXTrack
  • GPXTrackSegment
  • GPXTrackPoint
  • GPXWaypoint

Serialization for the following types should now be made easy!

Parser updates - 2019-03-26 06:44:33

Minor update. The parser will now parse the GPX file's version and creator as well.

Documentation Added! - 2019-03-24 07:47:34

This update contains the following:

  • #26 Add support for swift package manager installation
  • #29 Fully documented features in CoreGPX
  • Deprecate certain methods
  • Moved Date parsers out of GPXWaypoint for decluttering
  • Moved number converters out for decluttering
  • New way of initialising GPXLink
  • New way of initialising GPXEmail, for a more user friendly approach
  • Privatised most of GPXParser's internally used objects

GPXLink creation bug fix - 2019-02-27 04:22:55

This update includes:

  • a bug fix where href of GPXLink will produce null every time when generating a GPX file.

Special thanks to @jdleung for spotting and informing regards to this bug!

Another minor update! - 2019-02-20 13:36:20

While this update isn't all that big, it still includes these features:

  • Added Tests
  • Added a direct way of saving a GPX file from GPXRoot
  • Fixed missing Xcode example project in workspace
  • Removal of CGFloat related methods in GPXType (Apple Watch doesn't support CGFloat and the whole project uses Double now anyways)

Minor updates - 2019-02-15 14:08:57

Just some new init methods in GPXParser, and other minor changes including:

  • switching some init options to convenience inits
  • new init options
  • parser in GPXParser is now immutable

Parser enhancements - 2019-02-12 11:30:02

Minor updates, mostly focused on the GPXParser class.

#18 is now done, which is the main focus of this update.

  • bounds, author, copyright and email tags are now parsed by the parser.
  • new init method for GPXLink (with href:)

Major Update! - 2019-02-10 14:24:43

This update fixes bugs, as well as speed improvements to the GPX file parser.

This includes:

  • Speed improvement through optimisation in GPXParser.
  • Fixed bug where a file with more than one track segment will not work as expected.
  • Added support for macOS and watchOS.
  • Partial support of parsing metadata tag in GPX files.
  • When no extensions are defined, the extensions tag is no longer written, as it is meant to be empty.
  • Code cleanup

🎉Special Thanks to @lludo for cleaning up the code!

fixing 0.3.4 - 2019-01-23 10:05:57

Fixing a fix, as a fix is required.

Bug squash - 2019-01-23 10:04:54

  • Resolves issue #8, where track points don't work as expected. Thanks to @jdleung for pointing the issue out!

  • The example app is also updated, to include an example for creating the a GPX file formatted as a string according to info given on the UI. This example isn't the best available, but would remain like this for now.

  • GPXParser's performance is also improved and optimised. (Not good enough, more work needed)

Minor changes - 2019-01-13 13:04:02

  • Fixed a date parsing bug
  • Updated example app's text field
  • Removed redundant code

Updated Example - 2019-01-12 11:43:28

You can now parse a GPX file from a URL textfield using example app.

The output is then shown on a tableview.

Renamed to CoreGPX - 2019-01-12 07:41:54

Nothing much for this release. Just a name change.

Removal of TBXML - 2019-01-11 12:47:10

Total removal of TBXML dependency for parsing GPX files.

Full migration to native XML parser complete.

First initial release! - 2019-01-11 12:22:01

First stable version!

Currently works:

  • [x] Successfully outputs string that can be packaged into a GPX file
  • [x] Parses GPX files well using native XMLParser

More work will be done in near future. For now, TBXML is still included. Will be removed soon.