A swiss public transit API (SBB and Google..)
Here we go.. After weeks of going back and forth between a crappy API (sbb.ch) with exact schedule and a nice API with wrong schedule (google.com), I finally merged them into one.
What are the capabilities of this API? Let’s make an example.
Given you entered from = “Feldstrasse 133, Zürich” and to = “Bern”.
- It then checks sbb.ch first – No hit.
- Then it checks google.com, which will return you a schedule with the next transit station from the address “feldstrasse+133, Zürich”
Ok, this is not a big deal.
In GottaGo, we often use (or almost everytime) the coordinates of a station. Let’s make another example.
Query: from=Triemli[8.495521,47.368052,0] and to=”Feldstrasse 133″.
The coordinates are then reverse geocoded, so that we get a city name.. Which is “Zürich” in this case.
- The API will first check sbb.ch for “Zürich, Triemli” to “Feldstrasse 133″, which will be no hit.
- It then checks sbb.ch for “Zürich, Triemli” to “Zürich, Feldstrasse 133″.
Note that the city is also added to the other parameter since we had no hit in the first place and the city name did not yet occur in the second parameter “Feldstrasse 133″. But no hit again..
- Then it checks google.com for “Zürich, Triemli” to “Feldstrasse 133″, which will be no hit, since there are a few more “Feldstrasse”s around in Switzerland.
- Ok, now the last resort: Check google with “Zürich, Triemli” to “Zürich, Feldstrasse 133″ – Ahhh, finally a hit :)
Why all this? Because of POI and address-book search.
SBB.ch doesn’t really provide a proper API for using POIs and addresses. And google doesn’t provide the comfort of saying “Fribourg” is the Mainstation of “Fribourg” and not the center of Fribourg, and the schedule is sometimes wrong, especially during holidays.
This results in a comfortable API which we can use to make also very simples queries like: from “Current Location” to “Liip” in `GottaGo’.
The URL to this API? http://couch.codesofa.com/api/transit.xml?from=station[longitude,latitude,0]; station2[longitude,latitude,0]&to=station3; station4[longitude,latitude,0]
(The coordinates are optional, and you can enter as many stations as you like, separated by “;”)
Eg: couch.codesofa.com/api/transit.xml?from=Triemli[8.495521,47.368052,0]&to=Bern
Btw.: Latest Beta of `GottaGo’ is out. (An iPhone app for swiss public transit). If you want a preview, see: http://liip.to/applyforbeta
Sunshine follows rain – GottaGo in the wild
Well.. it took me a while to get here.. And here we are now.
GottaGo is done. (Well, as far as software can be done..) I’m very happy to tell, that GottaGo is ATM. out in the wild for testing and has already been submitted to the AppStore.
Here are some high quality pictures of GottaGo in action:






Well, what has happened so far?
The main problem was the absence of NSXMLDocument/Element. When I started the project, I chose NSXMLDocument over NSXMLParser (SAX) because it’s way easier to handle difficult documents.
Because the app gets its data from Google and SBB over their respective APIs, a flexible XML parser was needed. Especially for SBB. If you’ve ever dealt with the SBB page, you know what I’m talking about.
To my bad, NSXMLDocument was not going to be included in the final SDK – what now?
In the last blog post I mentioned my options. Alea iacta est ;)
First I tried to make it work without a proxy – using IconoraXML but this project was kinda unmaintained and even failed to build. My other approach, to write a wrapper for libxml2 was kinda overdosed.
So I had to rewrite the complete Google and SBB parsing stuff because I screwed up in the first place – this time using NSXMLParser.
What is NSXMLParser – you might ask. It’s actually a SAX parser for Objective-C, which means you look at 1 element at a time. There is no DOM tree or whatsoever. That is a problem if you have hierarchical data – obviously. Let’s say you have 3 train-connections, each with sections.. now how’d you know what section is in which connection if you don’t know about the parent node? I guess you get the point.
If you are really interested, grab the SeismicXML example for the SDK to see how it works in detail. Basically, you just work your way through that Document recursively and always add the stuff you `find’ to your current parent-object. Once you get it, it’s easy to follow..
Sounds like an easy deal, eh? Well, that might be true for the Google data. It was, and that’s what I did.
But SBB? No go. The loader wouldn’t even let me load the html. So what now? – Yes, a proxy was needed – and that’s what was next.
On http://couch.codesofa.com/api/sbb/from/Source1[;Source2 ..]/to/Destination1[;Destination2 ..].xml you see the result (Example). I think this is the first real API available to everyone for SBB.ch .
This was made using the Okapi-Framework with a lot of XPath magic :)
In the next days, I will release the source-code for it, together with an introduction into Okapi since it’s the most basic project I can think of – I just need to polish the code a bit..
So now it was quite easy to parse the SBB data..
Lessons learned? Well, there’s nothing more adorable than a good webservice ;)
What’s next? Favorites and Address book stuff.. But first are some other apps I wanted to get my hands on. (Top secret!)