oxmlrpc 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/oxmlrpc.rb +2 -0
- data/lib/oxmlrpc/parser.rb +64 -0
- data/lib/oxmlrpc/serializer.rb +95 -0
- data/spec/parser_spec.rb +220 -0
- data/spec/serializer_spec.rb +47 -0
- data/spec/spec_helper.rb +6 -0
- metadata +84 -0
data/lib/oxmlrpc.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module OXMLRPC
|
4
|
+
class Parser < ::Ox::Sax
|
5
|
+
|
6
|
+
attr_reader :rpc_method, :params
|
7
|
+
|
8
|
+
def self.parse(xml)
|
9
|
+
parser = self.new
|
10
|
+
Ox.sax_parse(parser, StringIO.new(xml))
|
11
|
+
parser
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@elements = []
|
16
|
+
@rpc_method = nil
|
17
|
+
@params = []
|
18
|
+
@array_mode = false
|
19
|
+
@struct_mode = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_element(name)
|
23
|
+
@elements << name
|
24
|
+
|
25
|
+
if :array == name
|
26
|
+
@array_mode = true
|
27
|
+
@params << Array.new
|
28
|
+
end
|
29
|
+
|
30
|
+
if :struct == name
|
31
|
+
@struct_mode = true
|
32
|
+
@params << Hash.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def end_element(name)
|
37
|
+
@array_mode = false if :array == name
|
38
|
+
@struct_mode = false if :struct == name
|
39
|
+
|
40
|
+
raise "Invalid XML" unless @elements.pop == name
|
41
|
+
end
|
42
|
+
|
43
|
+
def text(value)
|
44
|
+
@rpc_method = value if :methodName == @elements.last
|
45
|
+
@params.last[value] = nil if :name == @elements.last && @struct_mode
|
46
|
+
|
47
|
+
add_to_params value == 1 || value == "1" if :boolean == @elements.last
|
48
|
+
add_to_params value if [:value, :string].include?(@elements.last)
|
49
|
+
add_to_params Integer(value) if [:int, :i4].include?(@elements.last)
|
50
|
+
add_to_params Float(value) if :double == @elements.last
|
51
|
+
add_to_params Time.parse(value) if :'dateTime.iso8601' == @elements.last
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_to_params(value)
|
55
|
+
if @array_mode
|
56
|
+
@params.last << value
|
57
|
+
elsif @struct_mode
|
58
|
+
@params.last[@params.last.keys.last] = value
|
59
|
+
else
|
60
|
+
@params << value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module OXMLRPC
|
4
|
+
class Serializer
|
5
|
+
|
6
|
+
def self.serialize(data)
|
7
|
+
self.new(data).to_rpc
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(data = {})
|
11
|
+
@data = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_rpc
|
15
|
+
doc = Ox::Document.new(:version => '1.0')
|
16
|
+
doc << mr = Ox::Element.new('methodResponse')
|
17
|
+
mr << params = Ox::Element.new('params')
|
18
|
+
params << param = Ox::Element.new('param')
|
19
|
+
param << serialize(@data)
|
20
|
+
Ox.dump(doc, :indent => -1)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def serialize(sth)
|
26
|
+
case sth
|
27
|
+
when String then serialize_string(sth)
|
28
|
+
when Integer then serialize_integer(sth)
|
29
|
+
when Hash then serialize_hash(sth)
|
30
|
+
when Array then serialize_array(sth)
|
31
|
+
when Float then serialize_double(sth)
|
32
|
+
when TrueClass then serialize_boolean(true)
|
33
|
+
when FalseClass then serialize_boolean(false)
|
34
|
+
when Time then serialize_time(sth)
|
35
|
+
else
|
36
|
+
raise "Uknkown type"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def serialize_hash(hash)
|
41
|
+
value = Ox::Element.new('value')
|
42
|
+
value << struct = Ox::Element.new('struct')
|
43
|
+
hash.each do |key, value|
|
44
|
+
struct << member = Ox::Element.new('member')
|
45
|
+
member << (Ox::Element.new('name') << key.to_s)
|
46
|
+
member << serialize(value)
|
47
|
+
end
|
48
|
+
value
|
49
|
+
end
|
50
|
+
|
51
|
+
def serialize_array(arr)
|
52
|
+
value = Ox::Element.new('value')
|
53
|
+
value << array = Ox::Element.new('array')
|
54
|
+
array << data = Ox::Element.new('data')
|
55
|
+
arr.each do |element|
|
56
|
+
data << serialize(element)
|
57
|
+
end
|
58
|
+
value
|
59
|
+
end
|
60
|
+
|
61
|
+
def serialize_string(string)
|
62
|
+
value = Ox::Element.new('value')
|
63
|
+
value << string
|
64
|
+
value
|
65
|
+
end
|
66
|
+
|
67
|
+
def serialize_integer(integer)
|
68
|
+
value = Ox::Element.new('value')
|
69
|
+
value << int = Ox::Element.new('int')
|
70
|
+
int << integer.to_s
|
71
|
+
value
|
72
|
+
end
|
73
|
+
|
74
|
+
def serialize_double(float)
|
75
|
+
value = Ox::Element.new('value')
|
76
|
+
value << double = Ox::Element.new('double')
|
77
|
+
double << float.to_s
|
78
|
+
value
|
79
|
+
end
|
80
|
+
|
81
|
+
def serialize_boolean(boolean)
|
82
|
+
value = Ox::Element.new('value')
|
83
|
+
value << bool = Ox::Element.new('boolean')
|
84
|
+
bool << (boolean ? "1" : "0")
|
85
|
+
value
|
86
|
+
end
|
87
|
+
|
88
|
+
def serialize_time(time)
|
89
|
+
value = Ox::Element.new('value')
|
90
|
+
value << td = Ox::Element.new('dateTime.iso8601')
|
91
|
+
td << time.strftime("%Y%m%dT%H:%M:%S")
|
92
|
+
value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe OXMLRPC::Parser do
|
4
|
+
it 'should parse simple request with <int> value' do
|
5
|
+
xml_request = %{
|
6
|
+
<?xml version="1.0"?>
|
7
|
+
<methodCall>
|
8
|
+
<methodName>examples.getStateName</methodName>
|
9
|
+
<params>
|
10
|
+
<param>
|
11
|
+
<value><int>41</int></value>
|
12
|
+
</param>
|
13
|
+
</params>
|
14
|
+
</methodCall>
|
15
|
+
}
|
16
|
+
|
17
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
18
|
+
|
19
|
+
request.rpc_method.should eq "examples.getStateName"
|
20
|
+
request.params.should eq [41]
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should parse simple request with <i4> value' do
|
24
|
+
xml_request = %{
|
25
|
+
<?xml version="1.0"?>
|
26
|
+
<methodCall>
|
27
|
+
<methodName>examples.getStateName</methodName>
|
28
|
+
<params>
|
29
|
+
<param>
|
30
|
+
<value><i4>41</i4></value>
|
31
|
+
</param>
|
32
|
+
</params>
|
33
|
+
</methodCall>
|
34
|
+
}
|
35
|
+
|
36
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
37
|
+
|
38
|
+
request.rpc_method.should eq "examples.getStateName"
|
39
|
+
request.params.should eq [41]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should parse simple request with <string> value' do
|
43
|
+
xml_request = %{
|
44
|
+
<?xml version="1.0"?>
|
45
|
+
<methodCall>
|
46
|
+
<methodName>examples.getStateName</methodName>
|
47
|
+
<params>
|
48
|
+
<param>
|
49
|
+
<value><string>41</string></value>
|
50
|
+
</param>
|
51
|
+
</params>
|
52
|
+
</methodCall>
|
53
|
+
}
|
54
|
+
|
55
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
56
|
+
|
57
|
+
request.rpc_method.should eq "examples.getStateName"
|
58
|
+
request.params.should eq ["41"]
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should parse simple request with <empty> value' do
|
62
|
+
xml_request = %{
|
63
|
+
<?xml version="1.0"?>
|
64
|
+
<methodCall>
|
65
|
+
<methodName>examples.getStateName</methodName>
|
66
|
+
<params>
|
67
|
+
<param>
|
68
|
+
<value>41</value>
|
69
|
+
</param>
|
70
|
+
</params>
|
71
|
+
</methodCall>
|
72
|
+
}
|
73
|
+
|
74
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
75
|
+
|
76
|
+
request.rpc_method.should eq "examples.getStateName"
|
77
|
+
request.params.should eq ["41"]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should parse simple request with <int> values' do
|
81
|
+
xml_request = %{
|
82
|
+
<?xml version="1.0"?>
|
83
|
+
<methodCall>
|
84
|
+
<methodName>examples.getStateName</methodName>
|
85
|
+
<params>
|
86
|
+
<param>
|
87
|
+
<value><int>41</int></value>
|
88
|
+
</param>
|
89
|
+
<param>
|
90
|
+
<value><int>99</int></value>
|
91
|
+
</param>
|
92
|
+
</params>
|
93
|
+
</methodCall>
|
94
|
+
}
|
95
|
+
|
96
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
97
|
+
|
98
|
+
request.rpc_method.should eq "examples.getStateName"
|
99
|
+
request.params.should eq [41,99]
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should parse simple request with <bool> values' do
|
103
|
+
xml_request = %{
|
104
|
+
<?xml version="1.0"?>
|
105
|
+
<methodCall>
|
106
|
+
<methodName>examples.getStateName</methodName>
|
107
|
+
<params>
|
108
|
+
<param>
|
109
|
+
<value><boolean>0</boolean></value>
|
110
|
+
</param>
|
111
|
+
<param>
|
112
|
+
<value><boolean>1</boolean></value>
|
113
|
+
</param>
|
114
|
+
</params>
|
115
|
+
</methodCall>
|
116
|
+
}
|
117
|
+
|
118
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
119
|
+
|
120
|
+
request.rpc_method.should eq "examples.getStateName"
|
121
|
+
request.params.should eq [false,true]
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should parse simple request with <double> values' do
|
125
|
+
xml_request = %{
|
126
|
+
<?xml version="1.0"?>
|
127
|
+
<methodCall>
|
128
|
+
<methodName>examples.getStateName</methodName>
|
129
|
+
<params>
|
130
|
+
<param>
|
131
|
+
<value><double>-12.214</double></value>
|
132
|
+
</param>
|
133
|
+
</params>
|
134
|
+
</methodCall>
|
135
|
+
}
|
136
|
+
|
137
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
138
|
+
|
139
|
+
request.rpc_method.should eq "examples.getStateName"
|
140
|
+
request.params.should eq [-12.214]
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should parse simple request with <dateTime> values' do
|
144
|
+
xml_request = %{
|
145
|
+
<?xml version="1.0"?>
|
146
|
+
<methodCall>
|
147
|
+
<methodName>examples.getStateName</methodName>
|
148
|
+
<params>
|
149
|
+
<param>
|
150
|
+
<value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value>
|
151
|
+
</param>
|
152
|
+
</params>
|
153
|
+
</methodCall>
|
154
|
+
}
|
155
|
+
|
156
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
157
|
+
|
158
|
+
request.rpc_method.should eq "examples.getStateName"
|
159
|
+
request.params.should eq [Time.parse("19980717T14:08:55")]
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should parse simple request with <array> values' do
|
163
|
+
xml_request = %{
|
164
|
+
<?xml version="1.0"?>
|
165
|
+
<methodCall>
|
166
|
+
<methodName>examples.getStateName</methodName>
|
167
|
+
<params>
|
168
|
+
<param>
|
169
|
+
<value>
|
170
|
+
<array>
|
171
|
+
<data>
|
172
|
+
<value><int>12</int></value>
|
173
|
+
<value><string>Egypt</string></value>
|
174
|
+
<value><boolean>0</boolean></value>
|
175
|
+
<value><i4>-31</i4></value>
|
176
|
+
</data>
|
177
|
+
</array>
|
178
|
+
</value>
|
179
|
+
</param>
|
180
|
+
</params>
|
181
|
+
</methodCall>
|
182
|
+
}
|
183
|
+
|
184
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
185
|
+
|
186
|
+
request.rpc_method.should eq "examples.getStateName"
|
187
|
+
request.params.should eq [[12,"Egypt", false, -31]]
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'should parse simple request with <struct> values' do
|
191
|
+
xml_request = %{
|
192
|
+
<?xml version="1.0"?>
|
193
|
+
<methodCall>
|
194
|
+
<methodName>examples.getStateName</methodName>
|
195
|
+
<params>
|
196
|
+
<param>
|
197
|
+
<value>
|
198
|
+
<struct>
|
199
|
+
<member>
|
200
|
+
<name>lowerBound</name>
|
201
|
+
<value><i4>18</i4></value>
|
202
|
+
</member>
|
203
|
+
<member>
|
204
|
+
<name>upperBound</name>
|
205
|
+
<value><i4>139</i4></value>
|
206
|
+
</member>
|
207
|
+
</struct>
|
208
|
+
</value>
|
209
|
+
</param>
|
210
|
+
</params>
|
211
|
+
</methodCall>
|
212
|
+
}
|
213
|
+
|
214
|
+
request = OXMLRPC::Parser.parse(xml_request)
|
215
|
+
|
216
|
+
request.rpc_method.should eq "examples.getStateName"
|
217
|
+
request.params.should eq [{"lowerBound" => 18, "upperBound" => 139}]
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe OXMLRPC::Serializer do
|
4
|
+
it 'should serialize <int> value' do
|
5
|
+
OXMLRPC::Serializer.serialize(12).chomp
|
6
|
+
.should eq "<methodResponse><params><param><value><int>12</int></value></param></params></methodResponse>"
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should serialize <string> value' do
|
10
|
+
OXMLRPC::Serializer.serialize("hello").chomp
|
11
|
+
.should eq "<methodResponse><params><param><value>hello</value></param></params></methodResponse>"
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should serialize <boolean> value' do
|
15
|
+
OXMLRPC::Serializer.serialize(true).chomp
|
16
|
+
.should eq "<methodResponse><params><param><value><boolean>1</boolean></value></param></params></methodResponse>"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should serialize <double> value' do
|
20
|
+
OXMLRPC::Serializer.serialize(-12.45).chomp
|
21
|
+
.should eq "<methodResponse><params><param><value><double>-12.45</double></value></param></params></methodResponse>"
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should serialize <dateTime.iso8601> value' do
|
25
|
+
OXMLRPC::Serializer.serialize(Time.parse("19980717T14:08:55")).chomp
|
26
|
+
.should eq "<methodResponse><params><param><value><dateTime.iso8601>19980717T14:08:55</dateTime.iso8601></value></param></params></methodResponse>"
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should serialize <struct> value' do
|
30
|
+
OXMLRPC::Serializer.serialize({:x => 2, :y => "z"}).chomp
|
31
|
+
.should eq "<methodResponse><params><param><value><struct><member><name>x</name><value><int>2</int></value></member><member><name>y</name><value>z</value></member></struct></value></param></params></methodResponse>"
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should serialize <array> value' do
|
35
|
+
OXMLRPC::Serializer.serialize([12, "test"]).chomp
|
36
|
+
.should eq "<methodResponse><params><param><value><array><data><value><int>12</int></value><value>test</value></data></array></value></param></params></methodResponse>"
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should serialize <exception> value' do
|
40
|
+
pending
|
41
|
+
OXMLRPC::Serializer.serialize(StandardError.new("something wrong")).chomp
|
42
|
+
.should eq ""
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oxmlrpc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- fazibear
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ox
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Simple, lightweight and fast XML-RPC client library for ruby based on
|
47
|
+
OX XML parser.
|
48
|
+
email: fazibear@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/oxmlrpc.rb
|
54
|
+
- lib/oxmlrpc/parser.rb
|
55
|
+
- lib/oxmlrpc/serializer.rb
|
56
|
+
- spec/parser_spec.rb
|
57
|
+
- spec/serializer_spec.rb
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
homepage: http://github.com/fazibear/oxmlrpc
|
60
|
+
licenses: []
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.8.23
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Fast and simple XML-RPC Client
|
83
|
+
test_files: []
|
84
|
+
has_rdoc:
|