Skip to content

Instantly share code, notes, and snippets.

@shanemcd
Forked from rkumar/xml2db.rb
Created August 27, 2011 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shanemcd/1175706 to your computer and use it in GitHub Desktop.
Save shanemcd/1175706 to your computer and use it in GitHub Desktop.
convert itunes music library to database sqlite3 using ruby
#!/usr/bin/env ruby
=begin
* Name: xml.rb
* Description parses xml iTunes Music Library and inserts into database
so other apps can use, rather than each time parsing xml file
* Author: Original - Aaron Patterson (xml parsing portion)
http://groups.google.com/group/nokogiri-talk/browse_thread/thread/97973521c6f5f0dc
* Additions by rkumar
* Date: 2010-08-04
* License:
Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
* create the itunes.sqlite file using http://gist.github.com/508400
@usage
./xml2db.rb iTunes\ Music\ Library.xml
=end
require 'rubygems'
require 'nokogiri'
require 'sqlite3'
require 'arrayfields'
require "highline/import"
def table_insert_hash db, table, hash
str = "INSERT INTO #{table} ("
qstr = [] # question marks
fields = [] # field names
bind_vars = [] # values to insert
hash.each_pair { |name, val|
fields << name
bind_vars << val
qstr << "?"
}
fstr = fields.join(",")
str << fstr
str << ") values ("
str << qstr.join(",")
str << ")"
#puts str
db.execute(str, *bind_vars)
rowid = db.get_first_value( "select last_insert_rowid();")
return rowid
end
counter = 0
dbname = "itunes.sqlite"
raise " #{dbname} must exist with tables in it - use http://gist.github.com/508400"
db = SQLite3::Database.new(dbname)
list = []
filename = ARGV[0] || File.expand_path("~/Music/iTunes/iTunes Music Library.xml")
doc = Nokogiri::XML(File.open(filename, 'r'))
# Find each dictionary item and loop through it
doc.xpath('/plist/dict/dict/dict').each do |node|
#hash = {}
hash = Hash.new("Not found")
last_key = nil
# Stuff the key value pairs in to hash. We know a key is followed by
# a value, so we'll just skip blank nodes, save the key, then when we
# find the value, add it to the hash
node.children.each do |child|
next if child.blank? # Don't care about blank nodes
if child.name == 'key'
# Save off the key, lowercasing and putting _ for space
last_key = child.text.tr('A-Z','a-z').tr(' ','_')
else
# Use the key we saved
hash[last_key] = child.text
end
end
list << hash # push on to our list
hash["track_id"] = hash["track_id"].to_i
table_insert_hash db, "tracks", hash
print "."
counter += 1
# for testing
if counter > 100
#puts "exiting during testing"
#exit
end
end
puts "#{counter} items"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment