]> git.sesse.net Git - xml-template/blob - ruby/xmltemplate.rb
Update the PHP SWIG version to PHP 7, with various crash fixes, too.
[xml-template] / ruby / xmltemplate.rb
1 require "rexml/document"
2
3 module XMLTemplate
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)
8                 return doc
9         end
10
11         def XMLTemplate.process!(node, obj, clean = true)
12                 if obj.is_a?(String)                    # overwrite
13                         node.children.delete_if { true }
14                         node.text = obj
15                 elsif obj.is_a?(REXML::Element)         # overwrite
16                         if obj.is_a?(REXML::Document)
17                                 obj = obj.root
18                         end
19                 
20                         node.children.delete_if { true }
21                         
22                         newobj = obj.deep_clone
23                         node.add(newobj)
24
25                         process!(newobj, {}, clean)
26                 elsif obj.is_a?(Hash) and node.is_a?(REXML::Element)                    # substitute
27                         node.children.each do |child|
28                                 processed = false
29                                 attributes_to_delete = []
30
31                                 if child.is_a?(REXML::Element)
32                                         if child.namespace == "http://template.sesse.net/"
33                                                 id = child.local_name
34                                         else
35                                                 # workaround for .to_a being braindamaged
36                                                 attr_list = []
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"
40                                                 }
41                                                 if id_attr.nil?
42                                                         id = nil
43                                                 else
44                                                         id = id_attr.value
45                                                 end     
46                                         end
47
48                                         if clean
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)
54                                                         end
55                                                 end
56                                         end
57
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]
63                                                 end
64                                 
65                                                 if not processed
66                                                         if key == child.local_name or (not id.nil? and key == "#" + id)
67                                                                 process!(child, obj[key], clean)
68                                                                 processed = true
69                                                         end
70                                                 end
71                                         end
72                                 end
73
74                                 if not processed
75                                         process!(child, obj, clean)
76                                 end
77
78                                 #
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).
83                                 #
84                                 attributes_to_delete.each { |a| child.attributes.delete(a) }
85                         end
86                 elsif obj.is_a?(Array)                          # repeat
87                         doc = node.document
88                         frag = REXML::Element.new
89
90                         node.children.each { |e| frag.add(e) }
91                         node.children.delete_if { true }
92                         
93                         obj.find_all { |x| not x.nil? } .each do |instance|
94                                 newnode = frag.deep_clone
95                                 node.add(newnode)
96                                 process!(newnode, instance, clean)
97                         end
98                 end
99
100                 if clean then
101                         clean!(node)
102                 end
103         end
104
105         def XMLTemplate.alternate(tag, array, *elems)
106                 i = 0
107                 array_copy = array.clone
108                 
109                 array_copy.each do |ref|
110                         if not ref.nil?
111                                 ref[tag] = elems[i % elems.length]
112                                 i = i + 1
113                         end
114                 end
115
116                 return array_copy
117         end
118         
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)
125                 end
126         end
127 end
128