Importing data into AddressBook

Volume 11, Issue 11; 21 Jan 2008; last modified 08 Oct 2010

XML to XML to vCard for Mac AddressBook.

Mac applications that work with people expect those people to be in your AddressBook. I've got a solution for syncing contacts with my phone, but that solution doesn't include support for AddressBook. Yesterday, I decided to fix that.

My ambitions don't extend to writing a full, round-trip syncing solution. Like the iCal data that I generate from the appointments in my phone, I'm perfectly content if the Mac application has “read only” access to the data.

What I needed to do was generate vCard data. Of course, not any vCard data, but the specific vCard data that AddressBook expects. A little more flexibility and a little less extensibility might have been good for that spec.

So I reverse engineered the particular flavor of vCard that AddressBook expects. Rather than trying to go directly from my data to that format, I crafted an intermediate XML vocabulary for the cards and a stylesheet to generate vCards from that.

Then I wrote the stylesheet that transforms my actual data (as expressed in RDF, so that I can take advantage of any inferred properties) to the vCard schema.

And it works. Sweet.

A few notes:

  1. It is apparently a known bug that AddressBook ignores category information. I want to be able to select all the imported records so that I can delete them when I want to import new ones. To facilitate this, I added a “hiptop-id” attribute to the vcard element. If you use it, then the stylesheet will generate a “Hiptop” URL for each card. The URL is useless, but the word “Hiptop” lets me use an AddressBook smart group to collect all the relevant vCards together.

  2. If you generate a .vcf file with Unix line ends, AddressBook botches the encoding. Make sure you generate “PC” line ends.

  3. It's impractical to generate base64 encoded photographs directly in XSLT. The vCard schema I constructed identifies photographs instead by URI. This is written to the .vcf file in what's presumably invalid vCard. I post-process the file with a Perl script that gets the URIs and base64 encodes them.

Share and enjoy.