#!/usr/bin/python # # mkgcm -- make small geocache html files for a big GPX download. # # usage: mkgcm -i index.html -it "Monterey, CA" -o outdir monterey.gpx # # Copyright (c) 2007 Brian "Beej Jorgensen" Hall # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # import sys import os import os.path import xml.dom.minidom import re class Cache(object): def __init__(self): self.lat = None self.lon = None self.id = None self.desc = None self.url = None self.type = None self.name = None self.owner = None self.container = None self.difficulty = None self.terrain = None self.shortdesc = None self.longdesc = None self.available = True self.archived = False self.hints = None self.logs = [] self.travelbugs = [] class AppInfo(object): def __init__(self): self.outdirname = "." self.infilename = None self.indexfilename = None self.indextitle = None self.dom = None def usageExit(): sys.stderr.write("usage: mkgcm [-i indexfile] [-it indextitle] [-o outdir] infile\n") sys.exit(1) def parseCommandLine(argv): argv.pop(0) ai = AppInfo() while len(argv) > 0: if argv[0] == "-?" or argv[0] == "-h" or argv[0] == "--help": usageExit() elif argv[0] == "-o": if len(argv) == 1: usageExit() argv.pop(0) ai.outdirname = argv[0] elif argv[0] == "-i": if len(argv) == 1: usageExit() argv.pop(0) ai.indexfilename = argv[0] elif argv[0] == "-it": if len(argv) == 1: usageExit() argv.pop(0) ai.indextitle = argv[0] elif ai.infilename == None: ai.infilename = argv[0] else: usageExit() argv.pop(0) if ai.infilename == None: usageExit() if ai.indextitle == None: ai.indextitle = ai.infilename return ai def textUnder(node): text = "" for n in node.childNodes: if n.nodeType == n.TEXT_NODE: text = text + n.data return text def buildCacheList(dom): dom = dom.firstChild # cacheList = [] for wpt in dom.getElementsByTagName("wpt"): # all elements cache = Cache() cache.lat = wpt.getAttribute("lat") cache.lon = wpt.getAttribute("lon") cache.id = textUnder(wpt.getElementsByTagName("name")[0]) cache.url = textUnder(wpt.getElementsByTagName("url")[0]) gs = wpt.getElementsByTagName("groundspeak:cache")[0] cache.available = (gs.getAttribute("available") == "True") cache.archived = (gs.getAttribute("archived") == "True") cache.container = textUnder(gs.getElementsByTagName("groundspeak:container")[0]) cache.owner = textUnder(gs.getElementsByTagName("groundspeak:owner")[0]) cache.name = textUnder(gs.getElementsByTagName("groundspeak:name")[0]) cache.type = textUnder(gs.getElementsByTagName("groundspeak:type")[0]) cache.difficulty = textUnder(gs.getElementsByTagName("groundspeak:difficulty")[0]) cache.terrain = textUnder(gs.getElementsByTagName("groundspeak:terrain")[0]) cache.shortdesc = textUnder(gs.getElementsByTagName("groundspeak:short_description")[0]) cache.longdesc = textUnder(gs.getElementsByTagName("groundspeak:long_description")[0]) cache.hints = textUnder(gs.getElementsByTagName("groundspeak:encoded_hints")[0]).strip() logparent = gs.getElementsByTagName("groundspeak:logs")[0] for l in logparent.getElementsByTagName("groundspeak:log"): date = textUnder(l.getElementsByTagName("groundspeak:date")[0]) date = date.split("T")[0] type = textUnder(l.getElementsByTagName("groundspeak:type")[0]) finder = textUnder(l.getElementsByTagName("groundspeak:finder")[0]) cache.logs.append("%s: %s (%s)" % (date, type, finder)) tbparent = gs.getElementsByTagName("groundspeak:travelbugs")[0] for b in tbparent.getElementsByTagName("groundspeak:travelbug"): ref = b.getAttribute("ref") name = textUnder(b.getElementsByTagName("groundspeak:name")[0]) cache.travelbugs.append("%s (%s)" % (name, ref)) cacheList.append(cache) return cacheList def ll2hm(llstr, isLat): llfloat = float(llstr) if llfloat < 0: llfloat = -llfloat if isLat: dir = "S" else: dir = "W" else: if isLat: dir = "N" else: dir = "E" lldeg = int(llfloat) llmin = (llfloat - lldeg) * 60 return "%s %d° %.3f'" % (dir, lldeg, llmin) def writeFiles(cacheList): for c in cacheList: fp = file("%s.html" % c.id, "w") fp.write("\n\n") fp.write("%s\n" % c.id) fp.write("\n\n\n") fp.write("%s\n" % c.name.encode("ascii", "replace")) fp.write("
Lat: %.5f, Lon: %.5f\n" % (float(c.lat), float(c.lon))) fp.write("
Lat: %s, Lon: %s\n" % (ll2hm(c.lat, True), ll2hm(c.lon, False))) fp.write("

Type: %s\n" % c.type) fp.write("
Container: %s\n" % c.container) fp.write("
Difficulty: %s/5\n" % c.difficulty) fp.write("
Terrain: %s/5\n" % c.terrain) fp.write("
Owner: %s\n" % c.owner.encode('ascii', 'replace')) fp.write("
ID: %s\n" % (c.url, c.id)) if not c.available: fp.write("

WARNING! Cache marked as Unavailable!\n") if c.archived: fp.write("

WARNING! Cache marked as Archived!\n") if c.travelbugs != []: fp.write("

Travelbugs:\n

") fp.write("

\n") fp.write("

Description:\n") fp.write("

%s\n

%s\n" % (c.shortdesc.encode('ascii', 'replace'), c.longdesc.encode('ascii', 'replace'))) fp.write("

Hints:\n") if c.hints == "": fp.write("

None :-(
\n") else: c.hints = re.sub("\n", "\n
", c.hints) fp.write("

%s\n" % c.hints.encode("ascii", "replace")) fp.write("

Last Logs:\n

") if c.logs == []: fp.write("None!
\n") else: count = 0 for l in c.logs: fp.write("%s
\n" % l) count = count + 1 if count > 5: break fp.write("


\n\n\n") fp.close() def writeIndexFiles(ai, cacheList): fp = file(ai.indexfilename, "w") fp.write("\n\n") fp.write("%s\n" % ai.indextitle) fp.write("\n\n\n") fp.write("

%s

\n" % ai.indextitle) fp.write("\n
\n\n\n") fp.close() def main(argv): ai = parseCommandLine(argv) sys.stderr.write("reading XML...\n") ai.dom = xml.dom.minidom.parse(ai.infilename) sys.stderr.write("building cache list...\n") cacheList = buildCacheList(ai.dom) sys.stderr.write("writing cache files...\n") if not os.path.exists(ai.outdirname): os.makedirs(ai.outdirname) os.chdir(ai.outdirname) writeFiles(cacheList) if ai.indexfilename != None: sys.stderr.write("writing index file...\n") writeIndexFiles(ai, cacheList) return 0 if __name__ == "__main__": sys.exit(main(sys.argv))