Notes from the Trenches: A DP Blog

Parsing ITunes Library.xml with ActionScript 3.0

Posted At: June 27, 2007 12:06 PM | Posted By: Jeff Tapper
Related Categories: actionscript3, apollo, as3, flash9, flex2, flex3, fp9, itunes, libraryxml, ria

I recently built a hands-on presentation for the FlexManiacs conference, and thought it would be fun to have the class build a little apollo based mp3 player, which reads in the mp3 files from an iTunes libary.xml file, which they can then play, pause or stop.  Well, we did just that, but oddly enough, the hardest part in building that application turned out to be parsing the xml.  In the time I've been working with AS3 and Flex2, I've always found that working with well formed XML is incredibly easy.  Therein lies the problem, the xml that apple uses in this file is hideous, and seems to have been designed by someone without the least bit of understanding of structuring xml.

Here, you can see a sample library.xml file from itunes.  The first odd thing you might notice is that there are a total of only 5 different node names used throughout the file:  plist (the root node), key, string, integer and date.  Rather than using intelligently named nodes (ie. PlayList, Song, etc), a dict node is used to indicate any arbitrary grouping of other nodes.  Within a dict, you will find other dict nodes, or key nodes followed by either a node describing a datatype (string, integer or date).

The real challange in parsing this, is that there is no grouping of keynames to their values, except for the order in which they appear.  For example, for a song named "Every Worthy Cause" performed by Ben Wakeman, rather than an xml structure like this:

<song name="Every Worthy Cause" artist="Ben Wakeman" />  

or

<song><name>Every Worthy Cause</name><artist>Ben Wakeman</artist></song>

ITunes has it structured like this:

<dict><key>Name</key><string>Every Worthy Cause</string><key>Artist</key><string>Ben Wakeman</string></dict>

 This poses a number of challenges, primarily, because the only thing which associates the Name node with the value Every worthy cause is the order the nodes appear.  This makes the use of E4X for parsing the nodes nearly impossible.   Here, you can see the solution I came up with for parsing this xml.

package parsers{
 import mx.collections.ArrayCollection;
 import valueObjects.PlayListEntry;
 import flash.utils.Dictionary;
 import utils.TimeFormatter;
 
 
 public class LibraryParser{
  private static var lib:XML;
  public static function parseLibrary(xml:XML):ArrayCollection{
   var ac:ArrayCollection = new ArrayCollection();
   lib = xml;
   for each(var d:XML in xml.dict.dict.dict){
    ac.addItem(parseSong(d));
   }
   return ac;
  }
  private static function parseSong(song:XML):PlayListEntry{
   var ple:PlayListEntry = new PlayListEntry();
   var tune:Dictionary= new Dictionary();
           
   var key:String;
   for each (var tuneProperty:XML in song.children()){
             
       if (tuneProperty.name() == "key"){
           key = tuneProperty.text();
       } else {
           tune[key] = String(tuneProperty.text());
       }
   }
   ple.album = tune.Album;
   ple.artist = tune.Artist;
   ple.bitRate = tune["Bit Rate"];
   ple.genre=tune.Genre;
   ple.location=tune.Location;
   ple.name = tune.Name;
   ple.sampleRate = tune["Sample Rate"];
   ple.songLength = tune["Total Time"];
   ple.year=tune.Year;
   ple.lengthString = TimeFormatter.formatTime(ple.songLength);
   return ple;
  }
 }
}

What this does, is to find each dict node which indicates a song, and then loop over each of its children in order.  If it finds a node called Key, it creates a new entry in a Dictionary object (like a HashMap).  Once the dictionary is fully assembled, the elements from the dictionary are parsed into a strongly typed class called PlayListEntry, which simply specify all the attributes of a song.  The PlayListEntry class looks like this:

package valueObjects{
 public class PlayListEntry {
  public var name:String;
  public var artist:String;
  public var album:String;
  public var genre:String;
  public var songLength:int;
  public var year:int;
  public var location:String;
  public var bitRate:int;
  public var sampleRate:int;
  public var lengthString:String;
 }
}

A version of these files for use with Apollo (in which you pass in a FileStream object, rather than xml), can be found here.

If anyone has a more elegant solution to parsing this library.xml file into something usable in AS3, I'd love to hear it.

Share and Enjoy:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • PDF
  • RSS
  • email
  • Technorati

Comments (6)

6 Responses to “Parsing ITunes Library.xml with ActionScript 3.0”

  1. A visitor says:

    True, Apple’s Plist format really really sucks. It’s a pain to parse in any situation besides when you happen to run Cocoa (where there are API:s that do it for you). I’ve worked with XSL and Plists and that is probably as much trouble as E4X. However, I have written about Plist parsing in PHP, which can be accomplished quite elegantly (http://blog.iconara.net/2007/05/08/php-plist-parsing/) and also how to do it in XSL (http://blog.iconara.net/2006/12/13/xsl-and-plists/). Both methods can probably be converted into a solution using E4X.

  2. A visitor says:

    True, Apple’s Plist format really really sucks. It’s a pain to parse in any situation besides when you happen to run Cocoa (where there are API:s that do it for you). I’ve worked with XSL and Plists and that is probably as much trouble as E4X. However, I have written about Plist parsing in PHP, which can be accomplished quite elegantly (http://blog.iconara.net/2007/05/08/php-plist-parsing/) and also how to do it in XSL (http://blog.iconara.net/2006/12/13/xsl-and-plists/). Both methods can probably be converted into a solution using E4X.

  3. A visitor says:

    wow. i didnt think somebody would have tackled this in flex. i wish there would be a way to automate Itunes so it would re-export the xml files related to the playlist….

  4. A visitor says:

    wow. i didnt think somebody would have tackled this in flex. i wish there would be a way to automate Itunes so it would re-export the xml files related to the playlist….

  5. A visitor says:

    Dude, you need to seriuously work on your styling skills. Reading White text on a gray background gives me a headache. And even highlighting the text is a chore to read….

    Good solution in AS3 and Flex though……just work on font-colo vs. background color.

  6. A visitor says:

    Dude, you need to seriuously work on your styling skills. Reading White text on a gray background gives me a headache. And even highlighting the text is a chore to read….

    Good solution in AS3 and Flex though……just work on font-colo vs. background color.

Leave a Reply