Hack 44 Transform Your iTunes Library File

figs/moderate.gif figs/hack44.gif

Grab data out of your iTunes library file and transform it into HTML.

Apple's iTunes (http://www.apple.com/itunes/) is a nifty application that allows you to purchase, store, organize, and play media on either the Mac or Windows. You can buy and download individual songs or whole albums from the iTunes Music Store, and then store them on your hard drive, burn them to CD, or load them into an iPod digital music player (http://www.apple.com/ipod/). Figure 3-22 shows the iTunes Music Store in the iTunes application in Windows.

Figure 3-22. iTunes Music Store

One XML feature of iTunes is that you can save information about your music library in an XML file using the File Export Library command. This file is an example of the Apple Property List (plist) file format, common on Mac OS X systems. For example, the file ~/.MacOSX/environment.plist is a plist file in which a user's environment variables are stored and that can be edited with the PropertyListEditor.app (see http://developer.apple.com/qa/qa2001/qa1067.html for an example).

In raw form, plist files can be long and hard to decipher. That's where XSLT can help. This hack will show you how to transform your Library.xml plist file into HTML. A few lines of an instance of Library.xml (Version are shown in Example 3-26.

Example 3-26. Library.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/


<plist version="1.0">


    <key>Major Version</key><integer>1</integer>

    <key>Minor Version</key><integer>1</integer>

    <key>Application Version</key><string>4.2</string>

    <key>Music Folder</key><string>file://localhost/C:/






            <key>Track ID</key><integer>33</integer>

            <key>Name</key><string>A Thousand Years</string>


            <key>Album</key><string>Brand New Day</string>


            <key>Kind</key><string>Protected AAC audio



            <key>Total Time</key><integer>358144</integer>

            <key>Disc Number</key><integer>1</integer>

            <key>Disc Count</key><integer>1</integer>

            <key>Track Number</key><integer>1</integer>

            <key>Track Count</key><integer>10</integer>


            <key>Date Modified</key><date>2004-02-04T02:12:06Z</date>

            <key>Date Added</key><date>2004-02-04T02:10:11Z</date>

            <key>Bit Rate</key><integer>128</integer>

            <key>Sample Rate</key><integer>44100</integer>

            <key>Play Count</key><integer>5</integer>

            <key>Play Date</key><integer>-1136265306</integer>

            <key>Play Date UTC</key><date>2004-02-04T08:13:10Z</date>


The fields that represent tracks are stored in key elements, followed by string, integer, or date elements.

Having previously saved your Library.xml file to the XSLT working directory (where the archive files are stored), you can now transform it with Library.xsl, shown in Example 3-27.

Example 3-27. Library.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html" indent="yes"/>


<!-- Stylesheet for tracks in Apple iTunes library export file -->


<xsl:template match="plist">



 <title>My iTunes</title>

 <style type="text/css">

 body {font-family:sans-serif}

 h1 {text-align:center}

 table {margin-left:auto;margin-right:auto;}

 thead {background-color:black;color:white}

 td,th {padding: 7px 7px 7px 7px;font-size:15px}




 <h1>My iTunes</h1>

 <xsl:apply-templates select="dict"/>





<xsl:template match="dict">

 <table border="1" rules="all">



   <!--th>Track ID</th-->







   <!--th>Total Time</th-->

   <!--th>Disc Number</th-->

   <!--th>Disc Count</th-->

   <!--th>Track Number</th-->

   <!--th>Track Count</th-->


   <!--th>Date Modified</th-->

   <th>Date Added</th>

   <!--th>Bit Rate</th-->

   <!--th>Sample Rate</th-->

   <!--th>Play Count</th-->

   <!--th>Play Date</th-->

   <!--th>Play Date UTC</th-->



   <!--th>File Folder Count</th-->

   <!--th>Library Folder Count</th-->



 <xsl:apply-templates select="dict/dict"/>




<xsl:template match="dict/dict">


 <!--td style="text-align:center"><xsl:value-of select="key[.='Track ID']/


 <td><xsl:value-of select="key[.='Name']/following-sibling::string"/></td>

 <td><xsl:value-of select="key[.='Artist']/following-sibling::string"/></td>

 <td><xsl:value-of select="key[.='Album']/following-sibling::string"/></td>

 <td><xsl:value-of select="key[.='Genre']/following-sibling::string"/></td>

 <!--td><xsl:value-of select="key[.='Kind']/following-sibling::string"/></td-->

 <!--td style="text-align:center"><xsl:value-of select="key[.='Size']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Total Time']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Disc Number']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Disc Count']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Track Number']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Track Count']/


 <td style="text-align:center"><xsl:value-of select="key[.='Year']/


 <!--td><xsl:value-of select="substring(key[.='Date Modified']/

following-sibling::date, 1, 10)"/></td-->

 <td><xsl:value-of select="substring(key[.='Date Added']/

following-sibling::date, 1, 10)"/></td>

 <!--td style="text-align:center"><xsl:value-of select="key[.='Bit Rate']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Sample Rate']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Play Count']/


 <!--td><xsl:value-of select="key[.='Play Date']/



 <!--td><xsl:value-of select="substring(key[.='Play Date UTC']/

following-sibling::date, 1, 10)"/></td-->

 <!--td><xsl:value-of select="key[.='Normalization']/


 <!--td><xsl:value-of select="key[.='Location']/



 <!--td style="text-align:center"><xsl:value-of select="key[.='File Folder Count']/


 <!--td style="text-align:center"><xsl:value-of select="key[.='Library Folder Count']/






This stylesheet produces HTML output. (It's just one approach to the problem?there are plenty of other possibilities that could work, too.) Though most of the lines are commented out, each of the track's fields are represented. Only those lines that are uncommented will capture nodes from Library.xml. Currently, the stylesheet grabs the Name, Artist, Album, Genre, Year, and Date Added fields. This is done through the use of predicates or filters in square brackets (such as key[.='Name']), which identify the content of key elements. The following-sibling axis (such as following-sibling::string) helps find nodes that follow and are siblings of the selected node.

If you'd like, you can uncomment other fields, but you must do so in two places for each field: first, where the track name is stored in a th element near the top of the stylesheet; and second, in a complementary td element later in the stylesheet.

Now transform Library.xml with Library.xsl, saving it in an HTML file such as Library.html. I'll use Xalan to do the job, with this line:

xalan -o Library.html Library.xml Library.xsl

Next, display Library.html in a browser. You should see something that looks like Figure 3-23.

Figure 3-23. Library.html in Mozilla Firebird