lutaml-model 0.3.5 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +119 -12
- data/README.adoc +430 -21
- data/lib/lutaml/model/attribute.rb +27 -0
- data/lib/lutaml/model/config.rb +82 -1
- data/lib/lutaml/model/error/unknown_adapter_type_error.rb +16 -0
- data/lib/lutaml/model/error.rb +1 -0
- data/lib/lutaml/model/serialize.rb +75 -126
- data/lib/lutaml/model/type.rb +0 -24
- data/lib/lutaml/model/utils.rb +45 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +73 -0
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +89 -0
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +16 -90
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +14 -93
- data/lib/lutaml/model/xml_adapter/xml_document.rb +89 -0
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +0 -12
- data/lib/lutaml/model.rb +3 -2
- metadata +6 -3
- data/lib/lutaml/model/type/json.rb +0 -34
@@ -13,8 +13,6 @@ require_relative "comparable_model"
|
|
13
13
|
module Lutaml
|
14
14
|
module Model
|
15
15
|
module Serialize
|
16
|
-
FORMATS = %i[xml json yaml toml].freeze
|
17
|
-
|
18
16
|
include ComparableModel
|
19
17
|
|
20
18
|
def self.included(base)
|
@@ -73,7 +71,7 @@ module Lutaml
|
|
73
71
|
attr.options[:values].include?(value)
|
74
72
|
end
|
75
73
|
|
76
|
-
|
74
|
+
Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
|
77
75
|
define_method(format) do |&block|
|
78
76
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
79
77
|
mappings[format] = klass.new
|
@@ -87,9 +85,8 @@ module Lutaml
|
|
87
85
|
define_method(:"from_#{format}") do |data|
|
88
86
|
adapter = Lutaml::Model::Config.send(:"#{format}_adapter")
|
89
87
|
doc = adapter.parse(data)
|
90
|
-
|
91
|
-
|
92
|
-
generate_model_object(self, mapped_attrs)
|
88
|
+
|
89
|
+
apply_mappings(doc.to_h, format)
|
93
90
|
end
|
94
91
|
|
95
92
|
define_method(:"to_#{format}") do |instance|
|
@@ -120,13 +117,14 @@ module Lutaml
|
|
120
117
|
name = rule.to
|
121
118
|
next if except&.include?(name) || (only && !only.include?(name))
|
122
119
|
|
123
|
-
next handle_delegate(instance, rule, hash) if rule.delegate
|
120
|
+
next handle_delegate(instance, rule, hash, format) if rule.delegate
|
124
121
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
122
|
+
if rule.custom_methods[:to]
|
123
|
+
next instance.send(rule.custom_methods[:to], instance,
|
124
|
+
hash)
|
125
|
+
end
|
126
|
+
|
127
|
+
value = instance.send(name)
|
130
128
|
|
131
129
|
next if value.nil? && !rule.render_nil
|
132
130
|
|
@@ -134,68 +132,27 @@ module Lutaml
|
|
134
132
|
|
135
133
|
hash[rule.from] = if rule.child_mappings
|
136
134
|
generate_hash_from_child_mappings(value, rule.child_mappings)
|
137
|
-
elsif value.is_a?(Array)
|
138
|
-
value.map do |v|
|
139
|
-
if attribute.type <= Serialize
|
140
|
-
attribute.type.hash_representation(v, format, options)
|
141
|
-
else
|
142
|
-
attribute.type.serialize(v)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
elsif attribute.type <= Serialize
|
146
|
-
attribute.type.hash_representation(value, format, options)
|
147
135
|
else
|
148
|
-
attribute.
|
136
|
+
attribute.serialize(value, format, options)
|
149
137
|
end
|
150
138
|
end
|
151
139
|
end
|
152
140
|
|
153
|
-
def handle_delegate(instance, rule, hash)
|
141
|
+
def handle_delegate(instance, rule, hash, format)
|
154
142
|
name = rule.to
|
155
143
|
value = instance.send(rule.delegate).send(name)
|
156
144
|
return if value.nil? && !rule.render_nil
|
157
145
|
|
158
146
|
attribute = instance.send(rule.delegate).class.attributes[name]
|
159
|
-
hash[rule.from] =
|
160
|
-
when Array
|
161
|
-
value.map do |v|
|
162
|
-
if v.is_a?(Serialize)
|
163
|
-
hash_representation(v, format, options)
|
164
|
-
else
|
165
|
-
attribute.type.serialize(v)
|
166
|
-
end
|
167
|
-
end
|
168
|
-
else
|
169
|
-
if value.is_a?(Serialize)
|
170
|
-
hash_representation(value, format, options)
|
171
|
-
else
|
172
|
-
attribute.type.serialize(value)
|
173
|
-
end
|
174
|
-
end
|
147
|
+
hash[rule.from] = attribute.serialize(value, format)
|
175
148
|
end
|
176
149
|
|
177
150
|
def mappings_for(format)
|
178
151
|
mappings[format] || default_mappings(format)
|
179
152
|
end
|
180
153
|
|
181
|
-
def generate_model_object(type, mapped_attrs)
|
182
|
-
return type.model.new(mapped_attrs) if self == model
|
183
|
-
|
184
|
-
instance = type.model.new
|
185
|
-
|
186
|
-
type.attributes.each do |name, attr|
|
187
|
-
value = attr_value(mapped_attrs, name, attr)
|
188
|
-
|
189
|
-
instance.send(:"#{name}=", ensure_utf8(value))
|
190
|
-
end
|
191
|
-
|
192
|
-
instance
|
193
|
-
end
|
194
|
-
|
195
154
|
def attr_value(attrs, name, attr_rule)
|
196
|
-
value = if attrs.key?(name)
|
197
|
-
attrs[name]
|
198
|
-
elsif attrs.key?(name.to_sym)
|
155
|
+
value = if attrs.key?(name.to_sym)
|
199
156
|
attrs[name.to_sym]
|
200
157
|
elsif attrs.key?(name.to_s)
|
201
158
|
attrs[name.to_s]
|
@@ -213,8 +170,6 @@ module Lutaml
|
|
213
170
|
Lutaml::Model::Type.cast(v, attr_rule.type)
|
214
171
|
end
|
215
172
|
end
|
216
|
-
elsif value.is_a?(Hash) && attr_rule.type != Lutaml::Model::Type::Hash
|
217
|
-
generate_model_object(attr_rule.type, value)
|
218
173
|
else
|
219
174
|
# TODO: This code is problematic because Type.cast does not know
|
220
175
|
# about all the types.
|
@@ -281,11 +236,12 @@ module Lutaml
|
|
281
236
|
hash
|
282
237
|
end
|
283
238
|
|
284
|
-
def apply_mappings(doc, format)
|
285
|
-
|
239
|
+
def apply_mappings(doc, format, options = {})
|
240
|
+
instance = options[:instance] || model.new
|
241
|
+
return apply_xml_mapping(doc, instance, options) if format == :xml
|
286
242
|
|
287
243
|
mappings = mappings_for(format).mappings
|
288
|
-
mappings.
|
244
|
+
mappings.each do |rule|
|
289
245
|
attr = if rule.delegate
|
290
246
|
attributes[rule.delegate].type.attributes[rule.to]
|
291
247
|
else
|
@@ -294,50 +250,51 @@ module Lutaml
|
|
294
250
|
|
295
251
|
raise "Attribute '#{rule.to}' not found in #{self}" unless attr
|
296
252
|
|
297
|
-
value = if rule.
|
298
|
-
new.send(rule.custom_methods[:from], hash, doc)
|
299
|
-
elsif doc.key?(rule.name) || doc.key?(rule.name.to_sym)
|
253
|
+
value = if doc.key?(rule.name) || doc.key?(rule.name.to_sym)
|
300
254
|
doc[rule.name] || doc[rule.name.to_sym]
|
301
255
|
else
|
302
256
|
attr.default
|
303
257
|
end
|
304
258
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
value = (value || []).map do |v|
|
309
|
-
attr.type <= Serialize ? attr.type.apply_mappings(v, format) : v
|
310
|
-
end
|
311
|
-
elsif value.is_a?(Hash) && attr.type != Lutaml::Model::Type::Hash
|
312
|
-
value = attr.type.apply_mappings(value, format)
|
259
|
+
if rule.custom_methods[:from]
|
260
|
+
value = new.send(rule.custom_methods[:from], instance, value)
|
261
|
+
next
|
313
262
|
end
|
314
263
|
|
264
|
+
value = apply_child_mappings(value, rule.child_mappings)
|
265
|
+
value = attr.cast(value, format)
|
266
|
+
|
315
267
|
if rule.delegate
|
316
|
-
|
317
|
-
|
268
|
+
if instance.public_send(rule.delegate).nil?
|
269
|
+
instance.public_send(:"#{rule.delegate}=",
|
270
|
+
attributes[rule.delegate].type.new)
|
271
|
+
end
|
272
|
+
instance.public_send(rule.delegate).public_send(:"#{rule.to}=",
|
273
|
+
value)
|
318
274
|
else
|
319
|
-
|
275
|
+
instance.public_send(:"#{rule.to}=", value)
|
320
276
|
end
|
321
277
|
end
|
278
|
+
|
279
|
+
instance
|
322
280
|
end
|
323
281
|
|
324
|
-
def apply_xml_mapping(doc,
|
325
|
-
return unless doc
|
282
|
+
def apply_xml_mapping(doc, instance, options = {})
|
283
|
+
return instance unless doc
|
326
284
|
|
327
285
|
mappings = mappings_for(:xml).mappings
|
328
286
|
|
329
287
|
if doc.is_a?(Array)
|
330
288
|
raise "May be `collection: true` is" \
|
331
|
-
"missing for #{self} in #{caller_class}"
|
289
|
+
"missing for #{self} in #{options[:caller_class]}"
|
332
290
|
end
|
333
291
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
mapping_from = []
|
292
|
+
if instance.respond_to?(:ordered=)
|
293
|
+
instance.element_order = doc.item_order
|
294
|
+
instance.ordered = mappings_for(:xml).mixed_content? || options[:mixed_content]
|
295
|
+
end
|
339
296
|
|
340
|
-
mappings.
|
297
|
+
mappings.each do |rule|
|
341
298
|
attr = attributes[rule.to]
|
342
299
|
raise "Attribute '#{rule.to}' not found in #{self}" unless attr
|
343
300
|
|
@@ -348,52 +305,38 @@ module Lutaml
|
|
348
305
|
doc[rule.name.to_s] || doc[rule.name.to_sym]
|
349
306
|
end
|
350
307
|
|
351
|
-
if
|
352
|
-
|
353
|
-
|
308
|
+
if value.is_a?(Array)
|
309
|
+
value = value.map do |v|
|
310
|
+
v.is_a?(Hash) && !(attr.type <= Serialize) ? v["text"] : v
|
354
311
|
end
|
355
|
-
|
356
|
-
value =
|
357
|
-
if attr.type <= Serialize
|
358
|
-
attr.type.apply_xml_mapping(v, caller_class: self, mixed_content: rule.mixed_content)
|
359
|
-
elsif v.is_a?(Hash)
|
360
|
-
v["text"]
|
361
|
-
else
|
362
|
-
v
|
363
|
-
end
|
364
|
-
end
|
365
|
-
elsif attr.type <= Serialize
|
366
|
-
value = attr.type.apply_xml_mapping(value, caller_class: self, mixed_content: rule.mixed_content)
|
367
|
-
else
|
368
|
-
if value.is_a?(Hash) && attr.type != Lutaml::Model::Type::Hash
|
369
|
-
value = value["text"]
|
370
|
-
end
|
371
|
-
|
372
|
-
value = attr.type.cast(value) unless is_content_mapping
|
312
|
+
elsif !(attr.type <= Serialize) && value.is_a?(Hash) && attr.type != Lutaml::Model::Type::Hash
|
313
|
+
value = value["text"]
|
373
314
|
end
|
374
315
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
else
|
384
|
-
mapping_hash[rule.to]
|
385
|
-
end
|
316
|
+
unless is_content_mapping
|
317
|
+
value = attr.cast(
|
318
|
+
value,
|
319
|
+
:xml,
|
320
|
+
caller_class: self,
|
321
|
+
mixed_content: rule.mixed_content,
|
322
|
+
)
|
323
|
+
end
|
386
324
|
|
387
|
-
|
325
|
+
if rule.custom_methods[:from]
|
326
|
+
new.send(rule.custom_methods[:from], instance, value)
|
327
|
+
else
|
328
|
+
instance.public_send(:"#{rule.to}=", value)
|
329
|
+
end
|
388
330
|
end
|
389
331
|
|
390
|
-
|
332
|
+
instance
|
391
333
|
end
|
392
334
|
|
393
335
|
def ensure_utf8(value)
|
394
336
|
case value
|
395
337
|
when String
|
396
|
-
value.encode("UTF-8", invalid: :replace, undef: :replace,
|
338
|
+
value.encode("UTF-8", invalid: :replace, undef: :replace,
|
339
|
+
replace: "")
|
397
340
|
when Array
|
398
341
|
value.map { |v| ensure_utf8(v) }
|
399
342
|
when Hash
|
@@ -408,7 +351,7 @@ module Lutaml
|
|
408
351
|
end
|
409
352
|
end
|
410
353
|
|
411
|
-
|
354
|
+
attr_accessor :element_order
|
412
355
|
|
413
356
|
def initialize(attrs = {})
|
414
357
|
return unless self.class.attributes
|
@@ -431,22 +374,27 @@ module Lutaml
|
|
431
374
|
@ordered
|
432
375
|
end
|
433
376
|
|
377
|
+
def ordered=(ordered)
|
378
|
+
@ordered = ordered
|
379
|
+
end
|
380
|
+
|
434
381
|
def key_exist?(hash, key)
|
435
|
-
hash.key?(key
|
382
|
+
hash.key?(key.to_sym) || hash.key?(key.to_s)
|
436
383
|
end
|
437
384
|
|
438
385
|
def key_value(hash, key)
|
439
|
-
hash[key
|
386
|
+
hash[key.to_sym] || hash[key.to_s]
|
440
387
|
end
|
441
388
|
|
442
|
-
|
389
|
+
Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
|
443
390
|
define_method(:"to_#{format}") do |options = {}|
|
444
391
|
validate
|
445
392
|
adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
|
446
393
|
representation = if format == :xml
|
447
394
|
self
|
448
395
|
else
|
449
|
-
self.class.hash_representation(self, format,
|
396
|
+
self.class.hash_representation(self, format,
|
397
|
+
options)
|
450
398
|
end
|
451
399
|
|
452
400
|
adapter.new(representation).public_send(:"to_#{format}", options)
|
@@ -457,7 +405,8 @@ module Lutaml
|
|
457
405
|
self.class.attributes.each do |name, attr|
|
458
406
|
value = send(name)
|
459
407
|
unless self.class.attr_value_valid?(name, value)
|
460
|
-
raise Lutaml::Model::InvalidValueError.new(name, value,
|
408
|
+
raise Lutaml::Model::InvalidValueError.new(name, value,
|
409
|
+
attr.options[:values])
|
461
410
|
end
|
462
411
|
end
|
463
412
|
end
|
data/lib/lutaml/model/type.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
require "date"
|
2
2
|
require "bigdecimal"
|
3
|
-
require "securerandom"
|
4
|
-
require "uri"
|
5
|
-
require "ipaddr"
|
6
3
|
|
7
4
|
module Lutaml
|
8
5
|
module Model
|
@@ -20,12 +17,6 @@ module Lutaml
|
|
20
17
|
Boolean
|
21
18
|
Decimal
|
22
19
|
Hash
|
23
|
-
Uuid
|
24
|
-
Symbol
|
25
|
-
Binary
|
26
|
-
Url
|
27
|
-
IpAddress
|
28
|
-
Json
|
29
20
|
).each do |t|
|
30
21
|
class_eval <<~HEREDOC, __FILE__, __LINE__ + 1
|
31
22
|
class #{t} # class Integer
|
@@ -72,18 +63,6 @@ module Lutaml
|
|
72
63
|
BigDecimal(value.to_s)
|
73
64
|
when "Hash"
|
74
65
|
normalize_hash(Hash(value))
|
75
|
-
when "Uuid"
|
76
|
-
UUID_REGEX.match?(value) ? value : SecureRandom.uuid
|
77
|
-
when "Symbol"
|
78
|
-
value.to_sym
|
79
|
-
when "Binary"
|
80
|
-
value.force_encoding("BINARY")
|
81
|
-
when "Url"
|
82
|
-
URI.parse(value.to_s)
|
83
|
-
when "IpAddress"
|
84
|
-
IPAddr.new(value.to_s)
|
85
|
-
when "Json"
|
86
|
-
Json.cast(value)
|
87
66
|
else
|
88
67
|
value
|
89
68
|
end
|
@@ -107,8 +86,6 @@ module Lutaml
|
|
107
86
|
value.to_s("F")
|
108
87
|
when "Hash"
|
109
88
|
Hash(value)
|
110
|
-
when "Json"
|
111
|
-
value.to_json
|
112
89
|
else
|
113
90
|
value.to_s
|
114
91
|
end
|
@@ -145,4 +122,3 @@ end
|
|
145
122
|
|
146
123
|
require_relative "type/time_without_date"
|
147
124
|
require_relative "type/date_time"
|
148
|
-
require_relative "type/json"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Utils
|
6
|
+
class << self
|
7
|
+
# Convert string to camel case
|
8
|
+
def camel_case(str)
|
9
|
+
return "" if str.nil? || str.empty?
|
10
|
+
|
11
|
+
str.split("/").map { |part| camelize_part(part) }.join("::")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Convert string to class name
|
15
|
+
def classify(str)
|
16
|
+
str = str.to_s.delete(".")
|
17
|
+
str = str.sub(/^[a-z\d]*/) { |match| camel_case(match) || match }
|
18
|
+
|
19
|
+
str.gsub("::", "/").gsub(%r{(?:_|-|(/))([a-z\d]*)}i) do
|
20
|
+
word = Regexp.last_match(2)
|
21
|
+
substituted = camel_case(word) || word
|
22
|
+
Regexp.last_match(1) ? "::#{substituted}" : substituted
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Convert string to snake case
|
27
|
+
def snake_case(str)
|
28
|
+
str = str.to_s.tr(".", "_")
|
29
|
+
return str unless /[A-Z-]|::/.match?(str)
|
30
|
+
|
31
|
+
str.gsub("::", "/")
|
32
|
+
.gsub(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { "#{$1 || $2}_" }
|
33
|
+
.tr("-", "_")
|
34
|
+
.downcase
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def camelize_part(part)
|
40
|
+
part.gsub(/(?:_|-|^)([a-z\d])/i) { $1.upcase }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/lutaml/model/version.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
module XmlAdapter
|
4
|
+
module Builder
|
5
|
+
class Nokogiri
|
6
|
+
def self.build(options = {})
|
7
|
+
if block_given?
|
8
|
+
::Nokogiri::XML::Builder.new(options) do |xml|
|
9
|
+
yield(new(xml))
|
10
|
+
end
|
11
|
+
else
|
12
|
+
new(::Nokogiri::XML::Builder.new(options))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :xml
|
17
|
+
|
18
|
+
def initialize(xml)
|
19
|
+
@xml = xml
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_element(name, attributes = {})
|
23
|
+
xml.doc.create_element(name, attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_element(element, child)
|
27
|
+
element.add_child(child)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_and_add_element(element_name, prefix: nil, attributes: {})
|
31
|
+
add_namespace_prefix(prefix) if prefix
|
32
|
+
|
33
|
+
if block_given?
|
34
|
+
public_send(element_name, attributes) do
|
35
|
+
yield(self)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
public_send(element_name, attributes)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_text(element, text)
|
43
|
+
if element.is_a?(self.class)
|
44
|
+
element = element.xml.parent
|
45
|
+
end
|
46
|
+
|
47
|
+
add_element(element, ::Nokogiri::XML::Text.new(text.to_s, xml.doc))
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_namespace_prefix(prefix)
|
51
|
+
xml[prefix] if prefix
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(method_name, *args)
|
57
|
+
if block_given?
|
58
|
+
xml.public_send(method_name, *args) do
|
59
|
+
yield(xml)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
xml.public_send(method_name, *args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def respond_to_missing?(method_name, include_private = false)
|
67
|
+
xml.respond_to?(method_name) || super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
module XmlAdapter
|
4
|
+
module Builder
|
5
|
+
class Ox
|
6
|
+
def self.build(options = {})
|
7
|
+
if block_given?
|
8
|
+
::Ox::Builder.new(options) do |xml|
|
9
|
+
yield(new(xml))
|
10
|
+
end
|
11
|
+
else
|
12
|
+
new(::Ox::Builder.new(options))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :xml
|
17
|
+
|
18
|
+
def initialize(xml)
|
19
|
+
@xml = xml
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_element(name, attributes = {})
|
23
|
+
if block_given?
|
24
|
+
xml.element(name, attributes) do |element|
|
25
|
+
yield(self.class.new(element))
|
26
|
+
end
|
27
|
+
else
|
28
|
+
xml.element(name, attributes)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_element(element, child)
|
33
|
+
element << child
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_and_add_element(element_name, prefix: nil, attributes: {})
|
37
|
+
prefixed_name = if prefix
|
38
|
+
"#{prefix}:#{element_name}"
|
39
|
+
else
|
40
|
+
element_name
|
41
|
+
end
|
42
|
+
|
43
|
+
if block_given?
|
44
|
+
xml.element(prefixed_name, attributes) do |element|
|
45
|
+
yield(self.class.new(element))
|
46
|
+
end
|
47
|
+
else
|
48
|
+
xml.element(prefixed_name, attributes)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def <<(text)
|
53
|
+
xml.text(text)
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_text(element, text)
|
57
|
+
element << text
|
58
|
+
end
|
59
|
+
|
60
|
+
# Add XML namespace to document
|
61
|
+
#
|
62
|
+
# Ox doesn't support XML namespaces so this method does nothing.
|
63
|
+
def add_namespace_prefix(_prefix)
|
64
|
+
# :noop:
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def parent
|
69
|
+
xml
|
70
|
+
end
|
71
|
+
|
72
|
+
def method_missing(method_name, *args)
|
73
|
+
if block_given?
|
74
|
+
xml.public_send(method_name, *args) do
|
75
|
+
yield(xml)
|
76
|
+
end
|
77
|
+
else
|
78
|
+
xml.public_send(method_name, *args)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def respond_to_missing?(method_name, include_private = false)
|
83
|
+
xml.respond_to?(method_name) || super
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|