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.
- data/lib/rexslt.rb +116 -59
- 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
|
-
@
|
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
|
-
|
23
|
-
|
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()
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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,
|
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.
|
40
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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(
|
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(
|
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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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(
|
86
|
+
def apply_templates(element, x, doc_element, indent, previous_indent)
|
87
|
+
|
71
88
|
field = x.attribute('select').value.to_s
|
72
|
-
XPath.match(
|
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(
|
94
|
+
def value_of(element, x, doc_element, indent, previous_indent)
|
95
|
+
|
78
96
|
field = x.attribute('select').value.to_s
|
79
|
-
|
97
|
+
o = element.text(field)
|
98
|
+
doc_element.add REXML::Text.new(o.to_s)
|
99
|
+
|
80
100
|
end
|
81
101
|
|
82
|
-
def element(
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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(
|
110
|
+
def if(element, x, doc_element, indent, previous_indent)
|
111
|
+
|
91
112
|
condition = x.attribute('test').value.to_s
|
92
|
-
node = XPath.first(
|
93
|
-
read_node(x,
|
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(
|
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(
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
128
|
+
false
|
110
129
|
end
|
111
130
|
end
|
112
131
|
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
172
|
+
name = x.attribute('name').value
|
173
|
+
value = x.text.to_s
|
174
|
+
doc_element.add_attribute name, value
|
119
175
|
end
|
120
|
-
|
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.
|
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-
|
13
|
+
date: 2011-04-13 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|