Efficiently Processing GPX Files in Go

Use gpxreader to process a GPX file of any size without reading the whole thing into memory. This also avoids Go’s issue where the Decoder can decode one node at a time, but, when you do that, it implicitly ignores all child nodes (because it seeks to the matching close tag for validation without any ability to disable this behavior).

An excerpt of the test-script from the project:

//...

func (gv *gpxVisitor) GpxOpen(gpx *gpxreader.Gpx) error {
    fmt.Printf("GPX: %s\n", gpx)

    return nil
}

func (gv *gpxVisitor) GpxClose(gpx *gpxreader.Gpx) error {
    return nil
}

func (gv *gpxVisitor) TrackOpen(track *gpxreader.Track) error {
    fmt.Printf("Track: %s\n", track)

    return nil
}

func (gv *gpxVisitor) TrackClose(track *gpxreader.Track) error {
    return nil
}

func (gv *gpxVisitor) TrackSegmentOpen(trackSegment *gpxreader.TrackSegment) error {
    fmt.Printf("Track segment: %s\n", trackSegment)

    return nil
}

func (gv *gpxVisitor) TrackSegmentClose(trackSegment *gpxreader.TrackSegment) error {
    return nil
}

func (gv *gpxVisitor) TrackPointOpen(trackPoint *gpxreader.TrackPoint) error {
    return nil
}

func (gv *gpxVisitor) TrackPointClose(trackPoint *gpxreader.TrackPoint) error {
    fmt.Printf("Point: %s\n", trackPoint)

    return nil
}

//...

func main() {
    var gpxFilepath string

    o := readOptions()

    gpxFilepath = o.GpxFilepath

    f, err := os.Open(gpxFilepath)
    if err != nil {
        panic(err)
    }

    defer f.Close()

    gv := newGpxVisitor()
    gp := gpxreader.NewGpxParser(f, gv)

    err = gp.Parse()
    if err != nil {
        print("Error: %s\n", err.Error())
        os.Exit(1)
    }
}

Output:

$ gpxreadertest -f 20140909.gpx 
GPX: GPX<C=[GPSLogger - http://gpslogger.mendhak.com/]>
Track: Track<>
Track segment: TrackSegment<>
Point: TrackPoint<LAT=(26.47886514) LON=(-80.08643986) ELV=(-12.000000) CRS=(197.899994) SPD=(35.250000) HDOP=(0.900000) SRC=[gps] SAT=(21) TIME=[2014-09-09 19:07:27 +0000 UTC]>
Point: TrackPoint<LAT=(26.40728154) LON=(-80.11801469) ELV=(9.000000) CRS=(0.000000) SPD=(0.000000) HDOP=(1.200000) SRC=[gps] SAT=(16) TIME=[2014-09-09 22:07:52 +0000 UTC]>
Point: TrackPoint<LAT=(26.54074478) LON=(-80.07230151) ELV=(-31.000000) CRS=(12.800000) SPD=(31.503967) HDOP=(1.000000) SRC=[gps] SAT=(17) TIME=[2014-09-09 22:53:27 +0000 UTC]>
Advertisements