rexslt 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. data/lib/rexslt.rb +116 -59
  2. metadata +2 -2
data/lib/rexslt.rb CHANGED
@@ -1,120 +1,177 @@
1
1
  require 'rexml/document'
2
2
 
3
+
3
4
  class Rexslt
4
5
  include REXML
5
-
6
+
6
7
  def initialize(xsl, xml)
7
-
8
+
8
9
  doc_xml = Document.new(xml)
9
10
  doc_xsl = Document.new(xsl)
11
+
12
+ @doc = Document.new('<root/>')
13
+ indent = ''
14
+ previous_indent = indent.clone
15
+ @xsl_methods = [:apply_templates, :value_of, :element, :if, :choose, :when, :copy_of, :attribute]
16
+
17
+ h = XPath.match(doc_xsl.root, "xsl:output/attribute::*").inject({})\
18
+ {|r,x| r.merge(x.name.to_sym => x.value)}
10
19
 
11
- @xsl_methods = [:apply_templates, :value_of, :element, :if, :choose, :when]
20
+ @indent = true if h and h[:indent] == 'yes'
12
21
 
13
22
  # fetch the templates
14
23
  @templates = XPath.match(doc_xsl.root, 'xsl:template').inject({}) do |r,x|
15
24
  r.merge(x.attribute('match').value => x)
16
25
  end
17
26
 
18
- xpath = String.new @templates.to_a[0][0]
19
- o = XPath.first(doc_xml, xpath)
20
-
21
27
  # using the 1st template
22
- @a = XPath.match(doc_xml, xpath).map do |x|
23
- read_node @templates.to_a[0][-1], x
28
+ xpath = String.new @templates.to_a[0][0]
29
+ XPath.match(doc_xml, xpath).each_with_index do |x,i|
30
+ read_node @templates.to_a[0][-1], x, @doc.root, indent.clone, previous_indent.clone
24
31
  end
25
-
26
32
  end
27
33
 
28
- def to_s() @a.flatten.join end
29
-
30
- def to_a() @a end
31
-
32
- alias text to_s
34
+ def to_s()
35
+ @doc.to_s[/<root>(.*)<\/root>/m,1]
36
+ end
37
+
38
+ def to_doc(); @doc; end
33
39
 
34
40
  private
35
41
 
36
- def read_node(template_node, doc_node)
42
+ def read_node(template_node, element, doc_element, indent, previous_indent)
37
43
 
38
44
  procs = {"REXML::Element" => :read_raw_element, "REXML::Text" => :read_raw_text}
39
- template_node.map do |x|
40
- #puts 'x : ' + x.inspect
41
- method(procs[x.class.to_s]).call(doc_node, x)
45
+ template_node.each do |x|
46
+ method(procs[x.class.to_s]).call(element, x, doc_element, indent.clone, previous_indent)
42
47
  end
43
-
48
+
44
49
  end
45
50
 
46
- def read_raw_text(doc_node, x)
47
- r = x.to_s.strip.length > 0 ? x.to_s : ''
48
- #puts 'xx : ' + r.inspect
49
- r
51
+ # element: xml source element, x: xsl element, doc_element: current destination xml element
52
+ #
53
+ def read_raw_text(element, x, doc_element, raw_indent, previous_indent)
54
+
55
+ indent = @indent == true ? (raw_indent + ' ') : ''
56
+ doc_element.add(REXML::Text.new(indent + x.to_s, raw=true)) if x.to_s.strip.length > 0
50
57
  end
51
58
 
52
- def read_raw_element(doc_node, x)
59
+ def read_raw_element(element, x, doc_element, indent, previous_indent)
60
+
53
61
  method_name = x.name.gsub(/-/,'_').to_sym
54
62
  if @xsl_methods.include? method_name then
55
63
 
56
- method(method_name).call(doc_node, x)
64
+ method(method_name).call(element, x, doc_element, indent, previous_indent)
57
65
  else
58
66
 
59
67
  if x.has_elements? then
60
- element = "<%s>%%s</%s>" % ([x.name.to_s] * 2)
61
- k = element % read_node(x, doc_node).flatten.join
62
- #puts 'k : ' + k.inspect
63
- k
64
- else
65
- x.to_s
68
+
69
+ new_element = Element.new x.name.to_s
70
+
71
+ previous_indent = indent.clone
72
+ indent = indent_before(element, x, doc_element, indent, previous_indent) if @indent == true
73
+
74
+ doc_element.add new_element
75
+ read_node(x, element, new_element, indent.clone, previous_indent.clone)
76
+
77
+ indent_after(element, x, doc_element, indent, previous_indent) if @indent == true
78
+
79
+ else
80
+ doc_element.add Document.new(x.to_s)
81
+
66
82
  end
67
83
  end
68
84
  end
69
85
 
