rexslt 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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