lutaml-model 0.6.7 → 0.7.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.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/dependent-repos-todo.json +7 -0
  3. data/.github/workflows/dependent-repos.json +17 -9
  4. data/.rubocop.yml +1 -1
  5. data/.rubocop_todo.yml +51 -65
  6. data/Gemfile +4 -1
  7. data/README.adoc +5083 -2612
  8. data/RELEASE_NOTES.adoc +346 -0
  9. data/docs/custom_adapters.adoc +144 -0
  10. data/lib/lutaml/model/attribute.rb +101 -16
  11. data/lib/lutaml/model/choice.rb +7 -0
  12. data/lib/lutaml/model/comparable_model.rb +48 -9
  13. data/lib/lutaml/model/config.rb +48 -42
  14. data/lib/lutaml/model/error/collection_count_out_of_range_error.rb +1 -1
  15. data/lib/lutaml/model/error/polymorphic_error.rb +14 -0
  16. data/lib/lutaml/model/error.rb +1 -0
  17. data/lib/lutaml/model/format_registry.rb +41 -0
  18. data/lib/lutaml/model/hash/document.rb +11 -0
  19. data/lib/lutaml/model/hash/mapping.rb +19 -0
  20. data/lib/lutaml/model/hash/mapping_rule.rb +9 -0
  21. data/lib/lutaml/model/hash/standard_adapter.rb +17 -0
  22. data/lib/lutaml/model/hash/transform.rb +8 -0
  23. data/lib/lutaml/model/hash.rb +21 -0
  24. data/lib/lutaml/model/json/document.rb +11 -0
  25. data/lib/lutaml/model/json/mapping.rb +19 -0
  26. data/lib/lutaml/model/json/mapping_rule.rb +9 -0
  27. data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
  28. data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
  29. data/lib/lutaml/model/json/transform.rb +8 -0
  30. data/lib/lutaml/model/json.rb +21 -0
  31. data/lib/lutaml/model/key_value_document.rb +27 -0
  32. data/lib/lutaml/model/{key_value_mapping.rb → mapping/key_value_mapping.rb} +64 -16
  33. data/lib/lutaml/model/{key_value_mapping_rule.rb → mapping/key_value_mapping_rule.rb} +18 -2
  34. data/lib/lutaml/model/mapping/mapping.rb +13 -0
  35. data/lib/lutaml/model/mapping/mapping_rule.rb +300 -0
  36. data/lib/lutaml/model/schema/xml_compiler.rb +15 -15
  37. data/lib/lutaml/model/sequence.rb +2 -2
  38. data/lib/lutaml/model/serialization_adapter.rb +22 -0
  39. data/lib/lutaml/model/serialize.rb +219 -444
  40. data/lib/lutaml/model/services/logger.rb +54 -0
  41. data/lib/lutaml/model/services/transformer.rb +48 -0
  42. data/lib/lutaml/model/services.rb +2 -0
  43. data/lib/lutaml/model/toml/document.rb +11 -0
  44. data/lib/lutaml/model/toml/mapping.rb +27 -0
  45. data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
  46. data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
  47. data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
  48. data/lib/lutaml/model/toml/transform.rb +8 -0
  49. data/lib/lutaml/model/toml.rb +30 -0
  50. data/lib/lutaml/model/transform/key_value_transform.rb +291 -0
  51. data/lib/lutaml/model/transform/xml_transform.rb +239 -0
  52. data/lib/lutaml/model/transform.rb +78 -0
  53. data/lib/lutaml/model/type/date.rb +1 -1
  54. data/lib/lutaml/model/type/date_time.rb +2 -2
  55. data/lib/lutaml/model/type/hash.rb +1 -1
  56. data/lib/lutaml/model/type/time.rb +2 -2
  57. data/lib/lutaml/model/type/time_without_date.rb +2 -2
  58. data/lib/lutaml/model/type/value.rb +6 -9
  59. data/lib/lutaml/model/uninitialized_class.rb +64 -0
  60. data/lib/lutaml/model/utils.rb +44 -0
  61. data/lib/lutaml/model/validation.rb +1 -0
  62. data/lib/lutaml/model/version.rb +1 -1
  63. data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
  64. data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
  65. data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
  66. data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +41 -21
  67. data/lib/lutaml/model/xml/element.rb +32 -0
  68. data/lib/lutaml/model/xml/mapping.rb +410 -0
  69. data/lib/lutaml/model/xml/mapping_rule.rb +141 -0
  70. data/lib/lutaml/model/xml/nokogiri_adapter.rb +232 -0
  71. data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
  72. data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +3 -1
  73. data/lib/lutaml/model/xml/oga_adapter.rb +171 -0
  74. data/lib/lutaml/model/xml/ox_adapter.rb +215 -0
  75. data/lib/lutaml/model/xml/transform.rb +8 -0
  76. data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
  77. data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +23 -10
  78. data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
  79. data/lib/lutaml/model/xml.rb +31 -0
  80. data/lib/lutaml/model/xml_adapter/element.rb +11 -25
  81. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
  82. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
  83. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
  84. data/lib/lutaml/model/yaml/document.rb +10 -0
  85. data/lib/lutaml/model/yaml/mapping.rb +19 -0
  86. data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
  87. data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
  88. data/lib/lutaml/model/yaml/transform.rb +8 -0
  89. data/lib/lutaml/model/yaml.rb +21 -0
  90. data/lib/lutaml/model.rb +40 -4
  91. data/lutaml-model.gemspec +0 -4
  92. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +7 -7
  93. data/spec/fixtures/person.rb +5 -5
  94. data/spec/lutaml/model/attribute_spec.rb +37 -1
  95. data/spec/lutaml/model/cdata_spec.rb +9 -9
  96. data/spec/lutaml/model/collection_spec.rb +50 -2
  97. data/spec/lutaml/model/comparable_model_spec.rb +92 -27
  98. data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
  99. data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
  100. data/spec/lutaml/model/defaults_spec.rb +1 -1
  101. data/spec/lutaml/model/enum_spec.rb +1 -1
  102. data/spec/lutaml/model/group_spec.rb +333 -20
  103. data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
  104. data/spec/lutaml/model/json_adapter_spec.rb +6 -6
  105. data/spec/lutaml/model/key_value_mapping_spec.rb +65 -3
  106. data/spec/lutaml/model/mixed_content_spec.rb +24 -24
  107. data/spec/lutaml/model/multiple_mapping_spec.rb +5 -5
  108. data/spec/lutaml/model/ordered_content_spec.rb +6 -6
  109. data/spec/lutaml/model/polymorphic_spec.rb +526 -0
  110. data/spec/lutaml/model/render_empty_spec.rb +194 -0
  111. data/spec/lutaml/model/render_nil_spec.rb +206 -22
  112. data/spec/lutaml/model/root_mappings_spec.rb +3 -3
  113. data/spec/lutaml/model/schema/xml_compiler_spec.rb +6 -6
  114. data/spec/lutaml/model/serializable_spec.rb +179 -103
  115. data/spec/lutaml/model/simple_model_spec.rb +9 -9
  116. data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
  117. data/spec/lutaml/model/toml_spec.rb +51 -0
  118. data/spec/lutaml/model/transformation_spec.rb +72 -15
  119. data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
  120. data/spec/lutaml/model/value_map_spec.rb +240 -0
  121. data/spec/lutaml/model/xml/namespace/nested_with_explicit_namespace_spec.rb +85 -0
  122. data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
  123. data/spec/lutaml/model/xml/xml_element_spec.rb +93 -0
  124. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
  125. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
  126. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
  127. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +6 -6
  128. data/spec/lutaml/model/xml_adapter_spec.rb +6 -6
  129. data/spec/lutaml/model/xml_mapping_rule_spec.rb +105 -5
  130. data/spec/lutaml/model/xml_mapping_spec.rb +70 -16
  131. data/spec/lutaml/model/xml_spec.rb +63 -0
  132. data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
  133. data/spec/sample_model_spec.rb +3 -3
  134. data/spec/spec_helper.rb +3 -3
  135. metadata +76 -59
  136. data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
  137. data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
  138. data/lib/lutaml/model/loggable.rb +0 -15
  139. data/lib/lutaml/model/mapping_rule.rb +0 -109
  140. data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
  141. data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
  142. data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
  143. data/lib/lutaml/model/toml_adapter.rb +0 -6
  144. data/lib/lutaml/model/xml_mapping.rb +0 -307
  145. data/lib/lutaml/model/xml_mapping_rule.rb +0 -122
  146. data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
  147. data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
  148. data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -1,9 +1,12 @@
