Skip to content

Instantly share code, notes, and snippets.

@maxigs
Created February 14, 2012 12:22
Show Gist options
  • Save maxigs/1826435 to your computer and use it in GitHub Desktop.
Save maxigs/1826435 to your computer and use it in GitHub Desktop.
Script to merge values from a plist into another file
#!/usr/bin/env ruby
if ARGV.size != 2
puts "Merges Fields from Plist-Files together into a new file"
puts "USAGE: ./plistmerge.rb source-file input-file"
exit
end
# The values for those fields will be migrated from the source to the target file
FieldsToMigrate = %w(latitude longitude)
# Which field is used for matching dicts together
FieldToMatch = 'id'
mapping = {}
check_fileds = [FieldToMatch] + FieldsToMigrate
source_file = ARGV[0] # this file is the source
input_file = ARGV[1] # this files values will be merged into the source
output_file = source_file.gsub('.plist', '_new.plist')
# read the input file and build a hash with the data to be merged into the source file
#
node = nil
attribute = nil
File.open(input_file, "r:UTF-8") do |input|
while (line = input.gets)
if line =~ /<dict>/
# start new node
node = {}
elsif line =~ /<\/dict>/
# finish node
id = node.delete(FieldToMatch)
mapping[id], node = node, nil
elsif attribute
# read the value for the attribute, and reset the attribute
node[attribute] = line[/<(integer|string|real|date)>(.+)<\/(integer|string|real|date)>/, 2]
attribute = nil
elsif at = line[/<key>(.+)<\/key>/, 1] and check_fileds.include?(at)
# get the next key and set the attribute if we need it
attribute = at
end
end
end
# Read the input file and write it into the output file dict by dict
# while updating the to be merged fields on the go
#
write_buffer = []
File.open(output_file, "w:UTF-8") do |output|
File.open(input_file, "r:UTF-8") do |source|
while (line = source.gets)
if line =~ /<dict>/
# start new node
write_buffer << line
elsif line =~ /<\/dict>/
# finish node
write_buffer << line
node = nil
attribute = nil
write_buffer.each do |buffer_line|
if at = buffer_line[/<key>(.+)<\/key>/, 1] and at == FieldToMatch
attribute = FieldToMatch
elsif attribute
node = buffer_line[/<(integer|string|real|date)>(.+)<\/(integer|string|real|date)>/, 2]
attribute = nil
break
end
end
node = mapping[node]
attribute = nil
write_buffer.each do |buffer_line|
if at = buffer_line[/<key>(.+)<\/key>/, 1] and FieldsToMigrate.include?(at)
attribute = at
elsif attribute
buffer_line.gsub!(/<(integer|string|real|date)>(.+)<\/(integer|string|real|date)>/) do
"<#{$1}>#{node[attribute]}</#{$3}>"
end
attribute = nil
end
output.puts buffer_line
end
write_buffer = []
else
write_buffer << line
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment