Here is a very simple solution. It doesn't try to understand much of the
contents of the .ged file, it just builds a tree of nodes and dumps them
to xml.
#!/usr/bin/env ruby
require 'CGI'
class String
def indent(width)
map {|line| ' ' * width + line.chomp}.join("\n")
end
end
class Node
def initialize(type, value)
@type = type
@value = CGI.escapeHTML(value)
@children = []
end
def <<(child)
@children << child
end
def to_xml
children = @children.map{|c| c.to_xml}.join("\n").indent(2)
if @type[0] == ?@
return "<%s id=\"%s\">\n%s\n</%s>" %
[@value.downcase, @type, children, @value.downcase]
elsif children.empty?
return "<%s>%s</%s>" % [@type.downcase, @value, @type.downcase]
else
if @value.empty?
return "<%s>\n%s\n</%s>" %
[@type.downcase, children, @type.downcase]
else
return "<%s value=\"%s\">\n%s\n</%s>" %
[@type.downcase, @value, children, @type.downcase]
end
end
end
end
if ARGV.size != 2
puts "Usage: gedparser.rb [input.ged] [ouput.xml]"
exit
end
root = []
stack = [root]
File.readlines(ARGV[0]).each do |line|
line = line.strip
depth, type, value = line.split(/\s+/, 3)
next unless type
value ||= ''
node = Node.new(type, value)
stack[depth.to_i] << node
stack[depth.to_i + 1] = node
end
xml = root.map {|node| node.to_xml}.join("\n")
xml = "<gedcom>\n" + xml.indent(2) + "\n</gedcom>"
File.open(ARGV[1], 'w') {|f| f.puts xml}