libxml-xmlrpc 0.1.0

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