70
- def apply_templates(doc_node, x)
86
+ def apply_templates(element, x, doc_element, indent, previous_indent)
87
+
71
88
  field = x.attribute('select').value.to_s
72
- XPath.match(doc_node, field).map do |x|
73
- read_node @templates[field], x
89
+ XPath.match(element, field).each do |x|
90
+ read_node @templates[field], x, doc_element, indent, previous_indent
74
91
  end
75
92
  end
76
93
 
77
- def value_of(doc_node, x)
94
+ def value_of(element, x, doc_element, indent, previous_indent)
95
+
78
96
  field = x.attribute('select').value.to_s
79
- doc_node.text(field)
97
+ o = element.text(field)
98
+ doc_element.add REXML::Text.new(o.to_s)
99
+
80
100
  end
81
101
 
82
- def element(doc_node, x)
83
- name = x.attribute('name').value.to_s
84
- element = "<%s>%%s</%s>" % ([name] * 2)
85
- r = element % (read_node(x, doc_node).flatten.join)
86
- #puts 'r : ' + r.inspect
87
- r
102
+ def element(element, x, doc_element, indent, previous_indent)
103
+
104
+ name = x.attribute('name').value.to_s
105
+ new_element = Element.new name
106
+ doc_element.add new_element
107
+ read_node(x, element, new_element, indent, previous_indent)
88
108
  end
89
109
 
90
- def if(doc_node, x)
110
+ def if(element, x, doc_element, indent, previous_indent)
111
+
91
112
  condition = x.attribute('test').value.to_s
92
- node = XPath.first(doc_node, condition)
93
- read_node(x, doc_node).flatten.join if node and node == true
113
+ node = XPath.first(element, condition)
114
+ read_node(x, element, doc_element, indent, previous_indent) if node and node == true
94
115
  end
95
116
 
96
- def choose(doc_node, x)
117
+ def choose(element, x, doc_element, indent, previous_indent)
97
118
 
98
119
  #get the when clause
99
- nodes = XPath.match(x, "xsl:when")
100
-
101
- r = nodes.map do |xsl_node|
102
120
 
121
+ r = XPath.match(x, "xsl:when").map do |xsl_node|
103
122
  condition = xsl_node.attribute('test').value.to_s
104
- node = XPath.first(doc_node, condition)
105
-
106
- if node and node == true then
107
- read_node(xsl_node, doc_node).flatten.join
123
+ node = XPath.first(element, condition)
124
+ if node and node == true
125
+ read_node(xsl_node, element, doc_element, indent, previous_indent)
126
+ true
108
127
  else
109
- nil
128
+ false
110
129
  end
111
130
  end
112
131
 
113
- if r.compact.length <= 0 then
114
- xsl_node = XPath.first(x, 'xsl:otherwise')
115
- r = read_node(xsl_node, doc_node).flatten.join if xsl_node
132
+ unless r.any? then
133
+ node = XPath.first(x, 'xsl:otherwise')
134
+ read_node(node, element, doc_element, indent, previous_indent) if node
135
+ end
136
+
137
+ end
138
+
139
+ def copy_of(element, x, doc_element, indent, previous_indent)
140
+
141
+ indent_element(element, x, doc_element, indent, previous_indent) do
142
+ doc_element.add element
143
+ end
144
+
145
+ end
146
+
147
+ def indent_before(element, x, doc_element, indent, previous_indent)
148
+ text = ''
149
+ unless doc_element.texts.empty? and doc_element.texts.last.nil? then
150
+ text = indent unless doc_element.texts.last.to_s[/^\n\s/m]
151
+ else
152
+ text = "\n" + indent
116
153
  end
154
+ (doc_element.add REXML::Text.new text, raw=true) if text
155
+ indent += ' '
156
+ end
157
+
158
+ def indent_after(element, x, doc_element, indent, previous_indent)
159
+ if @indent == true then
160
+ doc_element.add REXML::Text.new "\n" + previous_indent[0..-3], raw=true
161
+ end
162
+ end
163
+
164
+ def indent_element(element, x, doc_element, indent, previous_indent)
165
+ indent_before(element, x, doc_element, indent, previous_indent) if @indent == true
166
+ yield
167
+ indent_after(element, x, doc_element, indent, previous_indent) if @indent == true
168
+ end
169
+
170
+ def attribute(element, x, doc_element, indent, previous_indent)
117
171
 
118
- r
172
+ name = x.attribute('name').value
173
+ value = x.text.to_s
174
+ doc_element.add_attribute name, value
119
175
  end
120
- end
176
+
177
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rexslt
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.3
5
+ version: 0.1.4
6
6
  platform: ruby
7
7
  authors: []
8
8
 
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-07 00:00:00 +01:00
13
+ date: 2011-04-13 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies: []
16
16