intertwingly

It’s just data

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.