Created
August 6, 2010 17:09
-
-
Save eigan/511627 to your computer and use it in GitHub Desktop.
Itunes php xml parser class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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