1
1
  require_relative "xml_attribute"
2
+ require_relative "document"
2
3
 
3
4
  module Lutaml
4
5
  module Model
5
- module XmlAdapter
6
+ module Xml
6
7
  class XmlElement
8
+ XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace".freeze
9
+
7
10
  attr_reader :attributes,
8
11
  :children,
9
12
  :namespace_prefix,
@@ -59,7 +62,7 @@ module Lutaml
59
62
  end
60
63
 
61
64
  def document
62
- XmlDocument.new(self)
65
+ Document.new(self)
63
66
  end
64
67
 
65
68
  def namespaces
@@ -118,7 +121,7 @@ module Lutaml
118
121
  def order
119
122
  children.map do |child|
120
123
  type = child.text? ? "Text" : "Element"
121
- Lutaml::Model::XmlAdapter::Element.new(type, child.unprefixed_name)
124
+ Lutaml::Model::Xml::Element.new(type, child.unprefixed_name)
122
125
  end
123
126
  end
124
127
 
@@ -127,9 +130,17 @@ module Lutaml
127
130
  end
128
131
 
129
132
  def text
133
+ return @text if children.empty?
130
134
  return text_children.map(&:text) if children.count > 1
131
135
 
132
- @text
136
+ text_children.map(&:text).join
137
+ end
138
+
139
+ def cdata
140
+ return @text if children.empty?
141
+ return cdata_children.map(&:text) if children.count > 1
142
+
143
+ cdata_children.map(&:text).join
133
144
  end
