I bought the upgrade to the Apple’s iLife suite, released on Friday. Here’s a gotcha for developers who parse iPhoto’s AlbumData.xml file, though it doesn’t directly affect most users. It affects me, because my own code parses AlbumData.xml to generate my web-based photo albums (such as the England trip pictures I just posted).
Though the overall format of iPhoto’s XML file stays the same (and my script had no trouble reading it), the Comments and Date fields are gone! The Date field is renamed and in a different format, which is no problem to work around because the image file’s embedded EXIF data contains the date as well. The missing Comments field is a different story.
From my quick inspection, the comment data seems to be only stored in a newly introduced iPhoto.db file, which is in some binary format. The rationale for this is presumably performance, but that doesn’t completely make sense, since the photo title is still stored in the XML file and it may be changed just as often.
In any case, here’s a workaround that uses AppleScript to write a parallel folder structure holding just the comments, one per text file. Paste the following into a Script Editor window and run. Use this anytime you’d like to protect your comments from the vagaries of software or platform transitions or upgrades. (The parallel folder structure helps this; the script could have used iPhoto’s internal IDs and generated all the files in a single folder, but that wouldn’t have been as forward-compatible.) GPL-licensed.
commentCommonBaseDir = os.path.expanduser("~/Pictures/") commentOrigDir = os.path.join(commentCommonBaseDir, "iPhoto Library") commentParallelDir = os.path.join(commentCommonBaseDir, "iPhoto Library - My Comments Cache") commentFileSuffix = ".comment.txt" def getCommentForFile(imagePath): if not imagePath.lower().startswith(commentOrigDir.lower()): raise ('Error: image does not appear to be in iPhoto Library; ' + 'cannot compute comment path. Image: "%s". Library: "%s".' ) \ % (imagePath, commentOrigDir) commentPath = os.path.join(commentParallelDir, imagePath[len(commentOrigDir)+1:]) + commentFileSuffix if os.path.isfile(commentPath): print "Read comment for " + imagePath return open(commentPath, 'r').read() return ''