lutaml-model 0.3.6 → 0.3.8
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 +14 -12
- data/README.adoc +30 -26
- data/lib/lutaml/model/attribute.rb +27 -0
- data/lib/lutaml/model/serialize.rb +100 -127
- data/lib/lutaml/model/type.rb +2 -0
- 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 +19 -92
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +22 -94
- data/lib/lutaml/model/xml_adapter/xml_document.rb +111 -7
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +0 -12
- data/lib/lutaml/model.rb +1 -0
- metadata +5 -2
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
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "nokogiri"
|
2
2
|
require_relative "xml_document"
|
3
|
+
require_relative "builder/nokogiri"
|
3
4
|
|
4
5
|
module Lutaml
|
5
6
|
module Model
|
@@ -12,12 +13,13 @@ module Lutaml
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def to_xml(options = {})
|
15
|
-
builder = Nokogiri
|
16
|
+
builder = Builder::Nokogiri.build(encoding: "UTF-8") do |xml|
|
16
17
|
if root.is_a?(Lutaml::Model::XmlAdapter::NokogiriElement)
|
17
18
|
root.to_xml(xml)
|
18
19
|
else
|
19
20
|
mapper_class = options[:mapper_class] || @root.class
|
20
|
-
options[:xml_attributes] =
|
21
|
+
options[:xml_attributes] =
|
22
|
+
build_namespace_attributes(mapper_class)
|
21
23
|
build_element(xml, @root, options)
|
22
24
|
end
|
23
25
|
end
|
@@ -31,59 +33,6 @@ module Lutaml
|
|
31
33
|
|
32
34
|
private
|
33
35
|
|
34
|
-
def build_unordered_element(xml, element, options = {})
|
35
|
-
mapper_class = options[:mapper_class] || element.class
|
36
|
-
xml_mapping = mapper_class.mappings_for(:xml)
|
37
|
-
return xml unless xml_mapping
|
38
|
-
|
39
|
-
attributes = options[:xml_attributes] ||= {}
|
40
|
-
attributes = build_attributes(element,
|
41
|
-
xml_mapping).merge(attributes)&.compact
|
42
|
-
|
43
|
-
prefixed_xml = if options.key?(:namespace_prefix)
|
44
|
-
options[:namespace_prefix] ? xml[options[:namespace_prefix]] : xml
|
45
|
-
elsif xml_mapping.namespace_prefix
|
46
|
-
xml[xml_mapping.namespace_prefix]
|
47
|
-
else
|
48
|
-
xml
|
49
|
-
end
|
50
|
-
|
51
|
-
tag_name = options[:tag_name] || xml_mapping.root_element
|
52
|
-
prefixed_xml.public_send(tag_name, attributes) do
|
53
|
-
if options.key?(:namespace_prefix) && !options[:namespace_prefix]
|
54
|
-
xml.parent.namespace = nil
|
55
|
-
end
|
56
|
-
|
57
|
-
xml_mapping.elements.each do |element_rule|
|
58
|
-
attribute_def = attribute_definition_for(element, element_rule, mapper_class: mapper_class)
|
59
|
-
value = attribute_value_for(element, element_rule)
|
60
|
-
|
61
|
-
next if value.nil? && !element_rule.render_nil?
|
62
|
-
|
63
|
-
nsp_xml = element_rule.prefix ? xml[element_rule.prefix] : xml
|
64
|
-
|
65
|
-
if attribute_def.collection?
|
66
|
-
value.each do |v|
|
67
|
-
add_to_xml(nsp_xml, v, attribute_def, element_rule)
|
68
|
-
end
|
69
|
-
elsif !value.nil? || element_rule.render_nil?
|
70
|
-
add_to_xml(nsp_xml, value, attribute_def, element_rule)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
if (content_rule = xml_mapping.content_mapping)
|
75
|
-
text = element.send(content_rule.to)
|
76
|
-
text = text.join if text.is_a?(Array)
|
77
|
-
|
78
|
-
if content_rule.custom_methods[:to]
|
79
|
-
text = @root.send(content_rule.custom_methods[:to], @root, text)
|
80
|
-
end
|
81
|
-
|
82
|
-
prefixed_xml.text text
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
36
|
def build_ordered_element(xml, element, options = {})
|
88
37
|
mapper_class = options[:mapper_class] || element.class
|
89
38
|
xml_mapping = mapper_class.mappings_for(:xml)
|
@@ -114,49 +63,27 @@ module Lutaml
|
|
114
63
|
element_rule = xml_mapping.find_by_name(name)
|
115
64
|
next if element_rule.nil?
|
116
65
|
|
117
|
-
attribute_def = attribute_definition_for(element, element_rule,
|
66
|
+
attribute_def = attribute_definition_for(element, element_rule,
|
67
|
+
mapper_class: mapper_class)
|
118
68
|
value = attribute_value_for(element, element_rule)
|
119
|
-
nsp_xml = element_rule.prefix ? xml[element_rule.prefix] : xml
|
120
69
|
|
121
70
|
if element_rule == xml_mapping.content_mapping
|
122
71
|
text = element.send(xml_mapping.content_mapping.to)
|
123
72
|
text = text[curr_index] if text.is_a?(Array)
|
124
73
|
|
125
74
|
prefixed_xml.text text
|
126
|
-
elsif attribute_def.collection?
|
127
|
-
add_to_xml(nsp_xml, value[curr_index], attribute_def,
|
128
|
-
element_rule)
|
129
75
|
elsif !value.nil? || element_rule.render_nil?
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
if value && (attribute&.type&.<= Lutaml::Model::Serialize)
|
142
|
-
handle_nested_elements(
|
143
|
-
xml,
|
144
|
-
value,
|
145
|
-
rule: rule,
|
146
|
-
attribute: attribute,
|
147
|
-
)
|
148
|
-
else
|
149
|
-
xml.public_send(rule.name) do
|
150
|
-
if !value.nil?
|
151
|
-
serialized_value = attribute.type.serialize(value)
|
152
|
-
|
153
|
-
if attribute.type == Lutaml::Model::Type::Hash
|
154
|
-
serialized_value.each do |key, val|
|
155
|
-
xml.public_send(key) { xml.text val }
|
156
|
-
end
|
157
|
-
else
|
158
|
-
xml.text(serialized_value)
|
159
|
-
end
|
76
|
+
value = value[curr_index] if attribute_def.collection?
|
77
|
+
|
78
|
+
add_to_xml(
|
79
|
+
xml,
|
80
|
+
element_rule.prefix,
|
81
|
+
value,
|
82
|
+
options.merge(
|
83
|
+
attribute: attribute_def,
|
84
|
+
rule: element_rule,
|
85
|
+
),
|
86
|
+
)
|
160
87
|
end
|
161
88
|
end
|
162
89
|
end
|
@@ -205,7 +132,7 @@ module Lutaml
|
|
205
132
|
end
|
206
133
|
|
207
134
|
def to_xml(builder = nil)
|
208
|
-
builder ||= Nokogiri
|
135
|
+
builder ||= Builder::Nokogiri.build
|
209
136
|
|
210
137
|
if name == "text"
|
211
138
|
builder.text(text)
|
@@ -232,7 +159,7 @@ module Lutaml
|
|
232
159
|
end
|
233
160
|
end
|
234
161
|
|
235
|
-
def build_attributes(node)
|
162
|
+
def build_attributes(node, _options = {})
|
236
163
|
attrs = node.attributes.transform_values(&:value)
|
237
164
|
|
238
165
|
attrs.merge(build_namespace_attributes(node))
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "ox"
|
2
2
|
require_relative "xml_document"
|
3
|
+
require_relative "builder/ox"
|
3
4
|
|
4
5
|
module Lutaml
|
5
6
|
module Model
|
@@ -12,7 +13,7 @@ module Lutaml
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def to_xml(options = {})
|
15
|
-
builder = Ox
|
16
|
+
builder = Builder::Ox.build
|
16
17
|
|
17
18
|
if @root.is_a?(Lutaml::Model::XmlAdapter::OxElement)
|
18
19
|
@root.to_xml(builder)
|
@@ -22,66 +23,12 @@ module Lutaml
|
|
22
23
|
build_element(builder, @root, options)
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
-
xml_data = builder.to_s
|
26
|
+
xml_data = builder.xml.to_s
|
27
27
|
options[:declaration] ? declaration(options) + xml_data : xml_data
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
31
|
|
32
|
-
def build_unordered_element(builder, element, options = {})
|
33
|
-
mapper_class = options[:mapper_class] || element.class
|
34
|
-
xml_mapping = mapper_class.mappings_for(:xml)
|
35
|
-
return xml unless xml_mapping
|
36
|
-
|
37
|
-
attributes = build_attributes(element, xml_mapping).compact
|
38
|
-
|
39
|
-
tag_name = options[:tag_name] || xml_mapping.root_element
|
40
|
-
prefixed_name = if options.key?(:namespace_prefix)
|
41
|
-
[options[:namespace_prefix], tag_name].compact.join(":")
|
42
|
-
elsif xml_mapping.namespace_prefix
|
43
|
-
"#{xml_mapping.namespace_prefix}:#{tag_name}"
|
44
|
-
else
|
45
|
-
tag_name
|
46
|
-
end
|
47
|
-
|
48
|
-
builder.element(prefixed_name, attributes) do |el|
|
49
|
-
xml_mapping.elements.each do |element_rule|
|
50
|
-
attribute_def = attribute_definition_for(element, element_rule, mapper_class: mapper_class)
|
51
|
-
value = attribute_value_for(element, element_rule)
|
52
|
-
|
53
|
-
val = if attribute_def.collection?
|
54
|
-
value
|
55
|
-
elsif value || element_rule.render_nil?
|
56
|
-
[value]
|
57
|
-
else
|
58
|
-
[]
|
59
|
-
end
|
60
|
-
|
61
|
-
val.each do |v|
|
62
|
-
if attribute_def&.type&.<= Lutaml::Model::Serialize
|
63
|
-
handle_nested_elements(el, v, rule: element_rule, attribute: attribute_def)
|
64
|
-
else
|
65
|
-
builder.element(element_rule.prefixed_name) do |el|
|
66
|
-
el.text(attribute_def.type.serialize(v)) if v
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
if (content_rule = xml_mapping.content_mapping)
|
73
|
-
text = element.send(xml_mapping.content_mapping.to)
|
74
|
-
text = text.join if text.is_a?(Array)
|
75
|
-
|
76
|
-
if content_rule.custom_methods[:to]
|
77
|
-
text = @root.send(content_rule.custom_methods[:to], @root, text)
|
78
|
-
end
|
79
|
-
|
80
|
-
el.text text
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
32
|
def build_ordered_element(builder, element, options = {})
|
86
33
|
mapper_class = options[:mapper_class] || element.class
|
87
34
|
xml_mapping = mapper_class.mappings_for(:xml)
|
@@ -90,7 +37,8 @@ module Lutaml
|
|
90
37
|
attributes = build_attributes(element, xml_mapping).compact
|
91
38
|
|
92
39
|
tag_name = options[:tag_name] || xml_mapping.root_element
|
93
|
-
builder.
|
40
|
+
builder.create_and_add_element(tag_name,
|
41
|
+
attributes: attributes) do |el|
|
94
42
|
index_hash = {}
|
95
43
|
|
96
44
|
element.element_order.each do |name|
|
@@ -99,47 +47,27 @@ module Lutaml
|
|
99
47
|
|
100
48
|
element_rule = xml_mapping.find_by_name(name)
|
101
49
|
|
102
|
-
attribute_def = attribute_definition_for(element, element_rule,
|
50
|
+
attribute_def = attribute_definition_for(element, element_rule,
|
51
|
+
mapper_class: mapper_class)
|
103
52
|
value = attribute_value_for(element, element_rule)
|
104
53
|
|
105
54
|
if element_rule == xml_mapping.content_mapping
|
106
55
|
text = element.send(xml_mapping.content_mapping.to)
|
107
56
|
text = text[curr_index] if text.is_a?(Array)
|
108
57
|
|
109
|
-
el.
|
110
|
-
elsif attribute_def.collection?
|
111
|
-
add_to_xml(el, value[curr_index], attribute_def, element_rule)
|
58
|
+
el.add_text(el, text)
|
112
59
|
elsif !value.nil? || element_rule.render_nil?
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
if value && (attribute&.type&.<= Lutaml::Model::Serialize)
|
125
|
-
handle_nested_elements(
|
126
|
-
xml,
|
127
|
-
value,
|
128
|
-
rule: rule,
|
129
|
-
attribute: attribute,
|
130
|
-
)
|
131
|
-
else
|
132
|
-
xml.element(rule.name) do |el|
|
133
|
-
if !value.nil?
|
134
|
-
serialized_value = attribute.type.serialize(value)
|
135
|
-
|
136
|
-
if attribute.type == Lutaml::Model::Type::Hash
|
137
|
-
serialized_value.each do |key, val|
|
138
|
-
el.element(key) { |child_el| child_el.text val }
|
139
|
-
end
|
140
|
-
else
|
141
|
-
el.text(serialized_value)
|
142
|
-
end
|
60
|
+
value = value[curr_index] if attribute_def.collection?
|
61
|
+
|
62
|
+
add_to_xml(
|
63
|
+
el,
|
64
|
+
nil,
|
65
|
+
value,
|
66
|
+
options.merge(
|
67
|
+
attribute: attribute_def,
|
68
|
+
rule: element_rule,
|
69
|
+
),
|
70
|
+
)
|
143
71
|
end
|
144
72
|
end
|
145
73
|
end
|
@@ -188,13 +116,13 @@ module Lutaml
|
|
188
116
|
end
|
189
117
|
|
190
118
|
def to_xml(builder = nil)
|
191
|
-
builder ||= Ox
|
119
|
+
builder ||= Builder::Ox.build
|
192
120
|
attrs = build_attributes(self)
|
193
121
|
|
194
122
|
if text?
|
195
|
-
builder.
|
123
|
+
builder.add_text(builder, text)
|
196
124
|
else
|
197
|
-
builder.
|
125
|
+
builder.create_and_add_element(name, attributes: attrs) do |el|
|
198
126
|
children.each { |child| child.to_xml(el) }
|
199
127
|
end
|
200
128
|
end
|
@@ -42,21 +42,24 @@ module Lutaml
|
|
42
42
|
@root.order
|
43
43
|
end
|
44
44
|
|
45
|
-
def handle_nested_elements(builder, value,
|
46
|
-
|
45
|
+
def handle_nested_elements(builder, value, options = {})
|
46
|
+
element_options = build_options_for_nested_elements(options)
|
47
47
|
|
48
48
|
case value
|
49
49
|
when Array
|
50
|
-
value.each { |val| build_element(builder, val,
|
50
|
+
value.each { |val| build_element(builder, val, element_options) }
|
51
51
|
else
|
52
|
-
build_element(builder, value,
|
52
|
+
build_element(builder, value, element_options)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def build_options_for_nested_elements(
|
56
|
+
def build_options_for_nested_elements(options = {})
|
57
|
+
attribute = options.delete(:attribute)
|
58
|
+
rule = options.delete(:rule)
|
59
|
+
|
57
60
|
return {} unless rule
|
58
61
|
|
59
|
-
options = {}
|
62
|
+
# options = {}
|
60
63
|
|
61
64
|
options[:namespace_prefix] = rule.prefix if rule&.namespace_set?
|
62
65
|
options[:mixed_content] = rule.mixed_content
|
@@ -97,6 +100,103 @@ module Lutaml
|
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
103
|
+
def add_to_xml(xml, prefix, value, options = {})
|
104
|
+
if value.is_a?(Array)
|
105
|
+
value.each do |item|
|
106
|
+
add_to_xml(xml, prefix, item, options)
|
107
|
+
end
|
108
|
+
|
109
|
+
return
|
110
|
+
end
|
111
|
+
|
112
|
+
attribute = options[:attribute]
|
113
|
+
rule = options[:rule]
|
114
|
+
|
115
|
+
if rule.custom_methods[:to]
|
116
|
+
@root.send(rule.custom_methods[:to], @root, xml.parent, xml)
|
117
|
+
return
|
118
|
+
end
|
119
|
+
|
120
|
+
if value && (attribute&.type&.<= Lutaml::Model::Serialize)
|
121
|
+
handle_nested_elements(
|
122
|
+
xml,
|
123
|
+
value,
|
124
|
+
options.merge({ rule: rule, attribute: attribute }),
|
125
|
+
)
|
126
|
+
else
|
127
|
+
xml.create_and_add_element(rule.name, prefix: prefix) do
|
128
|
+
if !value.nil?
|
129
|
+
serialized_value = attribute.type.serialize(value)
|
130
|
+
|
131
|
+
if attribute.type == Lutaml::Model::Type::Hash
|
132
|
+
serialized_value.each do |key, val|
|
133
|
+
xml.create_and_add_element(key) do |element|
|
134
|
+
element.text(val)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
else
|
138
|
+
xml.add_text(xml, serialized_value)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def build_unordered_element(xml, element, options = {})
|
146
|
+
mapper_class = options[:mapper_class] || element.class
|
147
|
+
xml_mapping = mapper_class.mappings_for(:xml)
|
148
|
+
return xml unless xml_mapping
|
149
|
+
|
150
|
+
attributes = options[:xml_attributes] ||= {}
|
151
|
+
attributes = build_attributes(element,
|
152
|
+
xml_mapping, options).merge(attributes)&.compact
|
153
|
+
|
154
|
+
prefix = if options.key?(:namespace_prefix)
|
155
|
+
options[:namespace_prefix]
|
156
|
+
elsif xml_mapping.namespace_prefix
|
157
|
+
xml_mapping.namespace_prefix
|
158
|
+
end
|
159
|
+
|
160
|
+
prefixed_xml = xml.add_namespace_prefix(prefix)
|
161
|
+
tag_name = options[:tag_name] || xml_mapping.root_element
|
162
|
+
|
163
|
+
xml.create_and_add_element(tag_name, prefix: prefix,
|
164
|
+
attributes: attributes) do
|
165
|
+
if options.key?(:namespace_prefix) && !options[:namespace_prefix]
|
166
|
+
xml.add_namespace_prefix(nil)
|
167
|
+
end
|
168
|
+
|
169
|
+
xml_mapping.elements.each do |element_rule|
|
170
|
+
attribute_def = attribute_definition_for(element, element_rule,
|
171
|
+
mapper_class: mapper_class)
|
172
|
+
|
173
|
+
value = attribute_value_for(element, element_rule)
|
174
|
+
|
175
|
+
next if value.nil? && !element_rule.render_nil?
|
176
|
+
|
177
|
+
value = [value] if attribute_def.collection? && !value.is_a?(Array)
|
178
|
+
|
179
|
+
add_to_xml(
|
180
|
+
xml,
|
181
|
+
element_rule.prefix,
|
182
|
+
value,
|
183
|
+
options.merge({ attribute: attribute_def, rule: element_rule }),
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
if (content_rule = xml_mapping.content_mapping)
|
188
|
+
if content_rule.custom_methods[:to]
|
189
|
+
@root.send(content_rule.custom_methods[:to], element,
|
190
|
+
prefixed_xml.parent, prefixed_xml)
|
191
|
+
else
|
192
|
+
text = element.send(content_rule.to)
|
193
|
+
text = text.join if text.is_a?(Array)
|
194
|
+
prefixed_xml.add_text(xml, text)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
100
200
|
def ordered?(element, options = {})
|
101
201
|
return false unless element.respond_to?(:element_order)
|
102
202
|
return element.ordered? if element.respond_to?(:ordered?)
|
@@ -142,10 +242,12 @@ module Lutaml
|
|
142
242
|
attrs
|
143
243
|
end
|
144
244
|
|
145
|
-
def build_attributes(element, xml_mapping)
|
245
|
+
def build_attributes(element, xml_mapping, options = {})
|
146
246
|
attrs = namespace_attributes(xml_mapping)
|
147
247
|
|
148
248
|
xml_mapping.attributes.each_with_object(attrs) do |mapping_rule, hash|
|
249
|
+
next if options[:except]&.include?(mapping_rule.to)
|
250
|
+
|
149
251
|
if mapping_rule.namespace
|
150
252
|
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
151
253
|
end
|
@@ -154,6 +256,8 @@ module Lutaml
|
|
154
256
|
end
|
155
257
|
|
156
258
|
xml_mapping.elements.each_with_object(attrs) do |mapping_rule, hash|
|
259
|
+
next if options[:except]&.include?(mapping_rule.to)
|
260
|
+
|
157
261
|
if mapping_rule.namespace
|
158
262
|
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
159
263
|
end
|
@@ -16,18 +16,6 @@ module Lutaml
|
|
16
16
|
def to_yaml(options = {})
|
17
17
|
YAML.dump(@attributes, options)
|
18
18
|
end
|
19
|
-
|
20
|
-
# TODO: Is this really needed?
|
21
|
-
def self.to_yaml(attributes, *args)
|
22
|
-
new(attributes).to_yaml(*args)
|
23
|
-
end
|
24
|
-
|
25
|
-
# TODO: Is this really needed?
|
26
|
-
def self.from_yaml(yaml, klass)
|
27
|
-
data = parse(yaml)
|
28
|
-
mapped_attrs = klass.send(:apply_mappings, data, :yaml)
|
29
|
-
klass.new(mapped_attrs)
|
30
|
-
end
|
31
19
|
end
|
32
20
|
end
|
33
21
|
end
|
data/lib/lutaml/model.rb
CHANGED