134
145
 
135
146
  def cdata_children
@@ -140,6 +151,10 @@ module Lutaml
140
151
  find_children_by_name("text")
141
152
  end
142
153
 
154
+ def [](name)
155
+ find_attribute_value(name) || find_children_by_name(name)
156
+ end
157
+
143
158
  def find_attribute_value(attribute_name)
144
159
  if attribute_name.is_a?(Array)
145
160
  attributes.values.find do |attr|
@@ -164,15 +179,13 @@ module Lutaml
164
179
  find_children_by_name(name).first
165
180
  end
166
181
 
167
- def cdata
168
- return cdata_children.map(&:text) if children.count > 1
169
-
170
- @text
171
- end
172
-
173
182
  def to_h
174
183
  document.to_h
175
184
  end
185
+
186
+ def nil_element?
187
+ find_attribute_value("xsi:nil") == "true"
188
+ end
176
189
  end
177
190
  end
178
191
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- module XmlAdapter
5
+ module Xml
6
6
  class XmlNamespace
7
7
  # Return name
8
8
  #
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lutaml
4
+ module Model
5
+ module Xml
6
+ def self.detect_xml_adapter
7
+ return :nokogiri if Object.const_defined?(:Nokogiri)
8
+ return :ox if Object.const_defined?(:Ox)
9
+ return :opal if Object.const_defined?(:Opal)
10
+
11
+ nil
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ require_relative "xml/document"
18
+ require_relative "xml/mapping"
19
+ require_relative "xml/mapping_rule"
20
+ require_relative "xml/transform"
21
+
22
+ Lutaml::Model::FormatRegistry.register(
23
+ :xml,
24
+ mapping_class: Lutaml::Model::Xml::Mapping,
25
+ adapter_class: nil,
26
+ transformer: Lutaml::Model::Xml::Transform,
27
+ )
28
+
29
+ if (adapter = Lutaml::Model::Xml.detect_xml_adapter)
30
+ Lutaml::Model::Config.xml_adapter_type = adapter
31
+ end
@@ -1,31 +1,17 @@
1
+ # require "ox"
2
+ # require_relative "xml_document"
3
+ # require_relative "builder/ox"
4
+
5
+ require_relative "../xml/element"
6
+
1
7
  module Lutaml
