lutaml-model 0.3.30 → 0.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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +34 -18
- data/README.adoc +172 -8
- data/lib/lutaml/model/attribute.rb +6 -2
- data/lib/lutaml/model/key_value_mapping.rb +0 -1
- data/lib/lutaml/model/key_value_mapping_rule.rb +3 -1
- data/lib/lutaml/model/mapping_rule.rb +14 -2
- data/lib/lutaml/model/serialize.rb +174 -61
- data/lib/lutaml/model/type/decimal.rb +5 -0
- data/lib/lutaml/model/type/time.rb +4 -4
- data/lib/lutaml/model/utils.rb +1 -1
- data/lib/lutaml/model/validation.rb +6 -2
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +1 -0
- data/lib/lutaml/model/xml_adapter/builder/oga.rb +180 -0
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +1 -0
- data/lib/lutaml/model/xml_adapter/oga/document.rb +20 -0
- data/lib/lutaml/model/xml_adapter/oga/element.rb +117 -0
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +77 -44
- data/lib/lutaml/model/xml_adapter/xml_document.rb +11 -9
- data/lib/lutaml/model/xml_mapping.rb +0 -1
- data/lib/lutaml/model/xml_mapping_rule.rb +16 -4
- data/spec/address_spec.rb +1 -0
- data/spec/fixtures/sample_model.rb +7 -0
- data/spec/lutaml/model/custom_model_spec.rb +47 -1
- data/spec/lutaml/model/custom_serialization_spec.rb +16 -0
- data/spec/lutaml/model/enum_spec.rb +131 -0
- data/spec/lutaml/model/included_spec.rb +192 -0
- data/spec/lutaml/model/mixed_content_spec.rb +48 -32
- data/spec/lutaml/model/multiple_mapping_spec.rb +329 -0
- data/spec/lutaml/model/ordered_content_spec.rb +1 -1
- data/spec/lutaml/model/render_nil_spec.rb +3 -2
- data/spec/lutaml/model/serializable_spec.rb +3 -3
- data/spec/lutaml/model/type/boolean_spec.rb +62 -0
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +11 -11
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +1 -1
- data/spec/lutaml/model/xml_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_mapping_spec.rb +24 -9
- data/spec/sample_model_spec.rb +114 -0
- metadata +9 -2
@@ -21,6 +21,7 @@ module Lutaml
|
|
21
21
|
|
22
22
|
def self.included(base)
|
23
23
|
base.extend(ClassMethods)
|
24
|
+
base.initialize_attrs(base)
|
24
25
|
end
|
25
26
|
|
26
27
|
module ClassMethods
|
@@ -28,14 +29,18 @@ module Lutaml
|
|
28
29
|
|
29
30
|
def inherited(subclass)
|
30
31
|
super
|
32
|
+
subclass.initialize_attrs(self)
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
def included(base)
|
36
|
+
base.extend(ClassMethods)
|
37
|
+
base.initialize_attrs(self)
|
38
|
+
end
|
34
39
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
def initialize_attrs(source_class)
|
41
|
+
@mappings = Utils.deep_dup(source_class.instance_variable_get(:@mappings)) || {}
|
42
|
+
@attributes = Utils.deep_dup(source_class.instance_variable_get(:@attributes)) || {}
|
43
|
+
instance_variable_set(:@model, self)
|
39
44
|
end
|
40
45
|
|
41
46
|
def model(klass = nil)
|
@@ -81,16 +86,104 @@ module Lutaml
|
|
81
86
|
attr = Attribute.new(name, type, options)
|
82
87
|
attributes[name] = attr
|
83
88
|
|
84
|
-
|
85
|
-
|
89
|
+
if attr.enum?
|
90
|
+
add_enum_methods_to_model(
|
91
|
+
model,
|
92
|
+
name,
|
93
|
+
options[:values],
|
94
|
+
collection: options[:collection],
|
95
|
+
)
|
96
|
+
else
|
97
|
+
define_method(name) do
|
98
|
+
instance_variable_get(:"@#{name}")
|
99
|
+
end
|
100
|
+
|
101
|
+
define_method(:"#{name}=") do |value|
|
102
|
+
value_set_for(name)
|
103
|
+
instance_variable_set(:"@#{name}", attr.cast_value(value))
|
104
|
+
end
|
86
105
|
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_enum_methods_to_model(klass, enum_name, values, collection: false)
|
109
|
+
add_enum_getter_if_not_defined(klass, enum_name, collection)
|
110
|
+
add_enum_setter_if_not_defined(klass, enum_name, values, collection)
|
87
111
|
|
88
|
-
|
89
|
-
|
90
|
-
|
112
|
+
return unless values.all?(::String)
|
113
|
+
|
114
|
+
values.each do |value|
|
115
|
+
Utils.add_method_if_not_defined(klass, "#{value}?") do
|
116
|
+
curr_value = public_send(:"#{enum_name}")
|
117
|
+
|
118
|
+
if collection
|
119
|
+
curr_value.include?(value)
|
120
|
+
else
|
121
|
+
curr_value == value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
Utils.add_method_if_not_defined(klass, value.to_s) do
|
126
|
+
public_send(:"#{value}?")
|
127
|
+
end
|
128
|
+
|
129
|
+
Utils.add_method_if_not_defined(klass, "#{value}=") do |val|
|
130
|
+
value_set_for(enum_name)
|
131
|
+
enum_vals = public_send(:"#{enum_name}")
|
132
|
+
|
133
|
+
enum_vals = if !!val
|
134
|
+
if collection
|
135
|
+
enum_vals << value
|
136
|
+
else
|
137
|
+
[value]
|
138
|
+
end
|
139
|
+
elsif collection
|
140
|
+
enum_vals.delete(value)
|
141
|
+
enum_vals
|
142
|
+
else
|
143
|
+
[]
|
144
|
+
end
|
145
|
+
|
146
|
+
instance_variable_set(:"@#{enum_name}", enum_vals)
|
147
|
+
end
|
148
|
+
|
149
|
+
Utils.add_method_if_not_defined(klass, "#{value}!") do
|
150
|
+
public_send(:"#{value}=", true)
|
151
|
+
end
|
91
152
|
end
|
92
153
|
end
|
93
154
|
|
155
|
+
def add_enum_getter_if_not_defined(klass, enum_name, collection)
|
156
|
+
Utils.add_method_if_not_defined(klass, enum_name) do
|
157
|
+
i = instance_variable_get(:"@#{enum_name}") || []
|
158
|
+
|
159
|
+
if !collection && i.is_a?(Array)
|
160
|
+
i.first
|
161
|
+
else
|
162
|
+
i.uniq
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def add_enum_setter_if_not_defined(klass, enum_name, _values, collection)
|
168
|
+
Utils.add_method_if_not_defined(klass, "#{enum_name}=") do |value|
|
169
|
+
value = [value] unless value.is_a?(Array)
|
170
|
+
|
171
|
+
value_set_for(enum_name)
|
172
|
+
|
173
|
+
if collection
|
174
|
+
curr_value = public_send(:"#{enum_name}")
|
175
|
+
|
176
|
+
instance_variable_set(:"@#{enum_name}", curr_value + value)
|
177
|
+
else
|
178
|
+
instance_variable_set(:"@#{enum_name}", value)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def enums
|
184
|
+
attributes.select { |_, attr| attr.enum? }
|
185
|
+
end
|
186
|
+
|
94
187
|
Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
|
95
188
|
define_method(format) do |&block|
|
96
189
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
@@ -135,7 +228,7 @@ module Lutaml
|
|
135
228
|
end
|
136
229
|
end
|
137
230
|
|
138
|
-
define_method(:"as_#{format}") do |instance|
|
231
|
+
define_method(:"as_#{format}") do |instance, options = {}|
|
139
232
|
if instance.is_a?(Array)
|
140
233
|
return instance.map { |item| public_send(:"as_#{format}", item) }
|
141
234
|
end
|
@@ -147,7 +240,7 @@ module Lutaml
|
|
147
240
|
|
148
241
|
return instance if format == :xml
|
149
242
|
|
150
|
-
hash_representation(instance, format)
|
243
|
+
hash_representation(instance, format, options)
|
151
244
|
end
|
152
245
|
end
|
153
246
|
|
@@ -166,7 +259,7 @@ module Lutaml
|
|
166
259
|
mappings.each_with_object({}) do |rule, hash|
|
167
260
|
name = rule.to
|
168
261
|
next if except&.include?(name) || (only && !only.include?(name))
|
169
|
-
next if !rule.render_default? && instance.using_default?(rule.to)
|
262
|
+
next if !rule.custom_methods[:to] && (!rule.render_default? && instance.using_default?(rule.to))
|
170
263
|
|
171
264
|
next handle_delegate(instance, rule, hash, format) if rule.delegate
|
172
265
|
|
@@ -176,15 +269,18 @@ module Lutaml
|
|
176
269
|
|
177
270
|
value = instance.send(name)
|
178
271
|
|
179
|
-
next if value.nil? && !rule.render_nil
|
180
|
-
|
181
272
|
attribute = attributes[name]
|
182
273
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
274
|
+
value = if rule.child_mappings
|
275
|
+
generate_hash_from_child_mappings(value, rule.child_mappings)
|
276
|
+
else
|
277
|
+
attribute.serialize(value, format, options)
|
278
|
+
end
|
279
|
+
|
280
|
+
next if Utils.blank?(value) && !rule.render_nil
|
281
|
+
|
282
|
+
rule_from_name = rule.multiple_mappings? ? rule.from.first.to_s : rule.from.to_s
|
283
|
+
hash[rule_from_name] = value
|
188
284
|
end
|
189
285
|
end
|
190
286
|
|
@@ -194,39 +290,14 @@ module Lutaml
|
|
194
290
|
return if value.nil? && !rule.render_nil
|
195
291
|
|
196
292
|
attribute = instance.send(rule.delegate).class.attributes[name]
|
197
|
-
|
293
|
+
rule_from_name = rule.multiple_mappings? ? rule.from.first.to_s : rule.from.to_s
|
294
|
+
hash[rule_from_name] = attribute.serialize(value, format)
|
198
295
|
end
|
199
296
|
|
200
297
|
def mappings_for(format)
|
201
298
|
mappings[format] || default_mappings(format)
|
202
299
|
end
|
203
300
|
|
204
|
-
def attr_value(attrs, name, attr_rule)
|
205
|
-
value = if attrs.key?(name.to_sym)
|
206
|
-
attrs[name.to_sym]
|
207
|
-
elsif attrs.key?(name.to_s)
|
208
|
-
attrs[name.to_s]
|
209
|
-
else
|
210
|
-
attr_rule.default
|
211
|
-
end
|
212
|
-
|
213
|
-
if attr_rule.collection? || value.is_a?(Array)
|
214
|
-
(value || []).map do |v|
|
215
|
-
if v.is_a?(Hash)
|
216
|
-
attr_rule.type.new(v)
|
217
|
-
else
|
218
|
-
# TODO: This code is problematic because Type.cast does not know
|
219
|
-
# about all the types.
|
220
|
-
Lutaml::Model::Type.cast(v, attr_rule.type)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
else
|
224
|
-
# TODO: This code is problematic because Type.cast does not know
|
225
|
-
# about all the types.
|
226
|
-
Lutaml::Model::Type.cast(value, attr_rule.type)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
301
|
def default_mappings(format)
|
231
302
|
klass = format == :xml ? XmlMapping : KeyValueMapping
|
232
303
|
|
@@ -325,8 +396,7 @@ module Lutaml
|
|
325
396
|
mappings = mappings_for(:xml).mappings
|
326
397
|
|
327
398
|
if doc.is_a?(Array)
|
328
|
-
raise "May be `collection: true` is"
|
329
|
-
"missing for #{self} in #{options[:caller_class]}"
|
399
|
+
raise "May be `collection: true` is missing for #{self} in #{options[:caller_class]}"
|
330
400
|
end
|
331
401
|
|
332
402
|
if instance.respond_to?(:ordered=) && doc.is_a?(Lutaml::Model::MappingHash)
|
@@ -350,17 +420,18 @@ module Lutaml
|
|
350
420
|
|
351
421
|
attr = attribute_for_rule(rule)
|
352
422
|
|
423
|
+
namespaced_names = rule.namespaced_names(options[:default_namespace])
|
424
|
+
|
353
425
|
value = if rule.raw_mapping?
|
354
426
|
doc.node.inner_xml
|
355
427
|
elsif rule.content_mapping?
|
356
428
|
doc[rule.content_key]
|
357
|
-
elsif doc.
|
358
|
-
doc
|
429
|
+
elsif key = (namespaced_names & doc.keys).first
|
430
|
+
doc[key]
|
359
431
|
else
|
360
432
|
defaults_used << rule.to
|
361
433
|
attr&.default || rule.to_value_for(instance)
|
362
434
|
end
|
363
|
-
|
364
435
|
value = normalize_xml_value(value, rule, attr, options)
|
365
436
|
rule.deserialize(instance, value, attributes, self)
|
366
437
|
end
|
@@ -379,13 +450,19 @@ module Lutaml
|
|
379
450
|
|
380
451
|
attr = attribute_for_rule(rule)
|
381
452
|
|
382
|
-
|
383
|
-
doc[rule.name] || doc[rule.name.to_sym]
|
384
|
-
else
|
385
|
-
attr.default
|
386
|
-
end
|
453
|
+
names = rule.multiple_mappings? ? rule.name : [rule.name]
|
387
454
|
|
388
|
-
|
455
|
+
value = names.collect do |rule_name|
|
456
|
+
if doc.key?(rule_name.to_s)
|
457
|
+
doc[rule_name.to_s]
|
458
|
+
elsif doc.key?(rule_name.to_sym)
|
459
|
+
doc[rule_name.to_sym]
|
460
|
+
else
|
461
|
+
attr&.default
|
462
|
+
end
|
463
|
+
end.compact.first
|
464
|
+
|
465
|
+
if rule.using_custom_methods?
|
389
466
|
if Utils.present?(value)
|
390
467
|
value = new.send(rule.custom_methods[:from], instance, value)
|
391
468
|
end
|
@@ -479,7 +556,7 @@ module Lutaml
|
|
479
556
|
|
480
557
|
self.class.attributes.each do |name, attr|
|
481
558
|
value = if attrs.key?(name) || attrs.key?(name.to_s)
|
482
|
-
|
559
|
+
attr_value(attrs, name, attr)
|
483
560
|
else
|
484
561
|
using_default_for(name)
|
485
562
|
attr.default
|
@@ -490,7 +567,35 @@ module Lutaml
|
|
490
567
|
value = []
|
491
568
|
end
|
492
569
|
|
493
|
-
|
570
|
+
default = using_default?(name)
|
571
|
+
public_send(:"#{name}=", self.class.ensure_utf8(value))
|
572
|
+
using_default_for(name) if default
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
def attr_value(attrs, name, attr_rule)
|
577
|
+
value = if attrs.key?(name.to_sym)
|
578
|
+
attrs[name.to_sym]
|
579
|
+
elsif attrs.key?(name.to_s)
|
580
|
+
attrs[name.to_s]
|
581
|
+
else
|
582
|
+
attr_rule.default
|
583
|
+
end
|
584
|
+
|
585
|
+
if attr_rule.collection? || value.is_a?(Array)
|
586
|
+
(value || []).map do |v|
|
587
|
+
if v.is_a?(Hash)
|
588
|
+
attr_rule.type.new(v)
|
589
|
+
else
|
590
|
+
# TODO: This code is problematic because Type.cast does not know
|
591
|
+
# about all the types.
|
592
|
+
Lutaml::Model::Type.cast(v, attr_rule.type)
|
593
|
+
end
|
594
|
+
end
|
595
|
+
else
|
596
|
+
# TODO: This code is problematic because Type.cast does not know
|
597
|
+
# about all the types.
|
598
|
+
Lutaml::Model::Type.cast(value, attr_rule.type)
|
494
599
|
end
|
495
600
|
end
|
496
601
|
|
@@ -539,6 +644,14 @@ module Lutaml
|
|
539
644
|
hash[key.to_sym] || hash[key.to_s]
|
540
645
|
end
|
541
646
|
|
647
|
+
def pretty_print_instance_variables
|
648
|
+
(instance_variables - %i[@using_default]).sort
|
649
|
+
end
|
650
|
+
|
651
|
+
def to_yaml_hash
|
652
|
+
self.class.as_yaml(self)
|
653
|
+
end
|
654
|
+
|
542
655
|
Lutaml::Model::Config::AVAILABLE_FORMATS.each do |format|
|
543
656
|
define_method(:"to_#{format}") do |options = {}|
|
544
657
|
adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
|
@@ -34,10 +34,10 @@ module Lutaml
|
|
34
34
|
# value&.iso8601
|
35
35
|
# end
|
36
36
|
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
# YAML timestamp format (native)
|
38
|
+
def to_yaml
|
39
|
+
value&.iso8601
|
40
|
+
end
|
41
41
|
|
42
42
|
# # TOML time format (HH:MM:SS.mmm)
|
43
43
|
# def to_toml
|
data/lib/lutaml/model/utils.rb
CHANGED
@@ -4,9 +4,13 @@ module Lutaml
|
|
4
4
|
def validate
|
5
5
|
errors = []
|
6
6
|
self.class.attributes.each do |name, attr|
|
7
|
-
value =
|
7
|
+
value = public_send(:"#{name}")
|
8
8
|
begin
|
9
|
-
|
9
|
+
if value.respond_to?(:validate!)
|
10
|
+
value.validate!
|
11
|
+
else
|
12
|
+
attr.validate_value!(value)
|
13
|
+
end
|
10
14
|
rescue Lutaml::Model::InvalidValueError,
|
11
15
|
Lutaml::Model::CollectionCountOutOfRangeError,
|
12
16
|
PatternNotMatchedError => e
|
data/lib/lutaml/model/version.rb
CHANGED
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module XmlAdapter
|
6
|
+
module Builder
|
7
|
+
class Oga
|
8
|
+
def self.build(options = {}, &block)
|
9
|
+
if block_given?
|
10
|
+
XmlAdapter::Builder::Oga.new(options, &block)
|
11
|
+
else
|
12
|
+
XmlAdapter::Builder::Oga.new(options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :document, :current_node, :options
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
@document = XmlAdapter::Oga::Document.new
|
20
|
+
@current_node = @document
|
21
|
+
@options = options
|
22
|
+
yield(self) if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_element(name, attributes = {}, &block)
|
26
|
+
if @current_namespace && !name.start_with?("#{@current_namespace}:")
|
27
|
+
name = "#{@current_namespace}:#{name}"
|
28
|
+
end
|
29
|
+
|
30
|
+
if block_given?
|
31
|
+
element(name, attributes, &block)
|
32
|
+
else
|
33
|
+
element(name, attributes)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def element(name, attributes = {})
|
38
|
+
oga_element = ::Oga::XML::Element.new(name: name)
|
39
|
+
if block_given?
|
40
|
+
element_attributes(oga_element, attributes)
|
41
|
+
@current_node.children << oga_element
|
42
|
+
# Save previous node to reset the pointer for the rest of the iteration
|
43
|
+
previous_node = @current_node
|
44
|
+
# Set current node to new element as pointer for the block
|
45
|
+
@current_node = oga_element
|
46
|
+
yield(self)
|
47
|
+
# Reset the pointer for the rest of the iterations
|
48
|
+
@current_node = previous_node
|
49
|
+
end
|
50
|
+
oga_element
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_element(oga_element, child)
|
54
|
+
if child.is_a?(String)
|
55
|
+
current_element = oga_element.is_a?(XmlAdapter::Oga::Document) ? current_node : oga_element
|
56
|
+
add_xml_fragment(current_element, child)
|
57
|
+
elsif oga_element.is_a?(XmlAdapter::Oga::Document)
|
58
|
+
oga_element.children.last.children << child
|
59
|
+
else
|
60
|
+
oga_element.children << child
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_attribute(element, name, value)
|
65
|
+
attribute = ::Oga::XML::Attribute.new(
|
66
|
+
name: name,
|
67
|
+
value: value.to_s,
|
68
|
+
)
|
69
|
+
if element.is_a?(XmlAdapter::Oga::Document)
|
70
|
+
element.children.last.attributes << attribute
|
71
|
+
else
|
72
|
+
element.attributes << attribute
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_and_add_element(
|
77
|
+
element_name,
|
78
|
+
prefix: (prefix_unset = true
|
79
|
+
nil),
|
80
|
+
attributes: {},
|
81
|
+
&block
|
82
|
+
)
|
83
|
+
@current_namespace = nil if prefix.nil? && !prefix_unset
|
84
|
+
prefixed_name = if prefix
|
85
|
+
"#{prefix}:#{element_name}"
|
86
|
+
elsif @current_namespace && !element_name.start_with?("#{@current_namespace}:")
|
87
|
+
"#{@current_namespace}:#{element_name}"
|
88
|
+
else
|
89
|
+
element_name
|
90
|
+
end
|
91
|
+
|
92
|
+
if block_given?
|
93
|
+
element(prefixed_name, attributes, &block)
|
94
|
+
else
|
95
|
+
element(prefixed_name, attributes)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def <<(text)
|
100
|
+
@current_node.text(text)
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_xml_fragment(element, content)
|
104
|
+
fragment = "<fragment>#{content}</fragment>"
|
105
|
+
parsed_fragment = ::Oga.parse_xml(fragment)
|
106
|
+
parsed_children = parsed_fragment.children.first.children
|
107
|
+
if element.is_a?(XmlAdapter::Oga::Document)
|
108
|
+
element.children.last.children += parsed_children
|
109
|
+
else
|
110
|
+
element.children += parsed_children
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_text(element, text, cdata: false)
|
115
|
+
return add_cdata(element, text) if cdata
|
116
|
+
|
117
|
+
oga_text = ::Oga::XML::Text.new(text: text.to_s)
|
118
|
+
if element.is_a?(XmlAdapter::Oga::Document)
|
119
|
+
children = element.children
|
120
|
+
children.empty? ? children << oga_text : children.last.children << oga_text
|
121
|
+
else
|
122
|
+
element.children << oga_text
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_cdata(element, value)
|
127
|
+
oga_cdata = ::Oga::XML::CData.new(text: value.to_s)
|
128
|
+
if element.is_a?(XmlAdapter::Oga::Document)
|
129
|
+
element.children.last.children << oga_cdata
|
130
|
+
else
|
131
|
+
element.children << oga_cdata
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def add_namespace_prefix(prefix)
|
136
|
+
@current_namespace = prefix
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
140
|
+
def parent
|
141
|
+
@document
|
142
|
+
end
|
143
|
+
|
144
|
+
def text(value = nil)
|
145
|
+
return @current_node.inner_text if value.nil?
|
146
|
+
|
147
|
+
str = value.is_a?(Array) ? value.join : value
|
148
|
+
@current_node.children << ::Oga::XML::Text.new(text: str)
|
149
|
+
end
|
150
|
+
|
151
|
+
def method_missing(method_name, *args)
|
152
|
+
if block_given?
|
153
|
+
@current_node.public_send(method_name, *args) do
|
154
|
+
yield(self)
|
155
|
+
end
|
156
|
+
else
|
157
|
+
@current_node.public_send(method_name, *args)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def respond_to_missing?(method_name, include_private = false)
|
162
|
+
@current_node.respond_to?(method_name) || super
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def element_attributes(oga_element, attributes)
|
168
|
+
oga_element.attributes = attributes.map do |name, value|
|
169
|
+
::Oga::XML::Attribute.new(
|
170
|
+
name: name,
|
171
|
+
value: value,
|
172
|
+
element: oga_element,
|
173
|
+
)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -43,6 +43,7 @@ module Lutaml
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def create_and_add_element(element_name, prefix: nil, attributes: {})
|
46
|
+
element_name = element_name.first if element_name.is_a?(Array)
|
46
47
|
prefixed_name = if prefix
|
47
48
|
"#{prefix}:#{element_name}"
|
48
49
|
elsif @current_namespace && !element_name.start_with?("#{@current_namespace}:")
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module XmlAdapter
|
6
|
+
module Oga
|
7
|
+
class Document < ::Oga::XML::Document
|
8
|
+
def initialize(options = {})
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def text(value = nil)
|
13
|
+
children << ::Oga::XML::Text.new(text: value)
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|