Dan Connolly's tinkering lab notebook

## hacking soccer schedules into hCalendar and into my sidekick

When I gave a microformats+GRDDL talk early this month, I listed my kid's soccer schedules on my wish list slide.

Those soccer schedules are now available. No matter how badly I need them in my sidekick calendar in order to coordinate other family activities, I couldn't bear the thought of manually keying them in. The bane of my existence is doing things that I know the computer could do for me.1998,2002

One of the schedules is in PDF. I toyed with a PDF to excel converter and with google's "view as HTML" cache feature but didn't get very far with those. But the other schedule is on a normal database-backed web site.

It took just 91 lines of XSLT to put hCalendar markup to the page. Each event was a row; I added a tbody element around each row so that I could use the row element as the class="description" element. I used an ASP recipie to figure out how to just add an attribute here and there and leave the rest alone. I didn't get the AM/PM XSLT code right the first time; silly, since I've written it before; I should have copied it, if not factored it out for reuse.

My PDA/cellphone is a t-mobile sidekick. There's a very nice XMLRPC interface to the data, but it went read-only and it's not supported, so I use a ClientForm screen-scraping hack to upload flight schedules and such to my PDA. hipAgent.py (in my palmagent project) gets its data thru a simple command-line interface or thru tab-separated text files. I had a set of eventlines.n3 rules for reducing RDF calendar data to tab-separated format, but its timezone support is quirky and it doesn't handle multi-line descriptions. So I bit the bullet and integrated cwm's RDF reader via the simple myStore API into hipAgent.py. I was simple enough:

        elif o in ("--importRDF",):            import uripath, os            from myStore import load # http://www.w3.org/2000/10/swap/            addr = uripath.join("file:" + os.getcwd() + "/", a)            kb = load(addr)            importTimedRDF(number, passwd, kb, icon...    from myStore import Namespace    RDF = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")    ICAL = Namespace('http://www.w3.org/2002/12/cal/icaltzd#')    for ev in kb.each(pred = RDF.type, obj = ICAL.Vevent):        titl = unicode(kb.the(subj = ev, pred = ICAL.summary)).encode("utf-8")        progress("== found event:", titl)        when = str(kb.the(subj = ev, pred = ICAL.dtstart))        dt = when[:10]        ti = when[11:16]                loc = kb.any(subj = ev, pred = ICAL.location)        if loc: loc = unicode(loc).encode("utf-8")        desc = kb.any(subj = ev, pred = ICAL.description)        if desc: desc = unicode(desc).encode("utf-8")                progress("a.addTimedEvent", dt, ti)        a.addTimedEvent(dt, ti,                        titl, desc,                        'minutes', 60, #@@hardcoded                        where=loc)

So I succesfully loaded son's soccer schedule into my sidekick PDA calendar:

1. GET the schedule
2. tidy it
3. add hCalendar markup (vevent, description, summary dtstart, location) using XSLT
4. convert to RDF/XML using a GRDDL transform for hCalendar, glean-hcal.xsl
5. load into sidekick using hipAgent.py

The folks running the DB-backed web site could add hCalendar markup with even less hassle then I did (though they might have to think a little bit to produce well-formed XHTML), at which point I could reduce the first 4 steps with GRDDL (either via remote service or by adding GRDDL support to hipAgent.py or to cwm's myStore.load() function).