2
8
  module Model
3
9
  module XmlAdapter
4
- class Element
5
- attr_reader :type, :name
6
-
7
- def initialize(type, name)
8
- @type = type
9
- @name = name
10
- end
11
-
12
- def text?
13
- @type == "Text" && @name != "#cdata-section"
14
- end
15
-
16
- def element_tag
17
- @name unless text?
18
- end
19
-
20
- def eql?(other)
21
- return false unless other.is_a?(self.class)
22
-
23
- instance_variables.all? do |var|
24
- instance_variable_get(var) == other.instance_variable_get(var)
25
- end
26
- end
27
-
28
- alias == eql?
10
+ class Element < ::Lutaml::Model::Xml::Element
11
+ Logger.warn_future_deprication(
12
+ old: "Lutaml::Model::XmlAdapter::Element",
13
+ replacement: "Lutaml::Model::Xml::Element",
14
+ )
29
15
  end
30
16
  end
31
17
  end
@@ -1,231 +1,14 @@
1
1
  require "nokogiri"
2
- require_relative "xml_document"
3
- require_relative "builder/nokogiri"
2
+ require_relative "../xml/nokogiri_adapter"
4
3
 
5
4
  module Lutaml
6
5
  module Model
7
6
  module XmlAdapter
8
- class NokogiriAdapter < XmlDocument
9
- def self.parse(xml, options = {})
10
- parsed = Nokogiri::XML(xml, nil, encoding(xml, options))
11
- @root = NokogiriElement.new(parsed.root)
12
- new(@root, parsed.encoding)
13
- end
14
-
15
- def to_xml(options = {})
16
- builder_options = {}
17
-
18
- if options.key?(:encoding)
19
- builder_options[:encoding] = options[:encoding] unless options[:encoding].nil?
20
- elsif options.key?(:parse_encoding)
21
- builder_options[:encoding] = options[:parse_encoding]
22
- else
23
- builder_options[:encoding] = "UTF-8"
24
- end
25
-
26
- builder = Builder::Nokogiri.build(builder_options) do |xml|
27
- if root.is_a?(Lutaml::Model::XmlAdapter::NokogiriElement)
28
- root.build_xml(xml)
29
- else
30
- mapper_class = options[:mapper_class] || @root.class
31
- options[:xml_attributes] =
32
- build_namespace_attributes(mapper_class)
33
- build_element(xml, @root, options)
34
- end
35
- end
36
-
37
- xml_options = {}
38
- xml_options[:indent] = 2 if options[:pretty]
39
-
40
- xml_data = builder.doc.root.to_xml(xml_options)
41
- options[:declaration] ? declaration(options) + xml_data : xml_data
42
- end
43
-
44
- private
45
-
46
- def prefix_xml(xml, mapping, options)
47
- if options.key?(:namespace_prefix)
48
- xml[options[:namespace_prefix]] if options[:namespace_prefix]
49
- elsif mapping.namespace_prefix
50
- xml[mapping.namespace_prefix]
51
- end
52
- xml
53
- end
54
-
55
- def build_ordered_element(xml, element, options = {})
56
- mapper_class = options[:mapper_class] || element.class
57
- xml_mapping = mapper_class.mappings_for(:xml)
58
- return xml unless xml_mapping
59
-
60
- attributes = build_attributes(element, xml_mapping)&.compact
61
-
62
- prefixed_xml = prefix_xml(xml, xml_mapping, options)
63
-
64
- tag_name = options[:tag_name] || xml_mapping.root_element
65
- tag_name = "#{tag_name}_" if prefixed_xml.respond_to?(tag_name)
66
- prefixed_xml.public_send(tag_name, attributes) do
67
- if options.key?(:namespace_prefix) && !options[:namespace_prefix]
68
- xml.parent.namespace = nil
69
- end
70
-
71
- index_hash = {}
72
- content = []
73
-
74
- element.element_order.each do |object|
75
- index_hash[object.name] ||= -1
76
- curr_index = index_hash[object.name] += 1
77
-
78
- element_rule = xml_mapping.find_by_name(object.name)
79
- next if element_rule.nil?
80
-
81
- attribute_def = attribute_definition_for(element, element_rule,
82
- mapper_class: mapper_class)
83
- value = attribute_value_for(element, element_rule)
84
-
85
- if element_rule == xml_mapping.content_mapping
86
- next if element_rule.cdata && object.text?
87
-
88
- text = xml_mapping.content_mapping.serialize(element)
89
- text = text[curr_index] if text.is_a?(Array)
90
-
91
- next prefixed_xml.add_text(xml, text, cdata: element_rule.cdata) if element.mixed?
92
-
93
- content << text
94
- elsif !value.nil? || element_rule.render_nil?
95
- value = value[curr_index] if attribute_def.collection?
96
-
97
- add_to_xml(
98
- xml,
99
- element,
100
- element_rule.prefix,
101
- value,
102
- options.merge(
103
- attribute: attribute_def,
104
- rule: element_rule,
105
- mapper_class: mapper_class,
106
- ),
107
- )
108
- end
109
- end
110
-
111
- prefixed_xml.text content.join
112
- end
113
- end
114
- end
115
-
116
- class NokogiriElement < XmlElement
117
- def initialize(node, root_node: nil, default_namespace: nil)
118
- if root_node
119
- node.namespaces.each do |prefix, name|
120
- namespace = XmlNamespace.new(name, prefix)
121
-
122
- root_node.add_namespace(namespace)
123
- end
124
- end
125
-
126
- attributes = {}
127
-
128
- # Using `attribute_nodes` instead of `attributes` because
129
- # `attribute_nodes` handles name collisions as well
130
- # More info: https://devdocs.io/nokogiri/nokogiri/xml/node#method-i-attributes
131
- node.attribute_nodes.each do |attr|
132
- name = if attr.namespace
133
- "#{attr.namespace.prefix}:#{attr.name}"
134
- else
135
- attr.name
136
- end
137
-
138
- attributes[name] = XmlAttribute.new(
139
- name,
140
- attr.value,
141
- namespace: attr.namespace&.href,
142
- namespace_prefix: attr.namespace&.prefix,
143
- )
144
- end
145
-
146
- if root_node.nil? && !node.namespace&.prefix
147
- default_namespace = node.namespace&.href
148
- end
149
-
150
- super(
151
- node,
152
- attributes,
153
- parse_all_children(node, root_node: root_node || self,
154
- default_namespace: default_namespace),
155
- node.text,
156
- parent_document: root_node,
157
- namespace_prefix: node.namespace&.prefix,
158
- default_namespace: default_namespace
159
- )
160
- end
161
-
162
- def text?
163
- # false
164
- children.empty? && text.length.positive?
165
- end
166
-
167
- def to_xml
168
- return text if text?
169
-
170
- build_xml.doc.root.to_xml
171
- end
172
-
173
- def inner_xml
174
- children.map(&:to_xml).join
175
- end
176
-
177
- def build_xml(builder = nil)
178
- builder ||= Builder::Nokogiri.build
179
-
180
- if name == "text"
181
- builder.text(text)
182
- else
183
- builder.public_send(name, build_attributes(self)) do |xml|
184
- children.each do |child|
185
- child.build_xml(xml)
186
- end
187
- end
188
- end
189
-
190
- builder
191
- end
192
-
193
- private
194
-
195
- def parse_children(node, root_node: nil)
196
- node.children.select(&:element?).map do |child|
197
- NokogiriElement.new(child, root_node: root_node)
198
- end
199
- end
200
-
201
- def parse_all_children(node, root_node: nil, default_namespace: nil)
202
- node.children.map do |child|
203
- NokogiriElement.new(child, root_node: root_node,
204
- default_namespace: default_namespace)
205
- end
206
- end
207
-
208
- def build_attributes(node, _options = {})
209
- attrs = node.attributes.transform_values(&:value)
210
-
211
- attrs.merge(build_namespace_attributes(node))
212
- end
213
-
214
- def build_namespace_attributes(node)
215
- namespace_attrs = {}
216
-
217
- node.own_namespaces.each_value do |namespace|
218
- namespace_attrs[namespace.attr_name] = namespace.uri
219
- end
220
-
221
- node.children.each do |child|
222
- namespace_attrs = namespace_attrs.merge(
223
- build_namespace_attributes(child),
224
- )
225
- end
226
-
227
- namespace_attrs
228
- end
7
+ class NokogiriAdapter < ::Lutaml::Model::Xml::NokogiriAdapter
8
+ Logger.warn_future_deprication(
9
+ old: "Lutaml::Model::XmlAdapter::NokogiriAdapter",
10
+ replacement: "Lutaml::Model::Xml::NokogiriAdapter",
11
+ )
229
12
  end
