1 require "rexml/document"
4 def XMLTemplate.process_file(filename, obj, clean = true)
5 file = File.new(filename)
6 doc = REXML::Document.new file
7 XMLTemplate.process!(doc, obj, clean)
11 def XMLTemplate.process!(node, obj, clean = true)
12 if obj.is_a?(String) # overwrite
13 node.children.delete_if { true }
15 elsif obj.is_a?(REXML::Element) # overwrite
16 if obj.is_a?(REXML::Document)
20 node.children.delete_if { true }
22 newobj = obj.deep_clone
25 process!(newobj, {}, clean)
26 elsif obj.is_a?(Hash) and node.is_a?(REXML::Element) # substitute
27 node.children.each do |child|
29 attributes_to_delete = []
31 if child.is_a?(REXML::Element)
32 if child.namespace == "http://template.sesse.net/"
35 # workaround for .to_a being braindamaged
37 child.attributes.each_attribute { |a| attr_list.push(a) }
38 id_attr = attr_list.find { |a|
39 a.namespace == "http://template.sesse.net/" and a.local_name == "id"
49 child.attributes.each_attribute do |a|
50 if a.namespace == "http://template.sesse.net/" then
51 attributes_to_delete.push(a)
52 elsif a.prefix == "xmlns" and a.value == "http://template.sesse.net/" then
53 attributes_to_delete.push(a)
58 # check all substitutions to see if we fuond anything appropriate
59 obj.keys.each do |key|
60 if (Regexp.new("^" + Regexp.escape(child.local_name) + "/") =~ key) or
61 (not id.nil? and Regexp.new("^#" + Regexp.escape(id) + "/") =~ key)
62 child.attributes[key.split("/")[1]] = obj[key]
66 if key == child.local_name or (not id.nil? and key == "#" + id)
67 process!(child, obj[key], clean)
75 process!(child, obj, clean)
79 # We need to do this _after_ processing all the sub-parts,
80 # since if we remove xmlns: attributes before processing,
81 # REXML loses track of the namespaces of the child elements
82 # (since the prefix declaration is no longer there).
84 attributes_to_delete.each { |a| child.attributes.delete(a) }
86 elsif obj.is_a?(Array) # repeat
88 frag = REXML::Element.new
90 node.children.each { |e| frag.add(e) }
91 node.children.delete_if { true }
93 obj.find_all { |x| not x.nil? } .each do |instance|
94 newnode = frag.deep_clone
96 process!(newnode, instance, clean)
105 def XMLTemplate.alternate(tag, array, *elems)
107 array_copy = array.clone
109 array_copy.each do |ref|
111 ref[tag] = elems[i % elems.length]
119 def XMLTemplate.clean!(node)
120 if node.is_a?(REXML::Element) and (node.namespace == "http://template.sesse.net/" or node.name == "UNDEFINED")
121 # as this is a dummy node, we want to remove it and move everything further up
122 # after we've done any required replacements
123 node.children.each { |n| node.parent.insert_before(node, n) }
124 node.parent.delete(node)