Skip to content

Instantly share code, notes, and snippets.

@eigan
Created August 6, 2010 17:09
Show Gist options
  • Save eigan/511627 to your computer and use it in GitHub Desktop.
Save eigan/511627 to your computer and use it in GitHub Desktop.
Itunes php xml parser class
<?php
/**
* Need to get an array of either tracks or playlists from your itunes library?
* yes? then use this shitty code then
*
* Just do like this:
*
* $itunes = new Parse("path/to/your/iTunes Music Library.xml", "all");
*
* The first paramter is (obviously) the xml file
* The second parameter is where you specify what you want to get,
* could be either playlist or tracks
*
*
* I have added some random code downstairs, so just test it, aight...
*
* CHANGES:
* 0.2.1 - hurr. Looks like the master playlist is a bit different depending
* on the iTunes version. But think I fixed skipping for
* the latest/english version now
* 0.2 - Skipping master playlist (that is everything), saves 5% memory
* 0.1 - Init release
*
*
* @author So yeah, the author is me, but i got some inspiration
* from the itunes xml parser at apple.com
* @license hurr, do whatever you want :S
* @version 0.1
*/
// I have a 50MB big (30K tracks, almost hundred playlists) xml file.
// ^ It works - but takes ALOT OF TIME
// might need this if your file is over 20MB
//ini_set('memory_limit', '300M');
// test memory usage for script
function mem_use($peak = false) {
if($peak) return number_format(memory_get_peak_usage(), 0, '.', ',') . " bytes\n";
return number_format(memory_get_usage(), 0, '.', ',') . " bytes\n";
}
echo 'Initial: ' . mem_use();
// only tracks now, but you could choose "playlists" or "all"
$itunes = new Parse("/path/to/iTunes Music Library.xml", "tracks");
echo 'Peak: ' . mem_use(true);
echo 'End: ' . mem_use();
// Print array with the result
print_r($itunes->getLibrary());
// The idea is to insert this to a dabase of your choice
// And here ladies(lol, like that happens) and gentlemen (yeah!). THE CODE!
class Parse {
private $library; // Array, where data is stored
private $current_key; // key for each element in second dimension of array
private $current_element; // stores xml element name
private $current_data; // value for second dimension array elements
private $current_type = "tracks"; // stores what type we are handling, starts with traks, later playlists
private $track_id; // counter for num tracks
private $playlist_id; // counter for playlist_id
private $skip_playlist; // boolean, will skip the master playlist (everything)
private $listing_playlist_tracks; // boolean, if inside playlist tracks array
private $stop_parser; // boolean used to help us out of library
/**
* Starts this shit :P
*
**/
public function __construct($file, $type = "all")
{
$this->find_type = $type;
$this->listing_playlist_tracks = false;
$this->stop_parser = false;
$this->skip_playlist = false;
$xml_parser = xml_parser_create();
xml_set_object($xml_parser, &$this);
xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, true);
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "_start", "_end");
xml_set_character_data_handler($xml_parser, "_char");
if (!($fp = @fopen($file, "r"))) {
return false;
}
while(($data = fread($fp, 4096)) && $this->stop_parser != true) {
if(!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d\n",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
}
/**
* Function is called when start tag is found
*
**/
private function _start($parser, $name, $attr)
{
if($name == "DICT" && $this->current_type == "tracks") {
$this->track_id++;
} elseif($name == "DICT"
&& $this->current_type == "playlists"
&& $this->listing_playlist_tracks === false
) {
$this->playlist_id++;
}
if ($this->track_id > 2){
$this->current_element = $name;
}
}
/**
* Function is called when end tag is found.
*
**/
private function _end($parser, $name)
{
if($this->find_type == "tracks" && $this->current_type == "playlists") {
$this->stop_parser = true;
return;
}
if($this->find_type == "playlists" && $this->current_type != "playlists") {
//$this->stop_parser = true; should not stop parser because playlists come after tracks in xml file
return;
}
if($this->current_type == "playlists"
&& ($this->current_key == "Master" && $this->current_data == "Master")
|| ($this->current_key == "Music" && $this->current_data == "Music")
) {
$this->skip_playlist = true;
unset($this->library[$this->current_type][$this->playlist_id]);
$this->playlist_id--;
}
if(!empty($this->current_element) && $this->skip_playlist === false) {
if($this->current_element=="KEY"){
$this->current_key = $this->current_data;
} elseif(!empty($this->current_data)) {
if($this->current_type == "tracks") {
$this->library[$this->current_type][$this->track_id][$this->current_key] = $this->current_data;
} elseif($this->listing_playlist_tracks === false) {
$this->library[$this->current_type][$this->playlist_id][$this->current_key] = $this->current_data;
} else {
$this->library[$this->current_type][$this->playlist_id]['Tracks'][][$this->current_key] = $this->current_data;
}
}
}
if($name == "ARRAY" && $this->listing_playlist_tracks) {
$this->listing_playlist_tracks = false;
$this->skip_playlist = false;
}
}
/**
* Function for handling data inside tags
*
**/
private function _char($parser, $data)
{
if($data=="Playlists") {
$this->current_type = "playlists";
}
if($data == "Playlist Items") {
$this->listing_playlist_tracks = true;
}
$this->current_data = trim($data);
}
/**
* Returns the library
*
* @return array
**/
public function getLibrary()
{
return $this->library;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment