A minimalist, ANSI compliant C library to parse the content of GPX files.
Background | Installation | API | Example Usage | License
This C library is designed to parse GPX flavour XML files produced by GPS devices for basic data. Its API is inspired by the minimalist C library philosophy of Christopher Wellons. For more detail on that philosophy, see here.
The header declares extern "C"
, so should also be usable in C++ code.
Copy libgpx.h
and libgpx.c
into your include path. Then add
#include <gpx_reader.h>
to your source code and link libgpx.c
to your compile step, e.g.
gcc .\src\application.c .\src\libgpx.c -I.\src\
The -ansi
flag can be added if compiling with GCC as the code is ANSI compliant.
libxml2
is required, and required to be on the include path such the following include statements are recognised:
#include <libxml/tree.h>
#include <libxml/parser.h>
When compiling, libxml2
will need to be linked, e.g.
gcc .\src.sample.c .\src\libgpx.c -I.\src\ -I\lib\libxml\include\ -L\lib\libxml\bin\ -lxml2
Internally, libgpx
has no further dependencies - it does not even include <stdlib.h>
.
- Value: 0
- Used to denote a collection of points in a element
- Value: 1
- Used to denote a collection of track segments grouped in a element
- Value: 2
- Used to denote a collection of points in a element
- Value: 65
- Used to allocate memory to character arrays storing strings from the XML file
This is the base type, pulling together all the GPX sub-types
- collections
libgpx_GPXPointCollection
* - A pointer to an array oflibgpx_GPXPointCollection
s, used to group the<trk></trk>
,<trkseg><trkseg>
and<rte></rte>
elements of a GPX file - links
libgpx_GPXLink
* - A pointer to an array oflibgpx_GPXLink
s, used to group any links found in a GPX file and connect them with their parent element - metadata
libgpx_GPXMetadata
- Contains detailed metadata about the GPX file - n_GPXLink s]ize_t - The length of the array
links
points to - n_GPXPoint size_t - length of the array
points
points to - n_GPXPointCollection size_t - The length of the array
collections
- points
libgpx_GPXPoint
* - A pointer to an array oflib_GPXPoint
s, used to group together the contents of the<rtept></rtept>
,<trkpt></trkpt>
and<wpt></wpt>
elements of the GPX file
Contains information about the author of the GPX file for libgpx_GPXMetadata
types
- email
libgpx_GPXEmail
- A contact e-mail address for the GPX author - name[
LIBGPX__XML_STRING_ALLOCATED_LENGTH
] - The name of the author of the GPX file
Contains copyright information about the GPX file for libgpx_GPXMetadata
types
Contains e-mail contact information for the author of the GPX file for [libgpx_GPXAuthor
] types
Contains information related to external links from the GPX file.
- href[
LIBGPX__XML_STRING_ALLOCATED_LENGTH
] char - The URI the link points to - member_of int - Indicates the ID of the node (
libgpx_GPXAuthor
,libgpx_GPXMetadata
,libgpx_GPXPoint
orlibgpx_GPXPointCollection
). If the node islibgpx_GPXAuthor
the ID is -2, if the node islibgpx_GPXMetadata
the value is -1, otherwise the node ID reflects the value in the lists oflibgpx_GPXPoint
orlibgpx_GPXPointCollection
held inlibgpx_GPX
- text[
LIBGPX__XML_STRING_ALLOCATED_LENGTH
] char - type[
LIBGPX__XML_STRING_ALLOCATED_LENGTH
] char
Contains detailed metadata about the GPX file. libgpx_GPXAuthor
and libgpx_Copyright
types are nested in this type.
Contains information about the latitude, longitude and elevation points in a GPX file, and how fixes were obtained. These points may be tracks or planned routes or waypoints.
Contains informtion grouping instances of libgpx_GPXPoint
into routes, tracks or track segments.
- collection_type:2 unsigned int - One of LIBGPX__COLLECTION_TYPE_RTE, LIBGPX__COLLECTION_TYPE_TRK or LIBGPX__COLLECTION_TYPE_TRKSEG
- id size_t - A sequential id shared across
libgpx_GPXPoint
andlibgpx_GPXPointCollection
- member_of int - Allows nesting of
libgpx_GPXPointCollection
s, for example track segments inside tracks. Points toid
of anotherlibgpx_GPXPointCollection
or is -1 if thelibgpx_GPXPointCollection
is a child of the root<gpx></gpx>
element - name[
LIBGPX__XML_STRING_ALLOCATED_LENGTH
] char - - type[
LIBGPX__XML_STRING_ALLOCATED_LENGTH
] char -
- Inputs
- gpx char *
- *sgpx libgpx_GPX *
- Returns
- An
int
, 1 on success, -1 on failure
- An
Parses a GPX file from a charcter array into a libgpx_GPX structure.
- Inputs
- gpx unsigned char *
- sgpx libgpx_GPX *
There are a couple of variables to initialise at the start of the code (These example use malloc from <stdlib.h>
, but this can be easily substituted in applications which are not linked against the standard library).:
libgpx_GPX *gpx = malloc(sizeof(libgpx_GPX));
if(gpx != NULL){
libgpx_GPXTypeCounts *ngpx = malloc(sizeof(libgpx_GPXTypeCounts));
/** Drop-in following example code here */
}
Once the XML document loaded to a char array pointer (in the example below, named buffer
), then the first step is to count the number of point collections, points and links in the XML file:
char *buffer = 0; /** wchar_t is a better option for some XML files */
/** Read your GPX data as XML into buffer here and then... */
int status_ngpx = libgpx_count_gpx_types(buffer, ngpx);
libgpx_count_gpx_types
will return a negative integer if it encountered an error, so that can be checked as the code progresses to allocating the arrays to store the various GPX data types.
if(status_ngpx > 0){
/** Allocate memory to the storage arrays*/
libgpx_GPXPoint *points = malloc(sizeof(libgpx_GPXPoint) * ngpx->n_points);
if(points != NULL){
libgpx_GPXLink *links = malloc(sizeof(libgpx_GPXLink) * ngpx->n_links);
if(links != NULL){
libgpx_GPXPointCollection *collections = malloc(sizeof(libgpx_GPXPointCollection) * ngpx->n_point_collections);
/** Move on to parsing the XML here */
}
}
}
The XML can then be parse with this command:
libgpx_parse_gpx((unsigned char*)buffer, gpx);
Putting it all together...
#include <libgpx.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
wchar_t *buffer = 0;
long len;
libgpx_GPX *gpx = malloc(sizeof(libgpx_GPX));
if(gpx){
/** Read the file contenst to `buffer` here */
if (buffer){
int gpx_type_count_status = libgpx_count_gpx_types((char *)buffer, gpx);
if(gpx_type_count_status > 0){
libgpx_GPXPoint *points = malloc(sizeof(libgpx_GPXPoint) * gpx->n_GPXPoint);
if(points){
libgpx_GPXLink *links = malloc(sizeof(libgpx_GPXLink) * gpx->n_GPXLink);
if(links){
libgpx_GPXPointCollection *collections = malloc(sizeof(libgpx_GPXPointCollection) * gpx->n_GPXPointCollection);
if(collections){
gpx->points = points;
gpx->collections = collections;
gpx->links = links;
libgpx_parse_gpx((unsigned char*)buffer, gpx);
}
}
}
}
}
return 0;
}
This software is "licensed" with the Unlicense. As such, this is free and unencumbered software released into the public domain.