Digging around today for a PHP parser for OSX plist files, I was surprised to find no good pre-existing solutions. Even Apple’s own site gives a relatively poor solution to the problem (see here). Normally SimpleXML is enough to handle most XML parsing needs, but the plist XML format is just broken enough to make parsing it with SimpleXML virtually impossible. Since I hadn’t played with XMLReader much, I thought it would be a good chance to give it a spin. For the anxious types, the code is available on github in my php_class_lib project, so dig right in. Read on for a simple example (included in the repos).
The original intent of the parser for me was to parse my iTunes’ library in PHP, so this example will show doing just that:
<?php
include("PlistParser.inc");
$parser = new plistParser();
$plist = $parser->parse(dirname(__FILE__) . "/iTunes.xml");
var_dump($plist);
And from that, the output is as follows:
array(8) {
["Major Version"]=>
int(1)
["Minor Version"]=>
int(1)
["Application Version"]=>
string(5) "8.0.1"
["Features"]=>
int(5)
["Show Content Ratings"]=>
bool(true)
["Music Folder"]=>
string(60) "file://localhost/Users/testUser/Music/iTunes/iTunes%20Music/"
["Library Persistent ID"]=>
string(15) "C39203948AF3D3E"
["Tracks"]=>
array(1) {
[1]=>
array(25) {
["Track ID"]=>
int(1)
["Name"]=>
string(8) "My Track"
["Artist"]=>
string(9) "My Artist"
["Album"]=>
string(8) "My Album"
["Genre"]=>
string(8) "My Genre"
["Kind"]=>
string(15) "MPEG audio file"
["Size"]=>
int(123456)
["Total Time"]=>
int(123456)
["Track Number"]=>
int(1)
["Year"]=>
int(2008)
["Date Modified"]=>
string(20) "2008-03-03T03:33:33Z"
["Date Added"]=>
string(20) "2008-03-03T03:33:33Z"
["Bit Rate"]=>
int(128)
["Sample Rate"]=>
int(44100)
["Comments"]=>
string(20) "All Rights Reserved."
["Release Date"]=>
string(20) "2007-03-12T04:01:37Z"
["Persistent ID"]=>
string(14) "C3E339393939E3"
["Track Type"]=>
string(4) "File"
["Podcast"]=>
bool(false)
["Unplayed"]=>
bool(true)
["File Type"]=>
int(123456)
["File Creator"]=>
int(123456)
["Location"]=>
string(66) "file://localhost/Users/testUser/Music/iTunes/iTunes%20Music/my.mp3"
["File Folder Count"]=>
int(4)
["Library Folder Count"]=>
int(1)
}
}
}
As you can see, the PHP parser made short order of that task. From here you now have full access to all the metadata in your iTunes library. Feel free to use the class in your own projects and be sure to let me know what you build with it.
Tags: Apple, git, github, iTunes, iTunes Library, metadata, OS X, parser, parsing, PHP, php_class_lib, plist, XML




Nice, this should help with dumps from Delicious Library as well. The XML export uses plist as well.
Thanks, this will be useful for me
[...] Johnstone has come up with a simple plist xml parser. The plist format is what iTunes (and some other application) uses for its library [...]
[...] Johnstone has come up with a simple plist xml parser. The plist format is what iTunes (and some other application) uses for its library [...]
I am unable to parse plist file in http://www.adiumxtras.com/index.php?a=xtras&xtra_id=1431 others such.
The reported error is: ‘Not a valid plist. key is not a valid type’.
If you aren’t set on writing your own thing to do this particular task (parsing the iTunes xml file), and you’re okay using tools Apple provides, look up the man page for PlistBuddy(8). iTunes comes with its own copy of the utility:
/Library/Receipts/iTunesX.pkg/Contents/Resources/PlistBuddy
It’s also at /usr/libexec/PlistBuddy.
The command:
PlistBuddy -c print iTunes\ Music\ Library.xml
…will print every entry in the xml (aka plist) file. There are also commands for adding, deleting, copying, importing, merging, and modifying entries to the same file. You could conceivably wrap php around calls to PlistBuddy (e.g., for a web-driven interface); stuff like that makes me cringe but if it works for you that’s all that matters.
Don’t know if it outputs in a format that you can use but it looks easier to deal with than the original xml.
Keep in mind though that the XML file is never used by iTunes unless the user explicitly tells iTunes to import from it. The XML file is just a way for other programs to get at iTunes’ data without needing to parse the actual library file (the format of which seems to change with every new release of iTunes).
Nice but I can’t get it to read ~/Library/Preferences/com.apple.Safari.plist or ~/Library/Preferences/org.mozilla.firefox.plist Any ideas?
Tom those plist files are in a binary format. This app (seems… I haven’t actually used it) to work on XML formatted plist files only.
If you want to convert a binary plist into xml do this from terminal (using the correct path for your case):
plutil -convert xml1 /Users/tomshaw/Desktop/Bookmarks.plist
Don’t know if the converted file will work with this script but you can give it a shot.
Just to clarify (using your example) you would do the above as follows (this assumes you have made a COPY of the plist file and put it on your desktop. Don’t do this to the original plist file as it will be made unreadable to Safari (though you can easily convert it back to the correct binary format:
plutil -convert xml1 ~/Desktop/com.apple.Safari.plist
This is a bug in parse_array function. I think your problem, Gurpartap Singh, should be resolved by moving line 99 and 100 in original code to line 98 and 99 accordingly (i mean above “do”). Thx.
this doesnt seem to follow arrays at all. if i have a dict->array->10dicts it fails but if i have dict->array->1dict it works.
PLists come either in XML or binary format. The parser written by Jeremy only works with the XML based PLists. Besides that, i could only find functionality for reading XML PLists.
In my projects I needed some more power, especially when it came to creating PLists. So i wrote a little tool called CFPropertyList, which in fact was just a logic wrapper around PHP’s DOM. To simplify things in daily business, i also added functionality for guessing the PList structure from native PHP data structures. A friend of mine ported Apple’s CFBinaryPList to PHP, adding the result to CFPropertyList. So now we’ve got a fairly simple API to use Apple’s PropertyLists (XML and binary) in PHP. Reading, writing, creating, manipulating – everything you need.
The tool was just launched this morning. Check it out at http://code.google.com/p/cfpropertylist/
“The PHP implementation of Apple’s PropertyList can handle XML PropertyLists as well as binary PropertyLists. It offers functionality to easily convert data between worlds, e.g. recalculating timestamps from unix epoch to apple epoch and vice versa. A feature to automagically create (guess) the plist structure from a normal PHP data structure will help you dump your data to plist in no time.”
Thanks for this, you saved me an hour of dullness! Just forked and pushed back a small changeset to allow parsing of strings as well as files, hope it’s useful to someone else.
There is some plistParser with Adium plist files, i want to create site-smiles sysem based on adium smile-sets
Try to parse plist from this set(http://www.adiumxtras.com/index.php?a=xtras&xtra_id=4207), it will crash with error:
Fatal error: Uncaught exception ‘Exception’ with message ‘Not a valid plist. key is not a valid type’