Patches Are... Wait For It... Just Data
James Snell: This is clearly better, IMHO, than the line-based diff, but still requires that the client and server both be able to do identical Atom-to-JSON serializations.
Why? My daughter is studying Algebra II right now, and evaluating f(g(x)), and if she can master such concepts, so can we:
require 'rexml/document'
require 'json'
doc = REXML::Document.new(open(ARGV[0]).read)
SINGULAR = {'authors'=>'author'}
JSON.parse(open(ARGV[1]).read).each {|rule|
# map json path to xpath
path=rule['path']
path=path[0..-3]+["@#{path.last}"] if path[-2] == 'attributes'
path.map! {|item| SINGULAR[item] || item}
name = path.pop if rule['action'] == 'create'
path=path.join('/')
path.gsub!(/\/(\d+)/) {"[#{$1.to_i+1}]"}
# apply the action
value = rule['value']
case rule['action']
when 'edit'
if path.index('@')
doc.elements[path].normalized=REXML::Text.normalize(value)
else
doc.elements[path].text = value
end
when 'create'
if name[0] == ?@
name = '@xml:lang' if name=='@lang'
doc.elements[path].attributes[name[1..-1]] = value
elsif value == []
doc.elements[path].add_element(name)
elsif value != {}
doc.elements[path].add_element(name).add_text(value)
end
end
}
puts doc
Note: the above is just barely enough to handle the input data and patch in James’ example, but with a few more test cases, this could quickly become full function.