package mlgpx
Install
dune-project
Dependency
Authors
Maintainers
Sources
md5=5342bb7e601273245a9fe263e5a08770
sha512=cd73b16e988b3ed3cc427a6c6c6d6c9c745adb1eb7efaae3c34e8d006e9c03d9f9d2616cd4118564bd9873903969d3e4053b585e79dbd3e3e7d0f541e2faac83
doc/mlgpx.core/Gpx/index.html
Module Gpx
Source
OCaml library for reading and writing GPX (GPS Exchange Format) files.
Overview
GPX (GPS Exchange Format) is an XML-based format for GPS data interchange, standardized by Topografix. This library provides a complete implementation of the GPX 1.1 specification with strong type safety and validation.
GPX files can contain three main types of GPS data:
- Waypoints: Individual points of interest with coordinates
- Routes: Ordered sequences of waypoints representing a planned path
- Tracks: Recorded GPS traces, typically from actual journeys
All coordinates in GPX use the WGS84 datum (World Geodetic System 1984), the same coordinate system used by GPS satellites. Coordinates are expressed as decimal degrees, with elevations in meters above mean sea level.
Quick Start Example
open Gpx
(* Create coordinates *)
let lat = Coordinate.latitude 37.7749 |> Result.get_ok in
let lon = Coordinate.longitude (-122.4194) |> Result.get_ok in
(* Create a waypoint *)
let waypoint = Waypoint.make lat lon
|> Waypoint.with_name "San Francisco"
|> Waypoint.with_description "Golden Gate Bridge area" in
(* Create GPX document *)
let gpx = make_gpx ~creator:"my-app"
|> Doc.add_waypoint waypoint in
(* Write to file or string *)
match write_string gpx with
| Ok xml -> print_endline xml
| Error e -> Printf.eprintf "Error: %s\n" (Error.to_string e)
This library provides a clean, modular interface for working with GPX files, with separate modules for each major component of the GPX specification.
Core Modules
The library is organized into focused modules, each handling a specific aspect of GPX data. Each module provides complete functionality for its domain with strong type safety and validation.
Main Document Type
A complete GPX document containing waypoints, routes, tracks, and metadata.
This is the main type representing a complete GPX file. GPX documents must have a creator string (identifying the creating application) and follow the GPX 1.1 specification format.
Error Handling
Comprehensive error type covering all possible GPX operation failures.
Errors can occur during:
- XML parsing (malformed XML, invalid structure)
- Coordinate validation (out of range values)
- Missing required GPX elements or attributes
- File I/O operations
GPX exception raised for unrecoverable errors.
Most functions return Result.t
for error handling, but this exception may be raised in exceptional circumstances.
Parsing Functions
Parse GPX data from various sources. All parsing functions support optional validation to check compliance with GPX specification constraints.
Parse GPX from XML input source.
Reads GPX data from an Xmlm.input
source, which can be created from files, strings, or other input sources using the Xmlm library.
Example:
let input = Xmlm.make_input (`String (0, gpx_xml_string)) in
match parse ~validate:true input with
| Ok gpx -> Printf.printf "Parsed %d waypoints\n" (List.length (Doc.waypoints gpx))
| Error e -> Printf.eprintf "Parse error: %s\n" (Error.to_string e)
Parse GPX from XML string.
Convenience function for parsing GPX data from a string. Equivalent to creating an Xmlm.input
from the string and calling parse
.
Example:
let gpx_xml = {|<?xml version="1.0"?>
<gpx version="1.1" creator="my-app">
<wpt lat="37.7749" lon="-122.4194">
<name>San Francisco</name>
</wpt>
</gpx>|} in
match parse_string ~validate:true gpx_xml with
| Ok gpx -> print_endline "Successfully parsed GPX"
| Error e -> Printf.eprintf "Error: %s\n" (Error.to_string e)
Writing Functions
Generate GPX XML from document structures. All writing functions support optional validation before output generation.
Write GPX to XML output destination.
Generates standard GPX 1.1 XML and writes it to an Xmlm.dest
destination. The output destination can target files, buffers, or other sinks.
Example:
let output = Buffer.create 1024 in
let dest = Xmlm.make_output (`Buffer output) in
match write ~validate:true dest gpx with
| Ok () -> Buffer.contents output
| Error e -> failwith (Error.to_string e)
Write GPX to XML string.
Convenience function that generates a complete GPX XML document as a string. The output includes XML declaration and proper namespace declarations.
Example:
match write_string ~validate:true gpx with
| Ok xml ->
print_endline "Generated GPX:";
print_endline xml
| Error e ->
Printf.eprintf "Failed to generate GPX: %s\n" (Error.to_string e)
Validation Functions
Comprehensive validation against GPX specification rules and best practices. Validation checks coordinate ranges, required elements, data consistency, and common issues that may cause problems for GPS applications.
type validation_issue = {
level : [ `Error | `Warning ];
(*
*)`Error
for specification violations,`Warning
for best practice issuesmessage : string;
(*Human-readable description of the issue
*)location : string option;
(*Optional location context (e.g., "waypoint 1", "track segment 2")
*)
}
A validation issue found during GPX document checking.
Issues are classified as either errors (specification violations that make the GPX invalid) or warnings (best practice violations or suspicious data).
type validation_result = {
issues : validation_issue list;
(*All validation issues found, both errors and warnings
*)is_valid : bool;
(*
*)true
if no errors found (warnings are allowed)
}
Complete validation result with all issues and validity status.
The is_valid
field indicates whether the document contains any errors. Documents with only warnings are considered valid.
Perform comprehensive validation of a GPX document.
Checks all aspects of the GPX document against the specification:
- Coordinate ranges (latitude -90 to +90, longitude -180 to +180)
- Required elements and attributes
- Data consistency (e.g., time ordering in tracks)
- Reasonable value ranges for GPS quality metrics
- Proper structure and nesting
Example:
let result = validate_gpx gpx in
if result.is_valid then
Printf.printf "Document is valid with %d warnings\n"
(List.length (List.filter (fun i -> i.level = `Warning) result.issues))
else begin
print_endline "Document has errors:";
List.iter (fun issue ->
if issue.level = `Error then
Printf.printf " ERROR: %s\n" (format_issue issue)
) result.issues
end
Quick validation check - returns true if document has no errors.
Equivalent to (validate_gpx gpx).is_valid
but potentially more efficient as it can stop at the first error found.
Get only validation errors (specification violations).
Returns only the issues marked as errors, filtering out warnings. If this list is empty, the document is valid according to the GPX specification.
Get only validation warnings (best practice violations).
Returns only the issues marked as warnings. These don't make the document invalid but may indicate potential problems or areas for improvement.
Format a validation issue for human-readable display.
Combines the issue message with location context if available.
Example output: "Error in waypoint 1: Latitude out of range (-95.0)"
Document Constructors and Utilities
Functions for creating GPX documents and basic document operations.
Create a new GPX document with the required creator field.
Every GPX document must identify its creating application through the creator
attribute. This is required by the GPX specification and helps identify the source of GPS data.
The created document:
- Uses GPX version 1.1 (the current standard)
- Contains no waypoints, routes, or tracks initially
- Has no metadata initially
- Can be extended using
Doc
module functions
Example:
let gpx = make_gpx ~creator:"MyTracker v2.1" in
let gpx = Doc.add_waypoint gpx some_waypoint in
let gpx = Doc.add_track gpx some_track in
(* gpx now contains waypoints and tracks *)
Create an empty GPX document with the required creator field.
Alias for make_gpx
provided for consistency with module naming patterns. Creates a document with no GPS data that can be populated using the Doc
module functions.
Example:
let gpx = empty ~creator:"GPS Logger" in
assert (List.length (Doc.waypoints gpx) = 0);
assert (List.length (Doc.tracks gpx) = 0);
assert (Doc.creator gpx = "GPS Logger");
Common Patterns and Best Practices
Reading GPX Files
The most common use case is reading existing GPX files:
(* From a file using platform-specific modules *)
match Gpx_unix.read "track.gpx" with
| Ok gpx -> process_gpx gpx
| Error e -> handle_error e
(* From a string *)
match parse_string ~validate:true gpx_content with
| Ok gpx -> process_gpx gpx
| Error e -> handle_error e
Creating GPX Files
To create new GPX files with waypoints:
(* Create coordinates *)
let lat = Coordinate.latitude 37.7749 |> Result.get_ok in
let lon = Coordinate.longitude (-122.4194) |> Result.get_ok in
(* Create waypoint *)
let waypoint = Waypoint.make lat lon
|> Waypoint.with_name "Golden Gate"
|> Waypoint.with_description "Famous San Francisco bridge" in
(* Create document *)
let gpx = make_gpx ~creator:"My App v1.0"
|> Doc.add_waypoint waypoint in
(* Write to file *)
match Gpx_unix.write "output.gpx" gpx with
| Ok () -> print_endline "File written successfully"
| Error e -> Printf.eprintf "Write error: %s\n" (Error.to_string e)
Working with Tracks
Tracks represent recorded GPS traces with timestamped points:
(* Create track points with timestamps *)
let points = List.map (fun (lat_f, lon_f, time) ->
let lat = Coordinate.latitude lat_f |> Result.get_ok in
let lon = Coordinate.longitude lon_f |> Result.get_ok in
Waypoint.make lat lon |> Waypoint.with_time (Some time)
) gps_data in
(* Create track segment *)
let segment = Track.Segment.make points in
(* Create track *)
let track = Track.make ~name:"Morning Run"
|> Track.add_segment segment in
(* Add to document *)
let gpx = make_gpx ~creator:"Fitness App"
|> Doc.add_track track
Coordinate Systems and Units
- All coordinates use WGS84 datum (World Geodetic System 1984)
- Latitude ranges from -90.0 (South Pole) to +90.0 (North Pole)
- Longitude ranges from -180.0 to +180.0 degrees
- Elevations are in meters above mean sea level
- Times use RFC 3339 format (ISO 8601 subset)
Validation Recommendations
- Always validate when parsing untrusted GPX data
- Validate before writing to catch data consistency issues
- Handle both errors and warnings appropriately
- Use
is_valid
for quick checks,validate_gpx
for detailed analysis
Performance Considerations
- The library uses streaming XML parsing for memory efficiency
- Large GPX files with many track points are handled efficiently
- Coordinate validation occurs at construction time
- Consider using platform-specific modules (
Gpx_unix
,Gpx_eio
) for file I/O
Extension Support
The library supports GPX extensions for custom data:
(* Create extension *)
let ext = Extension.make_text
~name:"temperature"
~namespace:"http://example.com/weather"
"25.5" in
(* Add to waypoint *)
let waypoint = Waypoint.make lat lon
|> Waypoint.add_extensions [ext]
Related Modules and Libraries
This core module provides the foundation. For complete applications, consider:
Gpx_unix
: File I/O operations using standard Unix librariesGpx_eio
: Concurrent file I/O using the Eio effects library- Xmlm: Underlying XML processing library
- Ptime: Time representation used for timestamps