Empact-roxml 2.1 → 2.2
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/README.rdoc +3 -3
- data/Rakefile +16 -9
- data/lib/roxml.rb +366 -323
- data/lib/roxml/extensions/array.rb +5 -0
- data/lib/roxml/extensions/array/conversions.rb +27 -0
- data/lib/roxml/extensions/deprecation.rb +15 -0
- data/lib/roxml/extensions/string.rb +22 -0
- data/lib/roxml/extensions/string/conversions.rb +44 -0
- data/lib/roxml/extensions/string/iterators.rb +12 -0
- data/lib/roxml/options.rb +27 -15
- data/lib/roxml/xml.rb +91 -118
- data/lib/roxml/xml/libxml.rb +2 -2
- data/lib/roxml/xml/rexml.rb +5 -2
- data/roxml.gemspec +16 -3
- data/test/fixtures/book_with_wrapped_attr.xml +3 -0
- data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
- data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
- data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
- data/test/fixtures/dictionary_of_names.xml +4 -0
- data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
- data/test/fixtures/node_with_name_conflicts.xml +4 -0
- data/test/mocks/mocks.rb +63 -11
- data/test/unit/options_test.rb +41 -1
- data/test/unit/roxml_test.rb +1 -1
- data/test/unit/string_test.rb +1 -1
- data/test/unit/to_xml_test.rb +5 -3
- data/test/unit/xml_attribute_test.rb +11 -6
- data/test/unit/xml_construct_test.rb +3 -3
- data/test/unit/xml_hash_test.rb +7 -11
- data/test/unit/xml_name_test.rb +22 -2
- data/test/unit/xml_namespace_test.rb +5 -4
- data/test/unit/xml_object_test.rb +36 -14
- data/test/unit/xml_text_test.rb +11 -11
- metadata +25 -6
- data/lib/roxml/array.rb +0 -15
- data/lib/roxml/string.rb +0 -35
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../deprecation')
|
|
2
|
+
|
|
3
|
+
module ROXML
|
|
4
|
+
module CoreExtensions
|
|
5
|
+
module Array #:nodoc:
|
|
6
|
+
module Conversions
|
|
7
|
+
# Translates an array into a hash, where each element of the array is
|
|
8
|
+
# an array with 2 elements:
|
|
9
|
+
#
|
|
10
|
+
# >> [[:key, :value], [1, 2], ['key', 'value']].to_h
|
|
11
|
+
# => {:key => :value, 1 => 2, 'key' => 'value'}
|
|
12
|
+
#
|
|
13
|
+
def to_hash
|
|
14
|
+
inject({}) do |result, (k, v)|
|
|
15
|
+
result[k] = v
|
|
16
|
+
result
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_h #:nodoc:
|
|
21
|
+
ActiveSupport::Deprecation.warn "Please use #to_hash instead"
|
|
22
|
+
to_hash
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require 'active_support/version'
|
|
3
|
+
|
|
4
|
+
module ActiveSupport # :nodoc:all
|
|
5
|
+
if VERSION::MAJOR <= 2 && VERSION::MINOR <= 1
|
|
6
|
+
module Deprecation
|
|
7
|
+
class << self
|
|
8
|
+
def deprecation_message(callstack, message = nil)
|
|
9
|
+
message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
|
|
10
|
+
"DEPRECATION WARNING: #{message}. #{deprecation_caller_message(callstack)}"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'string/conversions')
|
|
2
|
+
require File.join(File.dirname(__FILE__), 'string/iterators')
|
|
3
|
+
|
|
4
|
+
class String #:nodoc:
|
|
5
|
+
include ROXML::CoreExtensions::String::Conversions
|
|
6
|
+
include ROXML::CoreExtensions::String::Iterators
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), 'deprecation')
|
|
10
|
+
class Object #:nodoc:
|
|
11
|
+
# Deprecated in favor of explicit #to_s.to_utf
|
|
12
|
+
def to_utf
|
|
13
|
+
ActiveSupport::Deprecation.warn "This method will be removed from Object please use String#to_utf instead via explicit #to_s"
|
|
14
|
+
to_s.to_utf
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Deprecated in favor of explicit #to_s.to_latin
|
|
18
|
+
def to_latin
|
|
19
|
+
ActiveSupport::Deprecation.warn "This method will be removed from Object please use String#to_latin instead via explicit #to_s"
|
|
20
|
+
to_s.to_latin
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module ROXML
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module String
|
|
4
|
+
# Extension of String class to handle conversion from/to
|
|
5
|
+
# UTF-8/ISO-8869-1
|
|
6
|
+
module Conversions
|
|
7
|
+
require 'iconv'
|
|
8
|
+
|
|
9
|
+
#
|
|
10
|
+
# Return an utf-8 representation of this string.
|
|
11
|
+
#
|
|
12
|
+
def to_utf
|
|
13
|
+
begin
|
|
14
|
+
Iconv.new("utf-8", "iso-8859-1").iconv(to_s)
|
|
15
|
+
rescue Iconv::IllegalSequence
|
|
16
|
+
STDERR << "!! Failed converting from UTF-8 -> ISO-8859-1 (#{self}). Already the right charset?"
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Convert this string to iso-8850-1
|
|
23
|
+
#
|
|
24
|
+
def to_latin
|
|
25
|
+
begin
|
|
26
|
+
Iconv.new("iso-8859-1", "utf-8").iconv(to_s)
|
|
27
|
+
rescue Iconv::IllegalSequence
|
|
28
|
+
STDERR << "!! Failed converting from ISO-8859-1 -> UTF-8 (#{self}). Already the right charset?"
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class Object
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class String
|
|
41
|
+
def between(separator, &block)
|
|
42
|
+
split(separator).collect(&block).join(separator)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module ROXML
|
|
2
|
+
module CoreExtensions
|
|
3
|
+
module String #:nodoc:
|
|
4
|
+
module Iterators
|
|
5
|
+
# Allows you to iterate over and modify the sub-strings between _separator_. Returns the joined result of the modification.
|
|
6
|
+
def between(separator, &block)
|
|
7
|
+
split(separator).collect(&block).join(separator)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/roxml/options.rb
CHANGED
|
@@ -2,7 +2,7 @@ module ROXML
|
|
|
2
2
|
HASH_KEYS = [:attrs, :key, :value].freeze
|
|
3
3
|
TYPE_KEYS = [:attr, :text, :hash, :content].freeze
|
|
4
4
|
|
|
5
|
-
class HashDesc #
|
|
5
|
+
class HashDesc # :nodoc:
|
|
6
6
|
attr_reader :key, :value, :wrapper
|
|
7
7
|
|
|
8
8
|
def initialize(opts, wrapper)
|
|
@@ -78,25 +78,24 @@ module ROXML
|
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
class Opts #
|
|
82
|
-
attr_reader :type, :hash
|
|
81
|
+
class Opts # :nodoc:
|
|
82
|
+
attr_reader :name, :type, :hash, :blocks
|
|
83
83
|
|
|
84
|
-
def initialize(sym, *args)
|
|
84
|
+
def initialize(sym, *args, &block)
|
|
85
85
|
@opts = extract_options!(args)
|
|
86
86
|
|
|
87
87
|
@opts.reverse_merge!(:from => sym.to_s, :as => [], :else => nil, :in => nil)
|
|
88
88
|
@opts[:as] = [*@opts[:as]]
|
|
89
89
|
@type = extract_type(args)
|
|
90
|
+
@blocks = collect_blocks(block, @opts[:as])
|
|
90
91
|
|
|
91
92
|
@name = @opts[:from].to_s
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
93
|
+
@name = @name.singularize if hash? || array?
|
|
94
|
+
if hash? && (hash.key.name? || hash.value.name?)
|
|
95
|
+
@name = '*'
|
|
96
|
+
end
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
enumerable? ? @name.singularize : @name
|
|
98
|
+
raise ArgumentError, "Can't specify both :else default and :required" if required? && default
|
|
100
99
|
end
|
|
101
100
|
|
|
102
101
|
def hash
|
|
@@ -107,10 +106,6 @@ module ROXML
|
|
|
107
106
|
@opts[:else]
|
|
108
107
|
end
|
|
109
108
|
|
|
110
|
-
def enumerable?
|
|
111
|
-
hash? || array?
|
|
112
|
-
end
|
|
113
|
-
|
|
114
109
|
def hash?
|
|
115
110
|
@type == :hash
|
|
116
111
|
end
|
|
@@ -131,7 +126,24 @@ module ROXML
|
|
|
131
126
|
@opts[:in]
|
|
132
127
|
end
|
|
133
128
|
|
|
129
|
+
def required?
|
|
130
|
+
@opts[:required]
|
|
131
|
+
end
|
|
132
|
+
|
|
134
133
|
private
|
|
134
|
+
BLOCK_SHORTHANDS = {
|
|
135
|
+
:integer => lambda {|val| Integer(val) },
|
|
136
|
+
Integer => lambda {|val| Integer(val) },
|
|
137
|
+
:float => lambda {|val| Float(val) },
|
|
138
|
+
Float => lambda {|val| Float(val) }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
def collect_blocks(block, as)
|
|
142
|
+
shorthands = as & BLOCK_SHORTHANDS.keys
|
|
143
|
+
raise ArgumentError, "multiple block shorthands supplied #{shorthands.map(&:to_s).join(', ')}" if shorthands.size > 1
|
|
144
|
+
[BLOCK_SHORTHANDS[shorthands.first], block].compact
|
|
145
|
+
end
|
|
146
|
+
|
|
135
147
|
def extract_options!(args)
|
|
136
148
|
opts = args.extract_options!
|
|
137
149
|
unless (opts.keys & HASH_KEYS).empty?
|
data/lib/roxml/xml.rb
CHANGED
|
@@ -2,26 +2,27 @@ module ROXML
|
|
|
2
2
|
unless const_defined? 'XML_PARSER'
|
|
3
3
|
begin
|
|
4
4
|
require 'libxml'
|
|
5
|
-
XML_PARSER = 'libxml'
|
|
5
|
+
XML_PARSER = 'libxml' # :nodoc:
|
|
6
6
|
rescue LoadError
|
|
7
|
-
XML_PARSER = 'rexml'
|
|
7
|
+
XML_PARSER = 'rexml' # :nodoc:
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
require File.join(File.dirname(__FILE__), 'xml', XML_PARSER)
|
|
11
11
|
|
|
12
|
+
class RequiredElementMissing < Exception # :nodoc:
|
|
13
|
+
end
|
|
14
|
+
|
|
12
15
|
#
|
|
13
16
|
# Internal base class that represents an XML - Class binding.
|
|
14
17
|
#
|
|
15
|
-
class XMLRef #
|
|
16
|
-
attr_reader :accessor
|
|
18
|
+
class XMLRef # :nodoc:
|
|
19
|
+
attr_reader :accessor
|
|
20
|
+
delegate :name, :required?, :array?, :default, :wrapper, :blocks, :to => :opts
|
|
21
|
+
alias_method :xpath_name, :name
|
|
17
22
|
|
|
18
|
-
def initialize(accessor, args
|
|
23
|
+
def initialize(accessor, args)
|
|
19
24
|
@accessor = accessor
|
|
20
|
-
@
|
|
21
|
-
@name = args.name
|
|
22
|
-
@default = args.default
|
|
23
|
-
@block = block
|
|
24
|
-
@wrapper = args.wrapper
|
|
25
|
+
@opts = args
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
# Reads data from the XML element and populates the instance
|
|
@@ -36,9 +37,31 @@ module ROXML
|
|
|
36
37
|
false
|
|
37
38
|
end
|
|
38
39
|
|
|
40
|
+
def update_xml(xml, value)
|
|
41
|
+
returning wrap(xml) do |xml|
|
|
42
|
+
write_xml(xml, value)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def value(xml)
|
|
47
|
+
value = fetch_value(xml)
|
|
48
|
+
if value.blank?
|
|
49
|
+
raise RequiredElementMissing if required?
|
|
50
|
+
value = default
|
|
51
|
+
end
|
|
52
|
+
apply_blocks(value)
|
|
53
|
+
end
|
|
54
|
+
|
|
39
55
|
private
|
|
56
|
+
attr_reader :opts
|
|
57
|
+
|
|
58
|
+
def apply_blocks(val)
|
|
59
|
+
blocks.each {|block| val = block[*val] } unless blocks.empty?
|
|
60
|
+
val
|
|
61
|
+
end
|
|
62
|
+
|
|
40
63
|
def xpath
|
|
41
|
-
wrapper ? "#{wrapper}
|
|
64
|
+
wrapper ? "#{wrapper}/#{xpath_name}" : xpath_name.to_s
|
|
42
65
|
end
|
|
43
66
|
|
|
44
67
|
def wrap(xml)
|
|
@@ -52,23 +75,21 @@ module ROXML
|
|
|
52
75
|
# <element attribute="XMLAttributeRef">
|
|
53
76
|
# XMLTextRef
|
|
54
77
|
# </element>
|
|
55
|
-
class XMLAttributeRef < XMLRef #
|
|
78
|
+
class XMLAttributeRef < XMLRef # :nodoc:
|
|
79
|
+
private
|
|
56
80
|
# Updates the attribute in the given XML block to
|
|
57
81
|
# the value provided.
|
|
58
|
-
def
|
|
59
|
-
xml.attributes[name] = value.to_utf
|
|
60
|
-
xml
|
|
82
|
+
def write_xml(xml, value)
|
|
83
|
+
xml.attributes[name] = value.to_s.to_utf
|
|
61
84
|
end
|
|
62
85
|
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
block ? block.call(val) : val
|
|
86
|
+
def fetch_value(xml)
|
|
87
|
+
attr = xml.search(xpath).first
|
|
88
|
+
attr && attr.value
|
|
67
89
|
end
|
|
68
90
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
'@'
|
|
91
|
+
def xpath_name
|
|
92
|
+
"@#{name}"
|
|
72
93
|
end
|
|
73
94
|
end
|
|
74
95
|
|
|
@@ -78,165 +99,117 @@ module ROXML
|
|
|
78
99
|
# <element attribute="XMLAttributeRef">
|
|
79
100
|
# XMLTextRef
|
|
80
101
|
# </element>
|
|
81
|
-
class XMLTextRef < XMLRef #
|
|
82
|
-
|
|
102
|
+
class XMLTextRef < XMLRef # :nodoc:
|
|
103
|
+
delegate :cdata?, :content?, :to => :opts
|
|
83
104
|
|
|
84
|
-
def
|
|
85
|
-
|
|
86
|
-
@content = args.content?
|
|
87
|
-
@cdata = args.cdata?
|
|
105
|
+
def name?
|
|
106
|
+
name == '*'
|
|
88
107
|
end
|
|
89
108
|
|
|
109
|
+
private
|
|
90
110
|
# Updates the text in the given _xml_ block to
|
|
91
111
|
# the _value_ provided.
|
|
92
|
-
def
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
add(parent, value)
|
|
112
|
+
def write_xml(xml, value)
|
|
113
|
+
if content?
|
|
114
|
+
add(xml, value)
|
|
96
115
|
elsif name?
|
|
97
|
-
|
|
98
|
-
elsif array
|
|
116
|
+
xml.name = value
|
|
117
|
+
elsif array?
|
|
99
118
|
value.each do |v|
|
|
100
|
-
add(
|
|
119
|
+
add(xml.child_add(XML::Node.new_element(name)), v)
|
|
101
120
|
end
|
|
102
121
|
else
|
|
103
|
-
add(
|
|
122
|
+
add(xml.child_add(XML::Node.new_element(name)), value)
|
|
104
123
|
end
|
|
105
|
-
xml
|
|
106
124
|
end
|
|
107
125
|
|
|
108
|
-
def
|
|
109
|
-
|
|
126
|
+
def fetch_value(xml)
|
|
127
|
+
if content?
|
|
110
128
|
xml.content.strip
|
|
111
129
|
elsif name?
|
|
112
130
|
xml.name
|
|
113
|
-
elsif array
|
|
114
|
-
|
|
131
|
+
elsif array?
|
|
132
|
+
xml.search(xpath).collect do |e|
|
|
115
133
|
e.content.strip.to_latin if e.content
|
|
116
134
|
end
|
|
117
|
-
arr unless arr.empty?
|
|
118
135
|
else
|
|
119
136
|
child = xml.search(name).first
|
|
120
137
|
child.content if child
|
|
121
138
|
end
|
|
122
|
-
val = default unless val && !val.blank?
|
|
123
|
-
block ? block.call(val) : val
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def name?
|
|
127
|
-
name == '*'
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
private
|
|
131
|
-
def xpath_separator
|
|
132
|
-
'/'
|
|
133
139
|
end
|
|
134
140
|
|
|
135
141
|
def add(dest, value)
|
|
136
|
-
if cdata
|
|
137
|
-
dest.child_add(XML::Node.new_cdata(value.to_utf))
|
|
142
|
+
if cdata?
|
|
143
|
+
dest.child_add(XML::Node.new_cdata(value.to_s.to_utf))
|
|
138
144
|
else
|
|
139
|
-
dest.content = value.to_utf
|
|
145
|
+
dest.content = value.to_s.to_utf
|
|
140
146
|
end
|
|
141
147
|
end
|
|
142
148
|
end
|
|
143
149
|
|
|
144
|
-
class XMLHashRef < XMLTextRef #
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def initialize(accessor, args, &block)
|
|
148
|
-
super(accessor, args, &block)
|
|
149
|
-
@hash = args.hash
|
|
150
|
-
if @hash.key.name? || @hash.value.name?
|
|
151
|
-
@name = '*'
|
|
152
|
-
end
|
|
153
|
-
end
|
|
150
|
+
class XMLHashRef < XMLTextRef # :nodoc:
|
|
151
|
+
delegate :hash, :to => :opts
|
|
154
152
|
|
|
153
|
+
private
|
|
155
154
|
# Updates the composed XML object in the given XML block to
|
|
156
155
|
# the value provided.
|
|
157
|
-
def
|
|
158
|
-
parent = wrap(xml)
|
|
156
|
+
def write_xml(xml, value)
|
|
159
157
|
value.each_pair do |k, v|
|
|
160
|
-
node =
|
|
158
|
+
node = xml.child_add(XML::Node.new_element(hash.wrapper))
|
|
161
159
|
hash.key.update_xml(node, k)
|
|
162
160
|
hash.value.update_xml(node, v)
|
|
163
161
|
end
|
|
164
|
-
xml
|
|
165
162
|
end
|
|
166
163
|
|
|
167
|
-
def
|
|
168
|
-
|
|
169
|
-
[
|
|
170
|
-
end
|
|
171
|
-
if block
|
|
172
|
-
vals.collect! do |(key, val)|
|
|
173
|
-
block.call(key, val)
|
|
174
|
-
end
|
|
164
|
+
def fetch_value(xml)
|
|
165
|
+
xml.search(xpath).collect do |e|
|
|
166
|
+
[hash.key.value(e), hash.value.value(e)]
|
|
175
167
|
end
|
|
176
|
-
vals.to_h
|
|
177
168
|
end
|
|
178
169
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
170
|
+
def apply_blocks(vals)
|
|
171
|
+
unless blocks.empty?
|
|
172
|
+
vals.collect! do |kvp|
|
|
173
|
+
super(kvp)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
vals.to_hash
|
|
182
177
|
end
|
|
183
178
|
end
|
|
184
179
|
|
|
185
|
-
class XMLObjectRef < XMLTextRef #
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
def initialize(accessor, args, &block)
|
|
189
|
-
super(accessor, args, &block)
|
|
190
|
-
@klass = args.type
|
|
191
|
-
end
|
|
180
|
+
class XMLObjectRef < XMLTextRef # :nodoc:
|
|
181
|
+
delegate :type, :to => :opts
|
|
192
182
|
|
|
183
|
+
private
|
|
193
184
|
# Updates the composed XML object in the given XML block to
|
|
194
185
|
# the value provided.
|
|
195
|
-
def
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
parent.child_add(value.to_xml(name))
|
|
186
|
+
def write_xml(xml, value)
|
|
187
|
+
unless array?
|
|
188
|
+
xml.child_add(value.to_xml(name))
|
|
199
189
|
else
|
|
200
190
|
value.each do |v|
|
|
201
|
-
|
|
191
|
+
xml.child_add(v.to_xml(name))
|
|
202
192
|
end
|
|
203
193
|
end
|
|
204
|
-
xml
|
|
205
194
|
end
|
|
206
195
|
|
|
207
|
-
def
|
|
208
|
-
|
|
196
|
+
def fetch_value(xml)
|
|
197
|
+
unless array?
|
|
209
198
|
if child = xml.search(xpath).first
|
|
210
199
|
instantiate(child)
|
|
211
200
|
end
|
|
212
201
|
else
|
|
213
|
-
|
|
202
|
+
xml.search(xpath).collect do |e|
|
|
214
203
|
instantiate(e)
|
|
215
204
|
end
|
|
216
|
-
|
|
217
|
-
end || default
|
|
218
|
-
block ? block.call(val) : val
|
|
205
|
+
end
|
|
219
206
|
end
|
|
220
207
|
|
|
221
|
-
private
|
|
222
208
|
def instantiate(elem)
|
|
223
|
-
if
|
|
224
|
-
|
|
209
|
+
if type.respond_to? :from_xml
|
|
210
|
+
type.from_xml(elem)
|
|
225
211
|
else
|
|
226
|
-
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
#
|
|
232
|
-
# Returns an XML::Node representing this object.
|
|
233
|
-
#
|
|
234
|
-
def to_xml(name = nil)
|
|
235
|
-
returning XML::Node.new_element(name || tag_name) do |root|
|
|
236
|
-
tag_refs.each do |ref|
|
|
237
|
-
if v = __send__(ref.accessor)
|
|
238
|
-
ref.update_xml(root, v)
|
|
239
|
-
end
|
|
212
|
+
type.new(elem)
|
|
240
213
|
end
|
|
241
214
|
end
|
|
242
215
|
end
|