This perl script will convert a geocaching.com LOC file to a Garmin GPX file. Both files are XML, and writing this has renewed my hatred for XML as a bloated overcomplex format ill suited for 99% of the tasks put to it.
#!/usr/bin/perl
use strict;
use XML::Parser;
# initialize parser and read the file
my $parser = new XML::Parser( Style => 'Tree' );
my $tree = $parser->parsefile( shift @ARGV );
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime();
my $timeString = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ",$year+1900,$mon+1,$mday,$hour,$min,$sec);
print <<EOL;
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1"
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
creator="D???????????????" version="1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd">
<metadata>
<link href="http://dsss.be/">
<text>Tyler's loc2gpx</text>
</link>
<time>$timeString</time>
</metadata>
EOL
# god damn I hate XML
for (my $i=0; $i<@{$tree->[1]}; $i++) {
my $waypoint;
if ($tree->[1][$i] eq 'waypoint') {
$i++;
$waypoint = $tree->[1][$i];
} else {
next;
}
my $id = $waypoint->[4][0]{'id'};
my $name = $waypoint->[4][2];
my $lat = $waypoint->[8][0]{'lat'};
my $lon = $waypoint->[8][0]{'lon'};
my $link = $waypoint->[16][2];
print <<EOL;
<wpt lat="$lat" lon="$lon">
<name>($id) $name</name>
<sym>Geocache</sym>
</wpt>
EOL
}
print "</gpx>\n";