Fat Cat Software

Gathering data with PlistEdit Pro and Applescript

All sorts of information is stored in property lists these days. It's a simple but flexible format, used for simple stuff like application info and preferences to being the basis for some apps entire file formats. Browsing through property lists is fine and all, but there are some times when you need something with a little more oomph to sensibly look at the data you're looking for. Some simple but well placed Applescript code in conjunction with PlistEdit Pro can yield some very useful results.For example, in my various iPhoto related development, I'm often found in far too close contact with the AlbumData.xml file that iPhoto writes out, which is really just an XML property list. This file stores information on all the photos, albums, and rolls that exist in the iPhoto library. I recently found myself needing to look through the ID numbers of all the albums in a library, looking for duplicates. After about 30 seconds of twiddling down triangles and scrolling, I realized I needed a better way to get at this data.Enter ApplescriptOK, so you can write an Applescript that will iterate down into all those plists and compile the data for you. It would probably look something like this:tell application "PlistEdit Pro"set albumIDList to {}repeat with albumPlist in plists of plist "List of Albums" of plist of document "AlbumData.xml"set albumIDList to albumIDList & value of plist "AlbumId" of albumPlistend repeatreturn albumIDListend tellWell, that works OK, but with judicious use of Applescript's test clauses, getting a list of the album IDs could be done in a single statement:tell application "PlistEdit Pro"get value of plist "AlbumId" of every plist of plist "List of Albums" of plist of document "AlbumData.xml"end tellOK, that looks like quite a bit to swallow at once, so let's break that down, from right to left:plist of document "AlbumData.xml": gets the root plist of the AlbumData.xml document, which is assumed to already be open in PlistEdit Pro. Result: a Dictionary plistplist "List of Albums" of...: gets the plist under the key "List of Albums" in the root plist. Result: an Array plistevery plist of...: gets every child of the "List of Albums" plist. Result: a list of Dictionary plists.plist "AlbumId" of...: this is where Applescript gets cool - without having to write any silly loops, this statement iterates through the list of child plists, extracts the "AlbumId" child plist from each one, and returns a list containing the result, no muss no fuss. Result: a list of Number plists.get value of...: again, loops through the list of "AlbumId" plists we just got and extracts the value property of each one, resulting in a simple list of the ID numbers themselves, which is exactly what we're after. Result: a simple list of numbersNot only is this version of the script somewhat simpler, but it's also quite a bit more efficient, in that it doesn't have to send individual commands to retrieve each ID and concatenate it onto our result list. This isn't too bad in this example, but the difference can be quite significant in some applications (hint: try something similar with retrieving some message info from Mail and marvel at the speed difference) Reading the resultsRunning this script in Script Editor should result in something like:{2, 9.99001E+5, 9.99002E+5, 2580.0, 2578.0, 2579.0, 106.0, 107.0, 108.0, 357.0, 586.0, 587.0, 517.0, 427.0, 486.0, 411.0, 469.0, 538.0, 392.0, 442.0, 452.0, 458.0, 2265.0, 637.0, 655.0, 729.0, 2798.0, 2815.0, 3265.0, 3300.0}But why look at it in that hard to read form, when you can just feed it right back to PlistEdit Pro for display?tell application "PlistEdit Pro"set albumIDList to value of plist "AlbumId" of every plist of plist "List of Albums" of plist of document "AlbumData.xml"make new document at front of documentsset value of plist of front document to albumIDListactivateend tellNow you have a nicely displayed plist that you can sort, save, or do anything else you need to.Applescript is commonly thought of as mainly being for automating repetitive tasks, but with a little practice, it can also become quite useful for one-shot items like this.