230
13
  end
231
14
  end
@@ -1,170 +1,20 @@
1
- require "oga"
2
- require "moxml/adapter/oga"
3
- require_relative "xml_document"
4
- require_relative "oga/document"
5
- require_relative "oga/element"
6
- require_relative "builder/oga"
1
+ # require "oga"
2
+ # require "moxml/adapter/oga"
3
+ # require_relative "xml_document"
4
+ # require_relative "oga/document"
5
+ # require_relative "oga/element"
6
+ # require_relative "builder/oga"
7
+
8
+ require_relative "../xml/oga_adapter"
7
9
 
8
10
  module Lutaml
9
11
  module Model
10
12
  module XmlAdapter
11
- class OgaAdapter < XmlDocument
12
- TEXT_CLASSES = [Moxml::Text, Moxml::Cdata].freeze
13
-
14
- def self.parse(xml, options = {})
15
- parsed = Moxml::Adapter::Oga.parse(xml)
16
- @root = Oga::Element.new(parsed.children.first)
17
- new(@root, encoding(xml, options))
18
- end
19
-
20
- def to_xml(options = {})
21
- builder_options = {}
22
- builder_options[:encoding] = if options.key?(:encoding)
23
- options[:encoding]
24
- elsif options.key?(:parse_encoding)
25
- options[:parse_encoding]
26
- else
27
- "UTF-8"
28
- end
29
-
30
- builder = Builder::Oga.build(builder_options) do |xml|
31
- if @root.is_a?(Oga::Element)
32
- @root.build_xml(xml)
33
- else
34
- build_element(xml, @root, options)
35
- end
36
- end
37
- xml_data = builder.to_xml
38
- options[:declaration] ? declaration(options) + xml_data : xml_data
39
- end
40
-
41
- def attributes_hash(element)
42
- result = Lutaml::Model::MappingHash.new
43
-
44
- element.attributes.each do |attr|
45
- if attr.name == "schemaLocation"
46
- result["__schema_location"] = {
47
- namespace: attr.namespace,
48
- prefix: attr.namespace.prefix,
49
- schema_location: attr.value,
50
- }
51
- else
52
- result[self.class.namespaced_attr_name(attr)] = attr.value
53
- end
54
- end
55
-
56
- result
57
- end
58
-
59
- def self.name_of(element)
60
- case element
61
- when Moxml::Text
62
- "text"
63
- when Moxml::Cdata
64
- "cdata"
65
- else
66
- element.name
67
- end
68
- end
69
-
70
- def self.prefixed_name_of(node)
71
- return name_of(node) if TEXT_CLASSES.include?(node.class)
72
-
73
- [node&.namespace&.prefix, node.name].compact.join(":")
74
- end
75
-
76
- def self.text_of(element)
77
- element.content
78
- end
79
-
80
- def self.namespaced_attr_name(attribute)
81
- attr_ns = attribute.namespace
82
- attr_name = attribute.name
83
- return attr_name unless attr_ns
84
-
85
- prefix = attr_name == "lang" ? attr_ns.prefix : attr_ns.uri
86
- [prefix, attr_name].compact.join(":")
87
- end
88
-
89
- def self.namespaced_name_of(node)
90
- return name_of(node) unless node.respond_to?(:namespace)
91
-
92
- [node&.namespace&.uri, node.name].compact.join(":")
93
- end
94
-
95
- def order
96
- children.map do |child|
97
- type = child.text? ? "Text" : "Element"
98
- Element.new(type, child.unprefixed_name)
99
- end
100
- end
101
-
102
- def self.order_of(element)
103
- element.children.map do |child|
104
- instance_args = if TEXT_CLASSES.include?(child.class)
105
- ["Text", "text"]
106
- else
107
- ["Element", name_of(child)]
108
- end
109
- Element.new(*instance_args)
110
- end
111
- end
112
-
113
- private
114
-
115
- def build_ordered_element(builder, element, options = {})
116
- mapper_class = options[:mapper_class] || element.class
117
- xml_mapping = mapper_class.mappings_for(:xml)
118
- return xml unless xml_mapping
119
-
120
- attributes = build_attributes(element, xml_mapping).compact
121
-
122
- tag_name = options[:tag_name] || xml_mapping.root_element
123
- builder.create_and_add_element(tag_name,
124
- attributes: attributes) do |el|
125
- index_hash = {}
126
- content = []
127
-
128
- element.element_order.each do |object|
129
- index_hash[object.name] ||= -1
130
- curr_index = index_hash[object.name] += 1
131
-
132
- element_rule = xml_mapping.find_by_name(object.name)
133
- next if element_rule.nil?
134
-
135
- attribute_def = attribute_definition_for(element, element_rule,
136
- mapper_class: mapper_class)
137
- value = attribute_value_for(element, element_rule)
138
-
139
- next if element_rule == xml_mapping.content_mapping && element_rule.cdata && object.text?
140
-
141
- if element_rule == xml_mapping.content_mapping
142
- text = xml_mapping.content_mapping.serialize(element)
143
- text = text[curr_index] if text.is_a?(Array)
144
-
145
- next el.add_text(el, text, cdata: element_rule.cdata) if element.mixed?
146
-
147
- content << text
148
- elsif !value.nil? || element_rule.render_nil?
149
- value = value[curr_index] if attribute_def.collection?
150
-
151
- add_to_xml(
152
- el,
153
- element,
154
- nil,
155
- value,
156
- options.merge(
157
- attribute: attribute_def,
158
- rule: element_rule,
159
- mapper_class: mapper_class,
160
- ),
161
- )
162
- end
163
- end
164
-
165
- el.add_text(el, content.join)
166
- end
167
- end
13
+ class OgaAdapter < ::Lutaml::Model::Xml::OgaAdapter
14
+ Logger.warn_future_deprication(
15
+ old: "Lutaml::Model::XmlAdapter::OgaAdapter",
16
+ replacement: "Lutaml::Model::Xml::OgaAdapter",
17
+ )
168
18
  end
169
19
  end
170
20
  end