lutaml-model 0.3.1 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -5
- data/.rubocop_todo.yml +20 -101
- data/Gemfile +3 -18
- data/README.adoc +109 -6
- data/lib/lutaml/model/attribute.rb +15 -2
- data/lib/lutaml/model/config.rb +0 -1
- data/lib/lutaml/model/json_adapter/json_document.rb +20 -0
- data/lib/lutaml/model/json_adapter/json_object.rb +28 -0
- data/lib/lutaml/model/json_adapter/{multi_json.rb → multi_json_adapter.rb} +2 -3
- data/lib/lutaml/model/json_adapter/{standard.rb → standard_json_adapter.rb} +2 -3
- data/lib/lutaml/model/json_adapter.rb +1 -31
- data/lib/lutaml/model/key_value_mapping.rb +0 -1
- data/lib/lutaml/model/key_value_mapping_rule.rb +0 -1
- data/lib/lutaml/model/mapping_hash.rb +0 -2
- data/lib/lutaml/model/mapping_rule.rb +0 -1
- data/lib/lutaml/model/schema/json_schema.rb +0 -1
- data/lib/lutaml/model/schema/relaxng_schema.rb +0 -1
- data/lib/lutaml/model/schema/xsd_schema.rb +0 -1
- data/lib/lutaml/model/schema/yaml_schema.rb +0 -1
- data/lib/lutaml/model/schema.rb +0 -1
- data/lib/lutaml/model/serializable.rb +0 -1
- data/lib/lutaml/model/serialize.rb +22 -4
- data/lib/lutaml/model/toml_adapter/toml_document.rb +20 -0
- data/lib/lutaml/model/toml_adapter/toml_object.rb +28 -0
- data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +2 -3
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +2 -3
- data/lib/lutaml/model/toml_adapter.rb +0 -31
- data/lib/lutaml/model/type/date_time.rb +20 -0
- data/lib/lutaml/model/type/json.rb +34 -0
- data/lib/lutaml/model/type/time_without_date.rb +4 -3
- data/lib/lutaml/model/type.rb +61 -124
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +5 -6
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +4 -5
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +8 -9
- data/lib/lutaml/model/xml_adapter/xml_attribute.rb +27 -0
- data/lib/lutaml/model/xml_adapter/xml_document.rb +184 -0
- data/lib/lutaml/model/xml_adapter/xml_element.rb +94 -0
- data/lib/lutaml/model/xml_adapter/xml_namespace.rb +49 -0
- data/lib/lutaml/model/xml_adapter.rb +0 -285
- data/lib/lutaml/model/xml_mapping.rb +1 -1
- data/lib/lutaml/model/xml_mapping_rule.rb +3 -4
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +34 -0
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +20 -0
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +28 -0
- data/lib/lutaml/model/yaml_adapter.rb +1 -27
- data/lib/lutaml/model.rb +0 -5
- metadata +17 -5
- data/lib/lutaml/model/xml_namespace.rb +0 -47
@@ -0,0 +1,184 @@
|
|
1
|
+
require_relative "../mapping_hash"
|
2
|
+
require_relative "xml_element"
|
3
|
+
require_relative "xml_attribute"
|
4
|
+
require_relative "xml_namespace"
|
5
|
+
|
6
|
+
module Lutaml
|
7
|
+
module Model
|
8
|
+
module XmlAdapter
|
9
|
+
class XmlDocument
|
10
|
+
attr_reader :root
|
11
|
+
|
12
|
+
def initialize(root)
|
13
|
+
@root = root
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse(xml)
|
17
|
+
raise NotImplementedError, "Subclasses must implement `parse`."
|
18
|
+
end
|
19
|
+
|
20
|
+
def children
|
21
|
+
@root.children
|
22
|
+
end
|
23
|
+
|
24
|
+
def declaration(options)
|
25
|
+
version = "1.0"
|
26
|
+
version = options[:declaration] if options[:declaration].is_a?(String)
|
27
|
+
|
28
|
+
encoding = options[:encoding] ? "UTF-8" : nil
|
29
|
+
encoding = options[:encoding] if options[:encoding].is_a?(String)
|
30
|
+
|
31
|
+
declaration = "<?xml version=\"#{version}\""
|
32
|
+
declaration += " encoding=\"#{encoding}\"" if encoding
|
33
|
+
declaration += "?>\n"
|
34
|
+
declaration
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_h
|
38
|
+
parse_element(@root)
|
39
|
+
end
|
40
|
+
|
41
|
+
def order
|
42
|
+
@root.order
|
43
|
+
end
|
44
|
+
|
45
|
+
def handle_nested_elements(builder, value, rule: nil, attribute: nil)
|
46
|
+
options = build_options_for_nested_elements(attribute, rule)
|
47
|
+
|
48
|
+
case value
|
49
|
+
when Array
|
50
|
+
value.each { |val| build_element(builder, val, options) }
|
51
|
+
else
|
52
|
+
build_element(builder, value, options)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_options_for_nested_elements(attribute, rule)
|
57
|
+
return {} unless rule
|
58
|
+
|
59
|
+
options = {}
|
60
|
+
|
61
|
+
options[:namespace_prefix] = rule.prefix if rule&.namespace_set?
|
62
|
+
options[:mixed_content] = rule.mixed_content
|
63
|
+
|
64
|
+
options[:mapper_class] = attribute&.type if attribute
|
65
|
+
|
66
|
+
options
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_element(element)
|
70
|
+
result = Lutaml::Model::MappingHash.new
|
71
|
+
result.item_order = element.order
|
72
|
+
|
73
|
+
element.children.each_with_object(result) do |child, hash|
|
74
|
+
value = child.text? ? child.text : parse_element(child)
|
75
|
+
|
76
|
+
if hash[child.unprefixed_name]
|
77
|
+
hash[child.unprefixed_name] =
|
78
|
+
[hash[child.unprefixed_name], value].flatten
|
79
|
+
else
|
80
|
+
hash[child.unprefixed_name] = value
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
element.attributes.each_value do |attr|
|
85
|
+
result[attr.unprefixed_name] = attr.value
|
86
|
+
end
|
87
|
+
|
88
|
+
result
|
89
|
+
end
|
90
|
+
|
91
|
+
def build_element(xml, element, options = {})
|
92
|
+
if ordered?(element, options)
|
93
|
+
build_ordered_element(xml, element, options)
|
94
|
+
else
|
95
|
+
build_unordered_element(xml, element, options)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def ordered?(element, options = {})
|
100
|
+
return false unless element.respond_to?(:element_order)
|
101
|
+
return element.ordered? if element.respond_to?(:ordered?)
|
102
|
+
return options[:mixed_content] if options.key?(:mixed_content)
|
103
|
+
|
104
|
+
mapper_class = options[:mapper_class]
|
105
|
+
mapper_class ? mapper_class.mappings_for(:xml).mixed_content? : false
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_namespace_attributes(klass, processed = {})
|
109
|
+
xml_mappings = klass.mappings_for(:xml)
|
110
|
+
attributes = klass.attributes
|
111
|
+
|
112
|
+
attrs = {}
|
113
|
+
|
114
|
+
if xml_mappings.namespace_prefix
|
115
|
+
attrs["xmlns:#{xml_mappings.namespace_prefix}"] =
|
116
|
+
xml_mappings.namespace_uri
|
117
|
+
end
|
118
|
+
|
119
|
+
xml_mappings.mappings.each do |mapping_rule|
|
120
|
+
processed[klass] ||= {}
|
121
|
+
|
122
|
+
next if processed[klass][mapping_rule.name]
|
123
|
+
|
124
|
+
processed[klass][mapping_rule.name] = true
|
125
|
+
|
126
|
+
type = if mapping_rule.delegate
|
127
|
+
attributes[mapping_rule.delegate].type.attributes[mapping_rule.to].type
|
128
|
+
else
|
129
|
+
attributes[mapping_rule.to].type
|
130
|
+
end
|
131
|
+
|
132
|
+
if type <= Lutaml::Model::Serialize
|
133
|
+
attrs = attrs.merge(build_namespace_attributes(type, processed))
|
134
|
+
end
|
135
|
+
|
136
|
+
if mapping_rule.namespace
|
137
|
+
attrs["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
attrs
|
142
|
+
end
|
143
|
+
|
144
|
+
def build_attributes(element, xml_mapping)
|
145
|
+
attrs = namespace_attributes(xml_mapping)
|
146
|
+
|
147
|
+
xml_mapping.attributes.each_with_object(attrs) do |mapping_rule, hash|
|
148
|
+
if mapping_rule.namespace
|
149
|
+
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
150
|
+
end
|
151
|
+
|
152
|
+
hash[mapping_rule.prefixed_name] = element.send(mapping_rule.to)
|
153
|
+
end
|
154
|
+
|
155
|
+
xml_mapping.elements.each_with_object(attrs) do |mapping_rule, hash|
|
156
|
+
if mapping_rule.namespace
|
157
|
+
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def attribute_definition_for(element, rule, mapper_class: nil)
|
163
|
+
klass = mapper_class || element.class
|
164
|
+
return klass.attributes[rule.to] unless rule.delegate
|
165
|
+
|
166
|
+
element.send(rule.delegate).class.attributes[rule.to]
|
167
|
+
end
|
168
|
+
|
169
|
+
def attribute_value_for(element, rule)
|
170
|
+
return element.send(rule.to) unless rule.delegate
|
171
|
+
|
172
|
+
element.send(rule.delegate).send(rule.to)
|
173
|
+
end
|
174
|
+
|
175
|
+
def namespace_attributes(xml_mapping)
|
176
|
+
return {} unless xml_mapping.namespace_uri
|
177
|
+
|
178
|
+
key = ["xmlns", xml_mapping.namespace_prefix].compact.join(":")
|
179
|
+
{ key => xml_mapping.namespace_uri }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative "xml_attribute"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module XmlAdapter
|
6
|
+
class XmlElement
|
7
|
+
attr_reader :attributes,
|
8
|
+
:children,
|
9
|
+
:text,
|
10
|
+
:namespace_prefix,
|
11
|
+
:parent_document
|
12
|
+
|
13
|
+
def initialize(
|
14
|
+
name,
|
15
|
+
attributes = {},
|
16
|
+
children = [],
|
17
|
+
text = nil,
|
18
|
+
parent_document: nil,
|
19
|
+
namespace_prefix: nil
|
20
|
+
)
|
21
|
+
@name = extract_name(name)
|
22
|
+
@namespace_prefix = namespace_prefix || extract_namespace_prefix(name)
|
23
|
+
@attributes = attributes # .map { |k, v| XmlAttribute.new(k, v) }
|
24
|
+
@children = children
|
25
|
+
@text = text
|
26
|
+
@parent_document = parent_document
|
27
|
+
end
|
28
|
+
|
29
|
+
def name
|
30
|
+
if namespace_prefix
|
31
|
+
"#{namespace_prefix}:#{@name}"
|
32
|
+
else
|
33
|
+
@name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def unprefixed_name
|
38
|
+
@name
|
39
|
+
end
|
40
|
+
|
41
|
+
def document
|
42
|
+
XmlDocument.new(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
def namespaces
|
46
|
+
@namespaces || @parent_document&.namespaces || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def own_namespaces
|
50
|
+
@namespaces || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def namespace
|
54
|
+
return default_namespace unless namespace_prefix
|
55
|
+
|
56
|
+
namespaces[namespace_prefix]
|
57
|
+
end
|
58
|
+
|
59
|
+
def attribute_is_namespace?(name)
|
60
|
+
name.to_s.start_with?("xmlns")
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_namespace(namespace)
|
64
|
+
@namespaces ||= {}
|
65
|
+
@namespaces[namespace.prefix] = namespace
|
66
|
+
end
|
67
|
+
|
68
|
+
def default_namespace
|
69
|
+
namespaces[nil] || @parent_document&.namespaces&.dig(nil)
|
70
|
+
end
|
71
|
+
|
72
|
+
def extract_name(name)
|
73
|
+
n = name.to_s.split(":")
|
74
|
+
return name if n.length <= 1
|
75
|
+
|
76
|
+
n[1..].join(":")
|
77
|
+
end
|
78
|
+
|
79
|
+
def extract_namespace_prefix(name)
|
80
|
+
n = name.to_s.split(":")
|
81
|
+
return if n.length <= 1
|
82
|
+
|
83
|
+
n.first
|
84
|
+
end
|
85
|
+
|
86
|
+
def order
|
87
|
+
children.each_with_object([]) do |child, arr|
|
88
|
+
arr << child.unprefixed_name
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_striing_literal: true
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module XmlAdapter
|
6
|
+
class XmlNamespace
|
7
|
+
# Return name
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
attr_accessor :uri
|
13
|
+
|
14
|
+
# Return prefix
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
attr_accessor :prefix
|
20
|
+
|
21
|
+
# Initialize instance
|
22
|
+
#
|
23
|
+
# @param [String, nil] name
|
24
|
+
# @param [String, nil] prefix
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def initialize(uri = nil, prefix = nil)
|
28
|
+
@uri = uri
|
29
|
+
@prefix = normalize_prefix(prefix)
|
30
|
+
end
|
31
|
+
|
32
|
+
def normalize_prefix(prefix)
|
33
|
+
normalized_prefix = prefix.to_s.gsub(/xmlns:?/, "")
|
34
|
+
return if normalized_prefix.empty?
|
35
|
+
|
36
|
+
normalized_prefix
|
37
|
+
end
|
38
|
+
|
39
|
+
def attr_name
|
40
|
+
if prefix && !prefix.empty?
|
41
|
+
"xmlns:#{prefix}"
|
42
|
+
else
|
43
|
+
"xmlns"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,292 +1,7 @@
|
|
1
|
-
# lib/lutaml/model/xml_adapter.rb
|
2
|
-
|
3
|
-
require_relative "xml_namespace"
|
4
|
-
require_relative "mapping_hash"
|
5
|
-
|
6
1
|
module Lutaml
|
7
2
|
module Model
|
8
3
|
module XmlAdapter
|
9
4
|
XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace".freeze
|
10
|
-
|
11
|
-
class Document
|
12
|
-
attr_reader :root
|
13
|
-
|
14
|
-
def initialize(root)
|
15
|
-
@root = root
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.parse(xml)
|
19
|
-
raise NotImplementedError, "Subclasses must implement `parse`."
|
20
|
-
end
|
21
|
-
|
22
|
-
def children
|
23
|
-
@root.children
|
24
|
-
end
|
25
|
-
|
26
|
-
def declaration(options)
|
27
|
-
version = "1.0"
|
28
|
-
version = options[:declaration] if options[:declaration].is_a?(String)
|
29
|
-
|
30
|
-
encoding = options[:encoding] ? "UTF-8" : nil
|
31
|
-
encoding = options[:encoding] if options[:encoding].is_a?(String)
|
32
|
-
|
33
|
-
declaration = "<?xml version=\"#{version}\""
|
34
|
-
declaration += " encoding=\"#{encoding}\"" if encoding
|
35
|
-
declaration += "?>\n"
|
36
|
-
declaration
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_h
|
40
|
-
parse_element(@root)
|
41
|
-
end
|
42
|
-
|
43
|
-
def order
|
44
|
-
@root.order
|
45
|
-
end
|
46
|
-
|
47
|
-
def handle_nested_elements(builder, value, rule: nil, attribute: nil)
|
48
|
-
options = build_options_for_nested_elements(attribute, rule)
|
49
|
-
|
50
|
-
case value
|
51
|
-
when Array
|
52
|
-
value.each { |val| build_element(builder, val, options) }
|
53
|
-
else
|
54
|
-
build_element(builder, value, options)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def build_options_for_nested_elements(attribute, rule)
|
59
|
-
return {} unless rule
|
60
|
-
|
61
|
-
options = {}
|
62
|
-
|
63
|
-
options[:namespace_prefix] = rule.prefix if rule&.namespace_set?
|
64
|
-
options[:mixed_content] = rule.mixed_content
|
65
|
-
|
66
|
-
options[:mapper_class] = attribute&.type if attribute
|
67
|
-
|
68
|
-
options
|
69
|
-
end
|
70
|
-
|
71
|
-
def parse_element(element)
|
72
|
-
result = Lutaml::Model::MappingHash.new
|
73
|
-
result.item_order = element.order
|
74
|
-
|
75
|
-
element.children.each_with_object(result) do |child, hash|
|
76
|
-
value = child.text? ? child.text : parse_element(child)
|
77
|
-
|
78
|
-
if hash[child.unprefixed_name]
|
79
|
-
hash[child.unprefixed_name] =
|
80
|
-
[hash[child.unprefixed_name], value].flatten
|
81
|
-
else
|
82
|
-
hash[child.unprefixed_name] = value
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
element.attributes.each_value do |attr|
|
87
|
-
result[attr.unprefixed_name] = attr.value
|
88
|
-
end
|
89
|
-
|
90
|
-
result
|
91
|
-
end
|
92
|
-
|
93
|
-
def build_element(xml, element, options = {})
|
94
|
-
if ordered?(element, options)
|
95
|
-
build_ordered_element(xml, element, options)
|
96
|
-
else
|
97
|
-
build_unordered_element(xml, element, options)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def ordered?(element, options = {})
|
102
|
-
return false unless element.respond_to?(:element_order)
|
103
|
-
return element.ordered? if element.respond_to?(:ordered?)
|
104
|
-
return options[:mixed_content] if options.key?(:mixed_content)
|
105
|
-
|
106
|
-
mapper_class = options[:mapper_class]
|
107
|
-
mapper_class ? mapper_class.mappings_for(:xml).mixed_content? : false
|
108
|
-
end
|
109
|
-
|
110
|
-
def build_namespace_attributes(klass, processed = {})
|
111
|
-
xml_mappings = klass.mappings_for(:xml)
|
112
|
-
attributes = klass.attributes
|
113
|
-
|
114
|
-
attrs = {}
|
115
|
-
|
116
|
-
if xml_mappings.namespace_prefix
|
117
|
-
attrs["xmlns:#{xml_mappings.namespace_prefix}"] =
|
118
|
-
xml_mappings.namespace_uri
|
119
|
-
end
|
120
|
-
|
121
|
-
xml_mappings.mappings.each do |mapping_rule|
|
122
|
-
processed[klass] ||= {}
|
123
|
-
|
124
|
-
next if processed[klass][mapping_rule.name]
|
125
|
-
|
126
|
-
processed[klass][mapping_rule.name] = true
|
127
|
-
|
128
|
-
type = if mapping_rule.delegate
|
129
|
-
attributes[mapping_rule.delegate].type.attributes[mapping_rule.to].type
|
130
|
-
else
|
131
|
-
attributes[mapping_rule.to].type
|
132
|
-
end
|
133
|
-
|
134
|
-
if type <= Lutaml::Model::Serialize
|
135
|
-
attrs = attrs.merge(build_namespace_attributes(type, processed))
|
136
|
-
end
|
137
|
-
|
138
|
-
if mapping_rule.namespace
|
139
|
-
attrs["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
attrs
|
144
|
-
end
|
145
|
-
|
146
|
-
def build_attributes(element, xml_mapping)
|
147
|
-
attrs = namespace_attributes(xml_mapping)
|
148
|
-
|
149
|
-
xml_mapping.attributes.each_with_object(attrs) do |mapping_rule, hash|
|
150
|
-
if mapping_rule.namespace
|
151
|
-
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
152
|
-
end
|
153
|
-
|
154
|
-
hash[mapping_rule.prefixed_name] = element.send(mapping_rule.to)
|
155
|
-
end
|
156
|
-
|
157
|
-
xml_mapping.elements.each_with_object(attrs) do |mapping_rule, hash|
|
158
|
-
if mapping_rule.namespace
|
159
|
-
hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def attribute_definition_for(element, rule, mapper_class: nil)
|
165
|
-
klass = mapper_class || element.class
|
166
|
-
return klass.attributes[rule.to] unless rule.delegate
|
167
|
-
|
168
|
-
element.send(rule.delegate).class.attributes[rule.to]
|
169
|
-
end
|
170
|
-
|
171
|
-
def attribute_value_for(element, rule)
|
172
|
-
return element.send(rule.to) unless rule.delegate
|
173
|
-
|
174
|
-
element.send(rule.delegate).send(rule.to)
|
175
|
-
end
|
176
|
-
|
177
|
-
def namespace_attributes(xml_mapping)
|
178
|
-
return {} unless xml_mapping.namespace_uri
|
179
|
-
|
180
|
-
key = ["xmlns", xml_mapping.namespace_prefix].compact.join(":")
|
181
|
-
{ key => xml_mapping.namespace_uri }
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
class Element
|
186
|
-
attr_reader :attributes,
|
187
|
-
:children,
|
188
|
-
:text,
|
189
|
-
:namespace_prefix,
|
190
|
-
:parent_document
|
191
|
-
|
192
|
-
def initialize(
|
193
|
-
name,
|
194
|
-
attributes = {},
|
195
|
-
children = [],
|
196
|
-
text = nil,
|
197
|
-
parent_document: nil,
|
198
|
-
namespace_prefix: nil
|
199
|
-
)
|
200
|
-
@name = extract_name(name)
|
201
|
-
@namespace_prefix = namespace_prefix || extract_namespace_prefix(name)
|
202
|
-
@attributes = attributes # .map { |k, v| Attribute.new(k, v) }
|
203
|
-
@children = children
|
204
|
-
@text = text
|
205
|
-
@parent_document = parent_document
|
206
|
-
end
|
207
|
-
|
208
|
-
def name
|
209
|
-
if namespace_prefix
|
210
|
-
"#{namespace_prefix}:#{@name}"
|
211
|
-
else
|
212
|
-
@name
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def unprefixed_name
|
217
|
-
@name
|
218
|
-
end
|
219
|
-
|
220
|
-
def document
|
221
|
-
Document.new(self)
|
222
|
-
end
|
223
|
-
|
224
|
-
def namespaces
|
225
|
-
@namespaces || @parent_document&.namespaces || {}
|
226
|
-
end
|
227
|
-
|
228
|
-
def own_namespaces
|
229
|
-
@namespaces || {}
|
230
|
-
end
|
231
|
-
|
232
|
-
def namespace
|
233
|
-
return default_namespace unless namespace_prefix
|
234
|
-
|
235
|
-
namespaces[namespace_prefix]
|
236
|
-
end
|
237
|
-
|
238
|
-
def attribute_is_namespace?(name)
|
239
|
-
name.to_s.start_with?("xmlns")
|
240
|
-
end
|
241
|
-
|
242
|
-
def add_namespace(namespace)
|
243
|
-
@namespaces ||= {}
|
244
|
-
@namespaces[namespace.prefix] = namespace
|
245
|
-
end
|
246
|
-
|
247
|
-
def default_namespace
|
248
|
-
namespaces[nil] || @parent_document&.namespaces&.dig(nil)
|
249
|
-
end
|
250
|
-
|
251
|
-
def extract_name(name)
|
252
|
-
n = name.to_s.split(":")
|
253
|
-
return name if n.length <= 1
|
254
|
-
|
255
|
-
n[1..].join(":")
|
256
|
-
end
|
257
|
-
|
258
|
-
def extract_namespace_prefix(name)
|
259
|
-
n = name.to_s.split(":")
|
260
|
-
return if n.length <= 1
|
261
|
-
|
262
|
-
n.first
|
263
|
-
end
|
264
|
-
|
265
|
-
def order
|
266
|
-
children.each_with_object([]) do |child, arr|
|
267
|
-
arr << child.unprefixed_name
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
class Attribute
|
273
|
-
attr_reader :name, :value, :namespace, :namespace_prefix
|
274
|
-
|
275
|
-
def initialize(name, value, namespace: nil, namespace_prefix: nil)
|
276
|
-
@name = name
|
277
|
-
@value = value
|
278
|
-
@namespace = namespace
|
279
|
-
@namespace_prefix = namespace_prefix
|
280
|
-
end
|
281
|
-
|
282
|
-
def unprefixed_name
|
283
|
-
if namespace_prefix
|
284
|
-
name.split(":").last
|
285
|
-
else
|
286
|
-
name
|
287
|
-
end
|
288
|
-
end
|
289
|
-
end
|
290
5
|
end
|
291
6
|
end
|
292
7
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# lib/lutaml/model/xml_mapping_rule.rb
|
2
1
|
require_relative "mapping_rule"
|
3
2
|
|
4
3
|
module Lutaml
|
@@ -24,12 +23,12 @@ module Lutaml
|
|
24
23
|
with: with,
|
25
24
|
delegate: delegate,
|
26
25
|
mixed_content: mixed_content,
|
27
|
-
namespace_set: namespace_set
|
26
|
+
namespace_set: namespace_set,
|
28
27
|
)
|
29
28
|
|
30
29
|
@namespace = if namespace.to_s == "inherit"
|
31
|
-
|
32
|
-
|
30
|
+
# we are using inherit_namespace in xml builder by
|
31
|
+
# default so no need to do anything here.
|
33
32
|
else
|
34
33
|
namespace
|
35
34
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require_relative "yaml_document"
|
3
|
+
|
4
|
+
module Lutaml
|
5
|
+
module Model
|
6
|
+
module YamlAdapter
|
7
|
+
class StandardYamlAdapter < YamlDocument
|
8
|
+
def self.parse(yaml)
|
9
|
+
YAML.safe_load(
|
10
|
+
yaml,
|
11
|
+
permitted_classes: [Date, Time, DateTime, Symbol,
|
12
|
+
BigDecimal, Hash, Array],
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_yaml(options = {})
|
17
|
+
YAML.dump(@attributes, options)
|
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
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "yaml_object"
|
4
|
+
|
5
|
+
module Lutaml
|
6
|
+
module Model
|
7
|
+
module YamlAdapter
|
8
|
+
# Base class for YAML documents
|
9
|
+
class YamlDocument < YamlObject
|
10
|
+
def self.parse(yaml)
|
11
|
+
raise NotImplementedError, "Subclasses must implement `parse`."
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_yaml(*args)
|
15
|
+
raise NotImplementedError, "Subclasses must implement `to_yaml`."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|