libxml-xmlrpc 0.1.0

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.
@@ -0,0 +1,18 @@
1
+ require 'xml/libxml/xmlrpc/client'
2
+ require 'xml/libxml/xmlrpc/parser'
3
+ require 'xml/libxml/xmlrpc/builder'
4
+
5
+ module XML
6
+ #
7
+ # XML::XMLRPC -- LibXML interface to XML-RPC
8
+ #
9
+ # Right now, look at XML::XMLRPC::Parser, XML::XMLRPC::Builder
10
+ # and XML::XMLRPC::Client for docs
11
+ #
12
+ # Author:: Erik Hollensbe <erik@hollensbe.org>
13
+ #
14
+
15
+ module XMLRPC
16
+ VERSION = "0.1.0"
17
+ end
18
+ end
@@ -0,0 +1,228 @@
1
+ require 'base64'
2
+
3
+ module XML
4
+ module XMLRPC
5
+ #
6
+ # Class to build XML-RPC responses and calls.
7
+ #
8
+ # Example:
9
+ #
10
+ # XML::XMLRPC::Builder.foo(1,2,3) # generates xml for method call
11
+ # # 'foo' with arguments of int 1, 2
12
+ # # and 3
13
+ #
14
+ # XML::XMLRPC::Builder.response(1,2,3) # builds a response with args
15
+ # # 1,2,3
16
+ #
17
+ # # builds a fault response with faultCode 0 and faultString "Foo"
18
+ # XML::XMLRPC::Builder.fault_response(2, "Foo")
19
+ #
20
+ # # builds a call called 'fault_response'
21
+ # XML::XMLRPC::Builder.call('fault_response', 1, 2, 3)
22
+ #
23
+ # Notes:
24
+ # * To build a Base64 object, check out the XML::XMLRPC::Builder::Base64 class.
25
+ # * Date (and all other) objects must inherit directly from class
26
+ # Date or be the class themselves, DateTime is an example of direct
27
+ # inheritance of Date. Time (which inherits from Object) will NOT
28
+ # work.
29
+ # * All responses are encoded UTF-8. Be sure your strings, etc are
30
+ # UTF-8 before passing them into this module.
31
+ #
32
+ module Builder
33
+ #
34
+ # Builds the appropriate XML for a methodCall.
35
+ #
36
+ # Takes a methodname and a series of arguments.
37
+ #
38
+ def self.call(methodname, *args)
39
+ methodname = methodname.to_s
40
+
41
+ output = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
42
+ output += "<methodCall><methodName>#{methodname}</methodName>"
43
+ output += Value.generate(*args)
44
+ output += "</methodCall>"
45
+
46
+ return output
47
+ end
48
+
49
+ #
50
+ # Builds a response. Takes a series of response arguments.
51
+ #
52
+ def self.response(*args)
53
+ output = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
54
+ output += "<methodResponse>"
55
+ output += Value.generate(*args)
56
+ output += "</methodResponse>"
57
+
58
+ end
59
+
60
+ #
61
+ # Builds a fault response. Takes a faultCode (integer) and a faultMessage (string).
62
+ #
63
+ def self.fault_response(faultCode, faultMessage)
64
+ output = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
65
+ output += "<methodResponse>"
66
+ output += "<fault><value><struct>"
67
+ output += "<member><name>faultCode</name><value><int>#{faultCode}</int></value></member>"
68
+ output += "<member><name>faultString</name><value><string>#{faultMessage}</string></value></member>"
69
+ output += "</struct></value></fault>"
70
+ output += "</methodResponse>"
71
+ end
72
+
73
+ #
74
+ # Just calls #call, your method name will be the first argument and
75
+ # will be passed to call properly.
76
+ #
77
+ def self.method_missing(*args)
78
+ self.call(*args)
79
+ end
80
+ end
81
+
82
+ #
83
+ # Thrown when Builder encounters an error.
84
+ #
85
+ class Builder::Error < Exception
86
+ end
87
+
88
+ #
89
+ # Base64 type class. The 'Base64' module that comes with ruby does not
90
+ # hold anything (it's not a class), and since our parser depends on
91
+ # having the appropriate type to generate the right value clause, this
92
+ # is required for Base64 transfers.
93
+ #
94
+ class Builder::Base64
95
+
96
+ #
97
+ # Takes a string.
98
+ #
99
+ def initialize(str)
100
+ @string = str
101
+ end
102
+
103
+ #
104
+ # Encodes the encapsulated string as Base64.
105
+ #
106
+ def encode
107
+ ::Base64.encode64(@string)
108
+ end
109
+ end
110
+
111
+ #
112
+ # Generates Values. This has several subclasses that map to
113
+ # core types which I will not document.
114
+ #
115
+ # RTFS.
116
+ #
117
+
118
+ module Builder::Value
119
+
120
+ def self.generate(*args)
121
+ output = "<params>"
122
+ args.each do |x|
123
+ output += "<param>"
124
+ output += self.generate_value(x)
125
+ output += "</param>"
126
+ end
127
+ output += "</params>"
128
+
129
+ return output
130
+ end
131
+
132
+ def self.generate_value(arg)
133
+ output = "<value>"
134
+
135
+ # try the superclass if the class doesn't work (this isn't
136
+ # perfect but is better than nothing)
137
+ if arg.class == Builder::Base64
138
+ output += Base64.generate(arg)
139
+ elsif const_get(arg.class.to_s).respond_to? :generate
140
+ output += const_get(arg.class.to_s).generate(arg)
141
+ elsif const_get(arg.class.superclass.to_s).respond_to? :generate
142
+ output += const_get(arg.class.superclass.to_s).generate(arg)
143
+ else
144
+ raise Builder::Error, "Type '#{arg.class}' is not supported by XML-RPC"
145
+ end
146
+
147
+ output += "</value>"
148
+
149
+ return output
150
+ end
151
+
152
+ module Base64
153
+ def self.generate(arg)
154
+ "<base64>#{arg.encode}</base64>"
155
+ end
156
+ end
157
+
158
+ module Fixnum
159
+ def self.generate(arg)
160
+ "<int>#{arg}</int>"
161
+ end
162
+ end
163
+
164
+ module String
165
+ def self.generate(arg)
166
+ "<string>#{arg}</string>"
167
+ end
168
+ end
169
+
170
+ module Float
171
+ def self.generate(arg)
172
+ "<double>#{arg}</double>"
173
+ end
174
+ end
175
+
176
+ module Date
177
+ def self.generate(arg)
178
+ "<dateTime.iso8601>" + arg.strftime("%Y%m%dT%T") + "</dateTime.iso8601>"
179
+ end
180
+ end
181
+
182
+ module Array
183
+ def self.generate(args)
184
+ output = "<array><data>"
185
+ args.each do |x|
186
+ output += Builder::Value.generate_value(x)
187
+ end
188
+ output += "</data></array>"
189
+
190
+ return output
191
+ end
192
+ end
193
+
194
+ module Hash
195
+ def self.generate(args)
196
+ output = "<struct>"
197
+ args.each_key do |key|
198
+ output += "<member>"
199
+ output += "<name>#{key}</name>"
200
+ output += Builder::Value.generate_value(args[key])
201
+ output += "</member>"
202
+ end
203
+ output += "</struct>"
204
+ return output
205
+ end
206
+ end
207
+
208
+ module TrueClass
209
+ def self.generate(arg)
210
+ "<boolean>1</boolean>"
211
+ end
212
+ end
213
+
214
+ module FalseClass
215
+ def self.generate(arg)
216
+ "<boolean>0</boolean>"
217
+ end
218
+ end
219
+
220
+ module NilClass
221
+ def self.generate(arg)
222
+ # nil is treated as false in our spec
223
+ FalseClass.generate(arg)
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,44 @@
1
+ require 'xml/libxml/xmlrpc/parser'
2
+ require 'xml/libxml/xmlrpc/builder'
3
+
4
+ module XML
5
+ module XMLRPC
6
+ #
7
+ # Client is an easy-to-use XML-RPC method call and response mechanism.
8
+ #
9
+ # It will not handle redirection.
10
+ #
11
+ class Client
12
+ #
13
+ # Given an unused Net::HTTP object and a relative URL, it will post
14
+ # the XML-RPC information to this form after calling a method with
15
+ # ruby types.
16
+ #
17
+ # See XML::XMLRPC::Builder for caveats related to Base64 handling.
18
+ #
19
+ def initialize(http, url)
20
+ @http = http
21
+ @url = url
22
+ end
23
+
24
+ #
25
+ # See #call.
26
+ #
27
+ def method_missing(*args)
28
+ self.call(*args)
29
+ end
30
+
31
+ #
32
+ # Call and recieve the response. Returns a XML::XMLRPC::Parser object.
33
+ #
34
+ # Will throw an XML::XMLRPC::RemoteCallError if the call returns a
35
+ # fault response.
36
+ #
37
+ def call(methodName, *args)
38
+ res = @http.post(@url, XML::XMLRPC::Builder.call(methodName, *args))
39
+ res_args = XML::XMLRPC::Parser.new(res.body)
40
+ return res_args
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,259 @@
1
+ require 'xml/libxml'
2
+ require 'base64'
3
+ require 'date'
4
+ require 'stringio'
5
+
6
+ module XML::XMLRPC
7
+ class RemoteCallError < Exception
8
+ end
9
+ class ParserError < Exception
10
+ end
11
+
12
+ #
13
+ # Spec-compliant XML-RPC parser. Converts XML-RPC types to native Ruby
14
+ # types.
15
+ #
16
+ # _Overview_:
17
+ # <?xml version="1.0"?>
18
+ # <methodResponse>
19
+ # <params>
20
+ # <param>
21
+ # <value><string>South Dakota</string></value>
22
+ # </param>
23
+ # </params>
24
+ # </methodResponse>
25
+ #
26
+ # xml = XML::XMLRPC::Parser.new(IO or String object)
27
+ # xml[0] == "South Dakota"
28
+ #
29
+ # Notes:
30
+ # * Structs and Arrays are Hashes and Arrays respectively.
31
+ # * Base64 is auto-decoded.
32
+ # * Any interpreter-level (as opposed to syntax-level or exception
33
+ # handling) crash you see in ruby is the fault of libxml, not this code.
34
+ # * In a case where you're parsing a methodCall request, the method
35
+ # attribute will have data. In the case where you parse a response, method
36
+ # will be nil.
37
+ #
38
+ class Parser
39
+
40
+ include Enumerable
41
+
42
+ attr_reader :params
43
+ attr_reader :method
44
+
45
+ #
46
+ # Takes a String or IO object, which contains a response or call.
47
+ #
48
+ # Parses the document immediately.
49
+ #
50
+ def initialize(io)
51
+ @string = ""
52
+
53
+ if io.kind_of? String
54
+ @string = io
55
+ elsif io.kind_of? IO or io.kind_of? StringIO # stupid StringIO
56
+ @string = io.read
57
+ else
58
+ raise ParserError, "Argument to new must be String or IO"
59
+ end
60
+
61
+ @params = []
62
+ @method = nil
63
+ self.parse!
64
+
65
+ @params.freeze
66
+ @method.freeze
67
+ end
68
+
69
+ #
70
+ # Parses the document. Should not be required -- Parser#new already
71
+ # does this for you.
72
+ #
73
+ def parse!
74
+ document = XML::Parser.string(@string).parse
75
+ node = document.root
76
+ case node.name
77
+ when "methodCall"
78
+ @method, @params = Parser::Call.parse(node)
79
+ when "methodResponse"
80
+ @params = Parser::Response.parse(node)
81
+ else
82
+ raise ParserError, "XMLRPC is invalid - no call or response"
83
+ end
84
+ end
85
+
86
+ #
87
+ # Obtain param x, where x is an integer.
88
+ #
89
+ # Same as:
90
+ #
91
+ # xml.params[x]
92
+ #
93
+ def [](x)
94
+ @params[x]
95
+ end
96
+
97
+ #
98
+ # Iterate over each parameter.
99
+ #
100
+
101
+ def each
102
+ @params.each do |x|
103
+ yield x
104
+ end
105
+ end
106
+ end
107
+
108
+ #
109
+ # Parse a methodCall.
110
+ #
111
+
112
+ module Parser::Call
113
+ def self.parse(node)
114
+ method = node.find('/methodCall/methodName')
115
+ methodname = "unknown"
116
+ if method and method[0]
117
+ content = method[0].content
118
+ methodname = content
119
+ end
120
+
121
+ values = node.find('/methodCall/params/param/value')
122
+
123
+ parsed_params = Parser::ValueParser.parse(values)
124
+
125
+ return methodname, parsed_params
126
+ end
127
+ end
128
+
129
+ #
130
+ # Parse a methodResponse
131
+ #
132
+
133
+ class Parser::Response
134
+ def self.parse(node)
135
+ node.each_child do |child_node|
136
+ case child_node.name.downcase
137
+ when 'fault'
138
+ # RPC call has returned an error - find the fault and GTFO
139
+ value = Parser::ValueParser.parse(node.find('/methodResponse/fault/value'))
140
+ raise RemoteCallError, value[0][:faultCode].to_s + ": " + value[0][:faultString]
141
+ when 'params'
142
+ return Parser::ValueParser.parse(node.find('/methodResponse/params/param/value'))
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ #
149
+ # Parse values from a XML::Node::Set or Array of XML::Node objects.
150
+ #
151
+ # May be called recursively by ValueParser::Array or ValueParser::Struct.
152
+ #
153
+
154
+ module Parser::ValueParser
155
+ def self.parse(values)
156
+ parsed_params = []
157
+
158
+ values.each do |param_value_node|
159
+ value = nil
160
+ if param_value_node
161
+ param_value_node.each_child do |type|
162
+ value = case type.name.downcase
163
+ when /^(?:i4|int)$/
164
+ type.content.strip.to_i
165
+ when 'string'
166
+ type.content
167
+ when 'boolean'
168
+ if type.content.strip.to_i == 1
169
+ true
170
+ else
171
+ false
172
+ end
173
+ when 'double'
174
+ type.content.strip.to_f
175
+ when 'datetime.iso8601'
176
+ # Looks like this: 19980717T14:08:55
177
+ DateTime.strptime(type.content.strip, "%Y%m%dT%T")
178
+ when 'base64'
179
+ Base64.decode64(type.content.strip)
180
+ when 'struct'
181
+ Parser::ValueParser::Struct.parse(type)
182
+ when 'array'
183
+ Parser::ValueParser::Array.parse(type)
184
+ end
185
+
186
+ break if value
187
+ end
188
+ end
189
+ parsed_params.push value
190
+ end
191
+
192
+ return parsed_params
193
+ end
194
+ end
195
+
196
+ #
197
+ # Parse a 'struct' type.
198
+ #
199
+
200
+ module Parser::ValueParser::Struct
201
+ def self.parse(node)
202
+ # convert it to a hash with symbols as keys first.
203
+
204
+ hash = { }
205
+
206
+ node.each_child do |child_node|
207
+ if child_node.name == "member"
208
+ name = nil
209
+ value = nil
210
+
211
+ child_node.each_child do |member_node|
212
+ if member_node.name == "name"
213
+ name = member_node.content.strip.to_sym
214
+ if value
215
+ hash[name] = value
216
+ break
217
+ end
218
+ elsif member_node.name == "value"
219
+ value = Parser::ValueParser.parse([member_node])[0]
220
+ if name
221
+ hash[name] = value
222
+ break
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+
229
+ return hash
230
+ end
231
+ end
232
+
233
+ #
234
+ # Parse an 'array' type.
235
+ #
236
+
237
+ module Parser::ValueParser::Array
238
+ def self.parse(node)
239
+
240
+ value = []
241
+
242
+ node.each_child do |child_node|
243
+ if child_node.name == "data"
244
+ value_nodes = []
245
+ child_node.each_child do |value_node|
246
+ if value_node.name == "value"
247
+ value_nodes.push value_node
248
+ end
249
+ end
250
+
251
+ value = Parser::ValueParser.parse(value_nodes)
252
+ break # yes, first hit is last hit, so says the stay-puff't spec.
253
+ end
254
+ end
255
+
256
+ return value
257
+ end
258
+ end
259
+ end # fin.
@@ -0,0 +1,92 @@
1
+ require 'test/unit'
2
+ require 'xml/libxml/xmlrpc/builder'
3
+ require 'xml/libxml/xmlrpc/parser'
4
+
5
+ class TestBuilder < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @class = XML::XMLRPC::Builder
9
+ end
10
+
11
+ def test_call
12
+ # ugh. these sure are ugly.
13
+ assert_equal(@class.foo,
14
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params></params></methodCall>")
15
+ assert_equal(@class.bar,
16
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>bar</methodName><params></params></methodCall>")
17
+ assert_equal(@class.foo(1),
18
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><int>1</int></value></param></params></methodCall>")
19
+ assert_equal(@class.foo(1,2,3),
20
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><int>1</int></value></param><param><value><int>2</int></value></param><param><value><int>3</int></value></param></params></methodCall>")
21
+ assert_equal(@class.foo(nil),
22
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><boolean>0</boolean></value></param></params></methodCall>")
23
+ assert_equal(@class.foo(Date.civil(1978, 4, 6)),
24
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><dateTime.iso8601>19780406T00:00:00</dateTime.iso8601></value></param></params></methodCall>")
25
+ assert_equal(@class.foo([1,2,3]),
26
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><array><data><value><int>1</int></value><value><int>2</int></value><value><int>3</int></value></data></array></value></param></params></methodCall>")
27
+ assert_equal(@class.foo({:Bar => 1, :Foo => 2}),
28
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><struct><member><name>Bar</name><value><int>1</int></value></member><member><name>Foo</name><value><int>2</int></value></member></struct></value></param></params></methodCall>")
29
+ assert_equal(@class.foo(1, [1,2,3], {:Bar => 1, :Foo => 2}),
30
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><int>1</int></value></param><param><value><array><data><value><int>1</int></value><value><int>2</int></value><value><int>3</int></value></data></array></value></param><param><value><struct><member><name>Bar</name><value><int>1</int></value></member><member><name>Foo</name><value><int>2</int></value></member></struct></value></param></params></methodCall>")
31
+ assert_equal(@class.foo(XML::XMLRPC::Builder::Base64.new("foo")),
32
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodCall><methodName>foo</methodName><params><param><value><base64>Zm9v\n</base64></value></param></params></methodCall>")
33
+
34
+ # parse test. Our parser should be able to parse what we generate.
35
+
36
+ xml = XML::XMLRPC::Parser.new(@class.foo([1,2,3], { :Bar => 1, :Foo => 2 }, XML::XMLRPC::Builder::Base64.new("foo")))
37
+ assert_equal(xml[0], [1,2,3])
38
+ assert_equal(xml[1], { :Bar => 1, :Foo => 2})
39
+ assert_equal(xml[2], "foo")
40
+ assert_equal("foo", xml.method)
41
+
42
+ # response/fault call test
43
+
44
+ xml = XML::XMLRPC::Parser.new(@class.call('response', 1,2,3))
45
+ assert_equal(xml[0], 1)
46
+ assert_equal(xml[1], 2)
47
+ assert_equal(xml[2], 3)
48
+ assert_equal("response", xml.method)
49
+
50
+
51
+ xml = XML::XMLRPC::Parser.new(@class.call('fault_response', 1,2,3))
52
+ assert_equal(xml[0], 1)
53
+ assert_equal(xml[1], 2)
54
+ assert_equal(xml[2], 3)
55
+ assert_equal("fault_response", xml.method)
56
+ end
57
+
58
+ def test_response
59
+ assert_equal(@class.response,
60
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodResponse><params></params></methodResponse>")
61
+ assert_equal(@class.response(nil),
62
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodResponse><params><param><value><boolean>0</boolean></value></param></params></methodResponse>")
63
+ assert_equal(@class.fault_response(0, "foo"),
64
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<methodResponse><fault><value><struct><member><name>faultCode</name><value><int>0</int></value></member><member><name>faultString</name><value><string>foo</string></value></member></struct></value></fault></methodResponse>")
65
+
66
+ # parser test
67
+
68
+ xml = XML::XMLRPC::Parser.new(@class.response(1,2,3))
69
+ assert_equal(xml[0], 1)
70
+ assert_equal(xml[1], 2)
71
+ assert_equal(xml[2], 3)
72
+ assert_equal(xml.method, nil)
73
+
74
+ # test faults
75
+ assert_raise XML::XMLRPC::RemoteCallError do
76
+ xml = XML::XMLRPC::Parser.new(@class.fault_response(0, "Foo"))
77
+ end
78
+
79
+ e = nil
80
+
81
+ assert_nothing_raised do
82
+ begin
83
+ xml = XML::XMLRPC::Parser.new(@class.fault_response(0, "Foo"))
84
+ rescue XML::XMLRPC::RemoteCallError => error
85
+ e = error
86
+ end
87
+ end
88
+
89
+ assert_instance_of(XML::XMLRPC::RemoteCallError, e)
90
+ assert_equal(e.message, "0: Foo")
91
+ end
92
+ end
@@ -0,0 +1,119 @@
1
+ require 'test/unit'
2
+ require 'xml/libxml/xmlrpc/parser'
3
+ require 'stringio'
4
+
5
+ class TestParserGood < Test::Unit::TestCase
6
+ def test_constructor
7
+ assert_raise XML::XMLRPC::ParserError do
8
+ XML::XMLRPC::Parser.new(nil)
9
+ end
10
+
11
+ assert_nothing_raised do
12
+ XML::XMLRPC::Parser.new(File.open("test/data/big_call.xml"))
13
+ end
14
+
15
+ # should raise a LibXML error because there's nothing to parse
16
+ # XXX libxml no likey empty string.
17
+ assert_raise XML::Parser::ParseError do
18
+ XML::XMLRPC::Parser.new("asdf")
19
+ end
20
+ end
21
+
22
+ def test_datatypes
23
+ xml = nil
24
+
25
+ assert_nothing_raised do
26
+ xml = XML::XMLRPC::Parser.new(File.open("test/data/big_call.xml"))
27
+ end
28
+
29
+ # primitives
30
+
31
+ assert_equal(41, xml[0])
32
+ assert_equal("41", xml[1])
33
+ assert_equal(true, xml[2])
34
+ assert_equal(false, xml[3])
35
+ assert_equal(1.23, xml[4])
36
+
37
+ # DateTime
38
+ assert_kind_of(DateTime, xml[5])
39
+ assert_equal("1998-07-17T14:08:55+00:00", xml[5].to_s)
40
+
41
+ assert_equal("monkeys", xml[6]) # base64
42
+
43
+ assert_kind_of(Array, xml[7])
44
+ assert_equal([xml[6], xml[5]], xml[7])
45
+
46
+ assert_kind_of(Hash, xml[8])
47
+ assert_equal({ :Monkeys => [xml[6], xml[5]], :Poo => xml[5]}, xml[8])
48
+
49
+ assert_equal("examples.getStateName", xml.method)
50
+ end
51
+
52
+ def test_response
53
+ xml = nil
54
+
55
+ assert_raise XML::XMLRPC::RemoteCallError do
56
+ xml = XML::XMLRPC::Parser.new(File.open("test/data/fail_response.xml"))
57
+ end
58
+
59
+ # ensure the failure message is getting sent properly
60
+ e = nil
61
+ begin
62
+ xml = XML::XMLRPC::Parser.new(File.open("test/data/fail_response.xml"))
63
+ rescue XML::XMLRPC::RemoteCallError => error
64
+ e = error
65
+ end
66
+
67
+ assert_equal("4: Too many parameters.", e.message)
68
+
69
+ assert_nothing_raised do
70
+ xml = XML::XMLRPC::Parser.new(File.open("test/data/good_response.xml"))
71
+ end
72
+
73
+ assert_equal("South Dakota", xml[0])
74
+ end
75
+
76
+ def test_functionality
77
+ xml = nil
78
+ assert_nothing_raised do
79
+ xml = XML::XMLRPC::Parser.new(File.open("test/data/big_call.xml"))
80
+ end
81
+
82
+ # Enumerable functionality
83
+ xml.each_with_index do |x, i|
84
+ case i
85
+ when 0
86
+ assert_equal(41, x)
87
+ when 1
88
+ assert_equal("41", x)
89
+ when 2
90
+ assert_equal(true, x)
91
+ when 3
92
+ assert_equal(false, x)
93
+ when 4
94
+ assert_equal(1.23, x)
95
+ end
96
+ # that should be plenty.
97
+ end
98
+
99
+ assert(xml.include?(41))
100
+ end
101
+
102
+ def test_recursion
103
+ xml = nil
104
+ assert_nothing_raised do
105
+ xml = XML::XMLRPC::Parser.new(File.open("test/data/recursion_test.xml"))
106
+ end
107
+
108
+ assert_equal(
109
+ {
110
+ :Poo => [{
111
+ :Poo => ["monkeys", "19980717T14:08:55"],
112
+ :Monkeys => ["monkeys", "19980717T14:08:55"]
113
+ }],
114
+ :Monkeys => ["monkeys", "19980717T14:08:55"]
115
+ },
116
+ xml[0]
117
+ )
118
+ end
119
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: libxml-xmlrpc
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2007-10-23 00:00:00 -07:00
8
+ summary: Provides a alternative and faster XML-RPC layer through libxml's parsing framework
9
+ require_paths:
10
+ - lib
11
+ email: erik@hollensbe.org
12
+ homepage:
13
+ rubyforge_project: libxml-tools
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Erik Hollensbe
31
+ files:
32
+ - lib/xml
33
+ - lib/xml/libxml
34
+ - lib/xml/libxml/xmlrpc.rb
35
+ - lib/xml/libxml/xmlrpc
36
+ - lib/xml/libxml/xmlrpc/client.rb
37
+ - lib/xml/libxml/xmlrpc/parser.rb
38
+ - lib/xml/libxml/xmlrpc/builder.rb
39
+ - test/test_parser_good.rb
40
+ - test/data
41
+ - test/test_builder.rb
42
+ test_files: []
43
+
44
+ rdoc_options: []
45
+
46
+ extra_rdoc_files: []
47
+
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ requirements: []
53
+
54
+ dependencies:
55
+ - !ruby/object:Gem::Dependency
56
+ name: libxml-ruby
57
+ version_requirement:
58
+ version_requirements: !ruby/object:Gem::Version::Requirement
59
+ requirements:
60
+ - - ">"
61
+ - !ruby/object:Gem::Version
62
+ version: 0.0.0
63
+ version: