roxml 2.4.3 → 2.5.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.
- data/History.txt +54 -0
- data/Manifest.txt +9 -6
- data/README.rdoc +24 -17
- data/Rakefile +2 -1
- data/TODO +30 -31
- data/examples/active_record.rb +69 -0
- data/examples/amazon.rb +1 -1
- data/examples/current_weather.rb +1 -1
- data/examples/posts.rb +8 -8
- data/examples/twitter.rb +2 -2
- data/examples/xml/active_record.xml +70 -0
- data/lib/roxml.rb +174 -174
- data/lib/roxml/definition.rb +165 -89
- data/lib/roxml/extensions/deprecation.rb +5 -0
- data/lib/roxml/extensions/string/conversions.rb +2 -3
- data/lib/roxml/hash_definition.rb +26 -25
- data/lib/roxml/xml.rb +15 -6
- data/lib/roxml/xml/parsers/libxml.rb +9 -6
- data/lib/roxml/xml/parsers/rexml.rb +1 -1
- data/lib/roxml/xml/references.rb +14 -17
- data/roxml.gemspec +8 -5
- data/spec/definition_spec.rb +563 -0
- data/spec/examples/active_record_spec.rb +43 -0
- data/spec/roxml_spec.rb +372 -0
- data/spec/shared_specs.rb +15 -0
- data/spec/spec_helper.rb +21 -4
- data/spec/string_spec.rb +15 -0
- data/spec/xml/parser_spec.rb +22 -0
- data/test/fixtures/book_valid.xml +1 -1
- data/test/fixtures/person_with_guarded_mothers.xml +3 -3
- data/test/mocks/mocks.rb +57 -45
- data/test/unit/definition_test.rb +161 -12
- data/test/unit/deprecations_test.rb +97 -0
- data/test/unit/to_xml_test.rb +30 -1
- data/test/unit/xml_bool_test.rb +15 -3
- data/test/unit/xml_construct_test.rb +6 -6
- data/test/unit/xml_hash_test.rb +18 -0
- data/test/unit/xml_initialize_test.rb +6 -3
- data/test/unit/xml_object_test.rb +66 -5
- data/test/unit/xml_text_test.rb +3 -0
- metadata +23 -15
- data/test/unit/array_test.rb +0 -16
- data/test/unit/freeze_test.rb +0 -71
- data/test/unit/inheritance_test.rb +0 -63
- data/test/unit/overriden_output_test.rb +0 -33
- data/test/unit/roxml_test.rb +0 -60
- data/test/unit/string_test.rb +0 -11
data/lib/roxml.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__)) unless
|
2
2
|
$LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
|
+
require 'uri'
|
5
|
+
|
4
6
|
%w(extensions definition xml).each do |file|
|
5
7
|
require File.join('roxml', file)
|
6
8
|
end
|
7
9
|
|
8
10
|
module ROXML # :nodoc:
|
9
|
-
VERSION = '2.
|
11
|
+
VERSION = '2.5.0'
|
10
12
|
|
11
13
|
def self.included(base) # :nodoc:
|
12
14
|
base.extend ClassMethods::Accessors,
|
@@ -46,8 +48,8 @@ module ROXML # :nodoc:
|
|
46
48
|
# class Measurement
|
47
49
|
# include ROXML
|
48
50
|
#
|
49
|
-
# xml_reader :units, :attr
|
50
|
-
# xml_reader :value, :content
|
51
|
+
# xml_reader :units, :from => :attr
|
52
|
+
# xml_reader :value, :from => :content
|
51
53
|
#
|
52
54
|
# def xml_initialize
|
53
55
|
# # the object is instantiated, and all xml attributes are imported
|
@@ -69,14 +71,15 @@ module ROXML # :nodoc:
|
|
69
71
|
# #xml_initialize may be written to take arguments, in which case extra arguments
|
70
72
|
# from from_xml will be passed into the function.
|
71
73
|
#
|
72
|
-
def xml_initialize
|
74
|
+
def xml_initialize # :nodoc:
|
73
75
|
end
|
76
|
+
deprecate :xml_initialize => :after_parse
|
74
77
|
end
|
75
78
|
|
76
79
|
module Conversions
|
77
80
|
# Returns a LibXML::XML::Node or a REXML::Element representing this object
|
78
81
|
def to_xml(name = nil)
|
79
|
-
returning XML::Node.
|
82
|
+
returning XML::Node.new(name || self.class.tag_name) do |root|
|
80
83
|
self.class.roxml_attrs.each do |attr|
|
81
84
|
ref = attr.to_ref(self)
|
82
85
|
v = ref.to_xml
|
@@ -175,9 +178,9 @@ module ROXML # :nodoc:
|
|
175
178
|
(@roxml_naming_convention || superclass.try(:roxml_naming_convention)).freeze
|
176
179
|
end
|
177
180
|
|
178
|
-
# Declares
|
179
|
-
# or a typed collection of nodes.
|
180
|
-
#
|
181
|
+
# Declares a reference to a certain xml element, whether an attribute, a node,
|
182
|
+
# or a typed collection of nodes. This method does not add a corresponding accessor
|
183
|
+
# to the object. For that behavior see the similar methods: .xml_reader and .xml_accessor.
|
181
184
|
#
|
182
185
|
# == Sym Option
|
183
186
|
# [sym] Symbol representing the name of the accessor.
|
@@ -187,12 +190,12 @@ module ROXML # :nodoc:
|
|
187
190
|
# if no other is declared. For example,
|
188
191
|
#
|
189
192
|
# xml_reader :bob
|
190
|
-
# xml_accessor :pony, :attr
|
193
|
+
# xml_accessor :pony, :from => :attr
|
191
194
|
#
|
192
195
|
# are equivalent to:
|
193
196
|
#
|
194
197
|
# xml_reader :bob, :from => 'bob'
|
195
|
-
# xml_accessor :pony, :
|
198
|
+
# xml_accessor :pony, :from => '@pony'
|
196
199
|
#
|
197
200
|
# === Boolean attributes
|
198
201
|
# If the name ends in a ?, ROXML will attempt to coerce the value to true or false,
|
@@ -200,7 +203,7 @@ module ROXML # :nodoc:
|
|
200
203
|
# to false, as shown below:
|
201
204
|
#
|
202
205
|
# xml_reader :desirable?
|
203
|
-
# xml_reader :bizzare?, :
|
206
|
+
# xml_reader :bizzare?, :from => '@BIZZARE'
|
204
207
|
#
|
205
208
|
# x = #from_xml(%{
|
206
209
|
# <object BIZZARE="1">
|
@@ -234,94 +237,90 @@ module ROXML # :nodoc:
|
|
234
237
|
# }).strange?
|
235
238
|
# => DUNNO
|
236
239
|
#
|
237
|
-
# ==
|
238
|
-
#
|
239
|
-
# or used as :from, pointing to a xml name to indicate both type and attribute name.
|
240
|
-
# Also, any type may be passed via an array to indicate that multiple instances
|
241
|
-
# of the object should be returned as an array.
|
240
|
+
# == Blocks
|
241
|
+
# You may also pass a block which manipulates the associated parsed value.
|
242
242
|
#
|
243
|
-
#
|
244
|
-
#
|
243
|
+
# class Muffins
|
244
|
+
# include ROXML
|
245
245
|
#
|
246
|
-
#
|
247
|
-
# class Book
|
248
|
-
# xml_reader :isbn, :attr => "ISBN" # 'ISBN' is used to specify :from
|
249
|
-
# xml_accessor :title, :attr # :from defaults to :title
|
246
|
+
# xml_reader(:count, :from => 'bakers_dozens') {|val| val.to_i * 13 }
|
250
247
|
# end
|
251
248
|
#
|
252
|
-
#
|
253
|
-
#
|
249
|
+
# For hash types, the block recieves the key and value as arguments, and they should
|
250
|
+
# be returned as an array of [key, value]
|
254
251
|
#
|
255
|
-
#
|
256
|
-
# The default type, if none is specified. Declares an accessor that
|
257
|
-
# represents a text node from XML.
|
252
|
+
# For array types, the entire array is passed in, and must be returned in the same fashion.
|
258
253
|
#
|
259
|
-
#
|
260
|
-
#
|
261
|
-
#
|
262
|
-
#
|
263
|
-
# xml_reader :title
|
264
|
-
# end
|
254
|
+
# == Options
|
255
|
+
# === :as
|
256
|
+
# ==== Basic Types
|
257
|
+
# Allows you to specify one of several basic types to return the value as. For example
|
265
258
|
#
|
266
|
-
#
|
259
|
+
# xml_reader :count, :as => Integer
|
260
|
+
#
|
261
|
+
# is equivalent to:
|
262
|
+
#
|
263
|
+
# xml_reader(:count) {|val| Integer(val) unless val.empty? }
|
264
|
+
#
|
265
|
+
# Such block shorthands for Integer, Float, Fixnum, BigDecimal, Date, Time, and DateTime
|
266
|
+
# are currently available, but only for non-Hash declarations.
|
267
|
+
#
|
268
|
+
# To reference many elements, put the desired type in a literal array. e.g.:
|
269
|
+
#
|
270
|
+
# xml_reader :counts, :as => [Integer]
|
271
|
+
#
|
272
|
+
# Even an array of :text nodes can be specified with :as => []
|
273
|
+
#
|
274
|
+
# xml_reader :quotes, :as => []
|
275
|
+
#
|
276
|
+
# === Other ROXML Class
|
277
|
+
# Declares an accessor that represents another ROXML class as child XML element
|
278
|
+
# (one-to-one or composition) or array of child elements (one-to-many or
|
279
|
+
# aggregation) of this type. Default is one-to-one. For one-to-many, simply pass the class
|
280
|
+
# as the only element in an array.
|
281
|
+
#
|
282
|
+
# Composition example:
|
267
283
|
# <book>
|
268
|
-
# <
|
269
|
-
#
|
270
|
-
#
|
284
|
+
# <publisher>
|
285
|
+
# <name>Pragmatic Bookshelf</name>
|
286
|
+
# </publisher>
|
271
287
|
# </book>
|
272
288
|
#
|
273
|
-
#
|
289
|
+
# Can be mapped using the following code:
|
290
|
+
# class Book
|
291
|
+
# xml_reader :publisher, :as => Publisher
|
292
|
+
# end
|
274
293
|
#
|
275
|
-
#
|
294
|
+
# Aggregation example:
|
295
|
+
# <library>
|
296
|
+
# <books>
|
297
|
+
# <book/>
|
298
|
+
# <book/>
|
299
|
+
# </books>
|
300
|
+
# </library>
|
301
|
+
#
|
302
|
+
# Can be mapped using the following code:
|
276
303
|
# class Library
|
277
|
-
# xml_reader :books, [
|
304
|
+
# xml_reader :books, :as => [Book], :in => "books"
|
278
305
|
# end
|
279
306
|
#
|
280
|
-
#
|
307
|
+
# If you don't have the <books> tag to wrap around the list of <book> tags:
|
281
308
|
# <library>
|
282
|
-
#
|
283
|
-
#
|
284
|
-
#
|
285
|
-
# <book>Gödel, Escher, Bach</book>
|
286
|
-
# </books>
|
309
|
+
# <name>Ruby books</name>
|
310
|
+
# <book/>
|
311
|
+
# <book/>
|
287
312
|
# </library>
|
288
313
|
#
|
289
|
-
#
|
290
|
-
#
|
291
|
-
# rather than a sub-node
|
292
|
-
#
|
293
|
-
# Example:
|
294
|
-
# class Contributor
|
295
|
-
# xml_reader :name, :content
|
296
|
-
# xml_reader :role, :attr
|
297
|
-
# end
|
298
|
-
#
|
299
|
-
# To map:
|
300
|
-
# <contributor role="editor">James Wick</contributor>
|
314
|
+
# You can skip the wrapper argument:
|
315
|
+
# xml_reader :books, :as => [Book]
|
301
316
|
#
|
302
|
-
#
|
317
|
+
# ==== Hash
|
303
318
|
# Somewhere between the simplicity of a :text/:attr mapping, and the complexity of
|
304
319
|
# a full Object/Type mapping, lies the Hash mapping. It serves in the case where you have
|
305
320
|
# a collection of key-value pairs represented in your xml. You create a hash declaration by
|
306
321
|
# passing a hash mapping as the type argument. A few examples:
|
307
322
|
#
|
308
|
-
#
|
309
|
-
# For xml such as this:
|
310
|
-
#
|
311
|
-
# <dictionary>
|
312
|
-
# <definitions>
|
313
|
-
# <definition dt="quaquaversally"
|
314
|
-
# dd="adjective: (of a geological formation) sloping downward from the center in all directions." />
|
315
|
-
# <definition dt="tergiversate"
|
316
|
-
# dd="To use evasions or ambiguities; equivocate." />
|
317
|
-
# </definitions>
|
318
|
-
# </dictionary>
|
319
|
-
#
|
320
|
-
# You can use the :attrs key in you has with a [:key, :value] name array:
|
321
|
-
#
|
322
|
-
# xml_reader :definitions, {:attrs => ['dt', 'dd']}, :in => :definitions
|
323
|
-
#
|
324
|
-
# ==== Hash of :texts
|
323
|
+
# ===== Hash of :texts
|
325
324
|
# For xml such as this:
|
326
325
|
#
|
327
326
|
# <dictionary>
|
@@ -336,10 +335,10 @@ module ROXML # :nodoc:
|
|
336
335
|
# </dictionary>
|
337
336
|
#
|
338
337
|
# You can individually declare your key and value names:
|
339
|
-
# xml_reader :definitions, {:key => 'word',
|
340
|
-
#
|
338
|
+
# xml_reader :definitions, :as => {:key => 'word',
|
339
|
+
# :value => 'meaning'}
|
341
340
|
#
|
342
|
-
#
|
341
|
+
# ===== Hash of :content &c.
|
343
342
|
# For xml such as this:
|
344
343
|
#
|
345
344
|
# <dictionary>
|
@@ -350,10 +349,10 @@ module ROXML # :nodoc:
|
|
350
349
|
# You can individually declare the key and value, but with the attr, you need to provide both the type
|
351
350
|
# and name of that type (i.e. {:attr => :word}), because omitting the type will result in ROXML
|
352
351
|
# defaulting to :text
|
353
|
-
# xml_reader :definitions, {:key => {:attr => 'word'},
|
354
|
-
#
|
352
|
+
# xml_reader :definitions, :as => {:key => {:attr => 'word'},
|
353
|
+
# :value => :content}
|
355
354
|
#
|
356
|
-
#
|
355
|
+
# ===== Hash of :name &c.
|
357
356
|
# For xml such as this:
|
358
357
|
#
|
359
358
|
# <dictionary>
|
@@ -362,112 +361,119 @@ module ROXML # :nodoc:
|
|
362
361
|
# </dictionary>
|
363
362
|
#
|
364
363
|
# You can pick up the node names (e.g. quaquaversally) using the :name keyword:
|
365
|
-
# xml_reader :definitions, {:key => :name,
|
366
|
-
#
|
367
|
-
#
|
368
|
-
# === Other ROXML Class
|
369
|
-
# Declares an accessor that represents another ROXML class as child XML element
|
370
|
-
# (one-to-one or composition) or array of child elements (one-to-many or
|
371
|
-
# aggregation) of this type. Default is one-to-one. Use :array option for one-to-many, or
|
372
|
-
# simply pass the class in an array.
|
364
|
+
# xml_reader :definitions, :as => {:key => :name,
|
365
|
+
# :value => :content}
|
373
366
|
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
# <name>Pragmatic Bookshelf</name>
|
378
|
-
# </publisher>
|
379
|
-
# </book>
|
367
|
+
# === :from
|
368
|
+
# The name by which the xml value will be found, either an attribute or tag name in XML.
|
369
|
+
# Default is sym, or the singular form of sym, in the case of arrays and hashes.
|
380
370
|
#
|
381
|
-
#
|
382
|
-
# class Book
|
383
|
-
# xml_reader :publisher, Publisher
|
384
|
-
# end
|
371
|
+
# This value may also include XPath notation.
|
385
372
|
#
|
386
|
-
#
|
387
|
-
#
|
388
|
-
#
|
389
|
-
# <book/>
|
390
|
-
# <book/>
|
391
|
-
# </books>
|
392
|
-
# </library>
|
373
|
+
# ==== :from => :content
|
374
|
+
# When :from is set to :content, this refers to the content of the current node,
|
375
|
+
# rather than a sub-node. It is equivalent to :from => '.'
|
393
376
|
#
|
394
|
-
#
|
395
|
-
# class
|
396
|
-
# xml_reader :
|
377
|
+
# Example:
|
378
|
+
# class Contributor
|
379
|
+
# xml_reader :name, :from => :content
|
380
|
+
# xml_reader :role, :from => :attr
|
397
381
|
# end
|
398
382
|
#
|
399
|
-
#
|
400
|
-
# <
|
401
|
-
# <name>Ruby books</name>
|
402
|
-
# <book/>
|
403
|
-
# <book/>
|
404
|
-
# </library>
|
405
|
-
#
|
406
|
-
# You can skip the wrapper argument:
|
407
|
-
# xml_reader :books, [Book]
|
408
|
-
#
|
409
|
-
# == Blocks
|
410
|
-
# You may also pass a block which manipulates the associated parsed value.
|
383
|
+
# To map:
|
384
|
+
# <contributor role="editor">James Wick</contributor>
|
411
385
|
#
|
412
|
-
#
|
413
|
-
#
|
386
|
+
# ==== :from => :attr
|
387
|
+
# When :from is set to :attr, this refers to the content of an attribute,
|
388
|
+
# rather than a sub-node. It is equivalent to :from => '@attribute_name'
|
414
389
|
#
|
415
|
-
#
|
390
|
+
# Example:
|
391
|
+
# class Book
|
392
|
+
# xml_reader :isbn, :from => "@ISBN"
|
393
|
+
# xml_accessor :title, :from => :attr # :from defaults to '@title'
|
416
394
|
# end
|
417
395
|
#
|
418
|
-
#
|
419
|
-
#
|
396
|
+
# To map:
|
397
|
+
# <book ISBN="0974514055" title="Programming Ruby: the pragmatic programmers' guide" />
|
420
398
|
#
|
421
|
-
#
|
399
|
+
# ==== :from => :text
|
400
|
+
# The default source, if none is specified, this means the accessor
|
401
|
+
# represents a text node from XML. This is documented for completeness
|
402
|
+
# only. You should just leave this option off when you want the default behavior,
|
403
|
+
# as in the examples below.
|
422
404
|
#
|
423
|
-
#
|
405
|
+
# :text is equivalent to :from => accessor_name, and you should specify the
|
406
|
+
# actual node name if it differs, as in the case of :author below.
|
424
407
|
#
|
425
|
-
#
|
408
|
+
# Example:
|
409
|
+
# class Book
|
410
|
+
# xml_reader :author, :from => 'Author
|
411
|
+
# xml_accessor :description, :cdata => true
|
412
|
+
# xml_reader :title
|
413
|
+
# end
|
426
414
|
#
|
427
|
-
#
|
415
|
+
# To map:
|
416
|
+
# <book>
|
417
|
+
# <title>Programming Ruby: the pragmatic programmers' guide</title>
|
418
|
+
# <description><![CDATA[Probably the best Ruby book out there]]></description>
|
419
|
+
# <Author>David Thomas</Author>
|
420
|
+
# </book>
|
428
421
|
#
|
429
|
-
#
|
422
|
+
# Likewise, a number of :text node values can be collected in an array like so:
|
430
423
|
#
|
431
|
-
#
|
424
|
+
# Example:
|
425
|
+
# class Library
|
426
|
+
# xml_reader :books, :as => []
|
427
|
+
# end
|
432
428
|
#
|
433
|
-
#
|
434
|
-
#
|
429
|
+
# To map:
|
430
|
+
# <library>
|
431
|
+
# <book>To kill a mockingbird</book>
|
432
|
+
# <book>House of Leaves</book>
|
433
|
+
# <book>Gödel, Escher, Bach</book>
|
434
|
+
# </library>
|
435
435
|
#
|
436
|
-
#
|
437
|
-
# [:
|
438
|
-
#
|
439
|
-
# [:
|
440
|
-
# [:else] Default value for attribute, if missing
|
436
|
+
# === Other Options
|
437
|
+
# [:in] An optional name of a wrapping tag for this XML accessor.
|
438
|
+
# This can include other xpath values, which will be joined with :from with a '/'
|
439
|
+
# [:else] Default value for attribute, if missing from the xml on .from_xml
|
441
440
|
# [:required] If true, throws RequiredElementMissing when the element isn't present
|
442
441
|
# [:frozen] If true, all results are frozen (using #freeze) at parse-time.
|
442
|
+
# [:cdata] True for values which should be input from or output as cdata elements
|
443
443
|
#
|
444
|
-
def
|
445
|
-
|
446
|
-
|
447
|
-
|
444
|
+
def xml_attr(sym, type_and_or_opts = nil, opts = nil, &block)
|
445
|
+
returning Definition.new(sym, *[type_and_or_opts, opts].compact, &block) do |attr|
|
446
|
+
if roxml_attrs.map(&:accessor).include? attr.accessor
|
447
|
+
raise "Accessor #{attr.accessor} is already defined as XML accessor in class #{self.name}"
|
448
|
+
end
|
449
|
+
@roxml_attrs << attr
|
450
|
+
end
|
448
451
|
end
|
449
452
|
|
450
|
-
def xml(sym, writable = false, type_and_or_opts =
|
451
|
-
|
453
|
+
def xml(sym, writable = false, type_and_or_opts = nil, opts = nil, &block) #:nodoc:
|
454
|
+
send(writable ? :xml_accessor : :xml_reader, sym, type_and_or_opts, opts, &block)
|
452
455
|
end
|
453
|
-
deprecate :xml =>
|
456
|
+
deprecate :xml => "use xml_attr, xml_reader, or xml_accessor instead"
|
454
457
|
|
455
|
-
# Declares a read-only xml reference. See
|
458
|
+
# Declares a read-only xml reference. See xml_attr for details.
|
456
459
|
#
|
457
460
|
# Note that while xml_reader does not create a setter for this attribute,
|
458
461
|
# its value can be modified indirectly via methods. For more complete
|
459
462
|
# protection, consider the :frozen option.
|
460
|
-
def xml_reader(sym, type_and_or_opts =
|
461
|
-
|
463
|
+
def xml_reader(sym, type_and_or_opts = nil, opts = nil, &block)
|
464
|
+
attr = xml_attr sym, type_and_or_opts, opts, &block
|
465
|
+
add_reader(attr)
|
462
466
|
end
|
463
467
|
|
464
|
-
# Declares a writable xml reference. See
|
468
|
+
# Declares a writable xml reference. See xml_attr for details.
|
465
469
|
#
|
466
470
|
# Note that while xml_accessor does create a setter for this attribute,
|
467
471
|
# you can use the :frozen option to prevent its value from being
|
468
472
|
# modified indirectly via methods.
|
469
|
-
def xml_accessor(sym, type_and_or_opts =
|
470
|
-
|
473
|
+
def xml_accessor(sym, type_and_or_opts = nil, opts = nil, &block)
|
474
|
+
attr = xml_attr sym, type_and_or_opts, opts, &block
|
475
|
+
add_reader(attr)
|
476
|
+
attr_writer(attr.variable_name)
|
471
477
|
end
|
472
478
|
|
473
479
|
# This method is deprecated, please use xml_initialize instead
|
@@ -484,23 +490,9 @@ module ROXML # :nodoc:
|
|
484
490
|
deprecate :xml_construct => :xml_initialize
|
485
491
|
|
486
492
|
private
|
487
|
-
def
|
488
|
-
if roxml_attrs.map(&:accessor).include? attr.accessor
|
489
|
-
raise "Accessor #{attr.accessor} is already defined as XML accessor in class #{self.name}"
|
490
|
-
end
|
491
|
-
@roxml_attrs << attr
|
492
|
-
|
493
|
+
def add_reader(attr)
|
493
494
|
define_method(attr.accessor) do
|
494
|
-
|
495
|
-
if result.nil?
|
496
|
-
result = attr.default
|
497
|
-
instance_variable_set("@#{attr.variable_name}", result)
|
498
|
-
end
|
499
|
-
result
|
500
|
-
end
|
501
|
-
|
502
|
-
if writable && !instance_methods.include?("#{attr.accessor}=")
|
503
|
-
attr_writer(attr.accessor)
|
495
|
+
instance_variable_get("@#{attr.variable_name}")
|
504
496
|
end
|
505
497
|
end
|
506
498
|
end
|
@@ -559,7 +551,7 @@ module ROXML # :nodoc:
|
|
559
551
|
# Creates a new Ruby object from XML using mapping information
|
560
552
|
# annotated in the class.
|
561
553
|
#
|
562
|
-
# The input data is either an XML::Node or
|
554
|
+
# The input data is either an XML::Node, String, Pathname, or File representing
|
563
555
|
# the XML document.
|
564
556
|
#
|
565
557
|
# Example
|
@@ -568,7 +560,9 @@ module ROXML # :nodoc:
|
|
568
560
|
# book = Book.from_xml("<book><name>Beyond Java</name></book>")
|
569
561
|
#
|
570
562
|
# _initialization_args_ passed into from_xml will be passed into
|
571
|
-
# the object
|
563
|
+
# the object's .new, prior to populating the xml_attrs.
|
564
|
+
#
|
565
|
+
# After the instatiation and xml population
|
572
566
|
#
|
573
567
|
# See also: xml_initialize
|
574
568
|
#
|
@@ -581,13 +575,19 @@ module ROXML # :nodoc:
|
|
581
575
|
end.map {|attr| attr.to_ref(self).value_in(xml) }
|
582
576
|
new(*args)
|
583
577
|
else
|
584
|
-
returning
|
578
|
+
returning new(*initialization_args) do |inst|
|
585
579
|
roxml_attrs.each do |attr|
|
586
|
-
|
580
|
+
value = attr.to_ref(inst).value_in(xml)
|
581
|
+
setter = :"#{attr.variable_name}="
|
582
|
+
inst.respond_to?(setter) \
|
583
|
+
? inst.send(setter, value) \
|
584
|
+
: inst.instance_variable_set("@#{attr.variable_name}", value)
|
587
585
|
end
|
588
|
-
inst.
|
586
|
+
inst.try(:after_parse)
|
589
587
|
end
|
590
588
|
end
|
589
|
+
rescue ArgumentError => e
|
590
|
+
raise e, e.message + " for class #{self}"
|
591
591
|
end
|
592
592
|
|
593
593
|
# Deprecated in favor of #from_xml
|