X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ruby%2Fxmltemplate.rb;fp=ruby%2Fxmltemplate.rb;h=3f4e11a38e71488f2a3778a65f47daf633fcf13d;hb=7d86bc42d79ffdf9a9bd601716c2f832a123a1ce;hp=0000000000000000000000000000000000000000;hpb=0b5e750eae0d8d58ae293beeaf29368431d5b618;p=xml-template diff --git a/ruby/xmltemplate.rb b/ruby/xmltemplate.rb new file mode 100644 index 0000000..3f4e11a --- /dev/null +++ b/ruby/xmltemplate.rb @@ -0,0 +1,128 @@ +require "rexml/document" + +module XMLTemplate + def XMLTemplate.process_file(filename, obj, clean = true) + file = File.new(filename) + doc = REXML::Document.new file + XMLTemplate.process!(doc, obj, clean) + return doc + end + + def XMLTemplate.process!(node, obj, clean = true) + if obj.is_a?(String) # overwrite + node.children.delete_if { true } + node.text = obj + elsif obj.is_a?(REXML::Element) # overwrite + if obj.is_a?(REXML::Document) + obj = obj.root + end + + node.children.delete_if { true } + + newobj = obj.deep_clone + node.add(newobj) + + process!(newobj, {}, clean) + elsif obj.is_a?(Hash) and node.is_a?(REXML::Element) # substitute + node.children.each do |child| + processed = false + attributes_to_delete = [] + + if child.is_a?(REXML::Element) + if child.namespace == "http://template.sesse.net/" + id = child.local_name + else + # workaround for .to_a being braindamaged + attr_list = [] + child.attributes.each_attribute { |a| attr_list.push(a) } + id_attr = attr_list.find { |a| + a.namespace == "http://template.sesse.net/" and a.local_name == "id" + } + if id_attr.nil? + id = nil + else + id = id_attr.value + end + end + + if clean + child.attributes.each_attribute do |a| + if a.namespace == "http://template.sesse.net/" then + attributes_to_delete.push(a) + elsif a.prefix == "xmlns" and a.value == "http://template.sesse.net/" then + attributes_to_delete.push(a) + end + end + end + + # check all substitutions to see if we fuond anything appropriate + obj.keys.each do |key| + if (Regexp.new("^" + Regexp.escape(child.local_name) + "/") =~ key) or + (not id.nil? and Regexp.new("^#" + Regexp.escape(id) + "/") =~ key) + child.attributes[key.split("/")[1]] = obj[key] + end + + if not processed + if key == child.local_name or (not id.nil? and key == "#" + id) + process!(child, obj[key], clean) + processed = true + end + end + end + end + + if not processed + process!(child, obj, clean) + end + + # + # We need to do this _after_ processing all the sub-parts, + # since if we remove xmlns: attributes before processing, + # REXML loses track of the namespaces of the child elements + # (since the prefix declaration is no longer there). + # + attributes_to_delete.each { |a| child.attributes.delete(a) } + end + elsif obj.is_a?(Array) # repeat + doc = node.document + frag = REXML::Element.new + + node.children.each { |e| frag.add(e) } + node.children.delete_if { true } + + obj.find_all { |x| not x.nil? } .each do |instance| + newnode = frag.deep_clone + node.add(newnode) + process!(newnode, instance, clean) + end + end + + if clean then + clean!(node) + end + end + + def XMLTemplate.alternate(tag, array, *elems) + i = 0 + array_copy = array.clone + + array_copy.each do |ref| + if not ref.nil? + ref[tag] = elems[i % elems.length] + i = i + 1 + end + end + + return array_copy + end + + def XMLTemplate.clean!(node) + if node.is_a?(REXML::Element) and (node.namespace == "http://template.sesse.net/" or node.name == "UNDEFINED") + # as this is a dummy node, we want to remove it and move everything further up + # after we've done any required replacements + node.children.each { |n| node.parent.insert_before(node, n) } + node.parent.delete(node) + end + end +end +