lutaml-model 0.6.7 → 0.7.1

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 (60) 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_todo.yml +18 -33
  5. data/README.adoc +4380 -2557
  6. data/lib/lutaml/model/attribute.rb +94 -15
  7. data/lib/lutaml/model/choice.rb +7 -0
  8. data/lib/lutaml/model/comparable_model.rb +48 -9
  9. data/lib/lutaml/model/error/collection_count_out_of_range_error.rb +1 -1
  10. data/lib/lutaml/model/error/polymorphic_error.rb +9 -0
  11. data/lib/lutaml/model/error.rb +1 -0
  12. data/lib/lutaml/model/mapping/json_mapping.rb +17 -0
  13. data/lib/lutaml/model/{key_value_mapping.rb → mapping/key_value_mapping.rb} +58 -14
  14. data/lib/lutaml/model/{key_value_mapping_rule.rb → mapping/key_value_mapping_rule.rb} +18 -2
  15. data/lib/lutaml/model/mapping/mapping_rule.rb +299 -0
  16. data/lib/lutaml/model/mapping/toml_mapping.rb +25 -0
  17. data/lib/lutaml/model/{xml_mapping.rb → mapping/xml_mapping.rb} +97 -15
  18. data/lib/lutaml/model/{xml_mapping_rule.rb → mapping/xml_mapping_rule.rb} +20 -3
  19. data/lib/lutaml/model/mapping/yaml_mapping.rb +17 -0
  20. data/lib/lutaml/model/mapping.rb +14 -0
  21. data/lib/lutaml/model/schema/xml_compiler.rb +15 -15
  22. data/lib/lutaml/model/sequence.rb +2 -2
  23. data/lib/lutaml/model/serialize.rb +247 -97
  24. data/lib/lutaml/model/type/date.rb +1 -1
  25. data/lib/lutaml/model/type/date_time.rb +2 -2
  26. data/lib/lutaml/model/type/hash.rb +1 -1
  27. data/lib/lutaml/model/type/time.rb +2 -2
  28. data/lib/lutaml/model/type/time_without_date.rb +2 -2
  29. data/lib/lutaml/model/uninitialized_class.rb +64 -0
  30. data/lib/lutaml/model/utils.rb +14 -0
  31. data/lib/lutaml/model/validation.rb +1 -0
  32. data/lib/lutaml/model/version.rb +1 -1
  33. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +1 -1
  34. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
  35. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +1 -1
  36. data/lib/lutaml/model/xml_adapter/xml_document.rb +38 -17
  37. data/lib/lutaml/model/xml_adapter/xml_element.rb +17 -7
  38. data/lib/lutaml/model.rb +1 -0
  39. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +3 -3
  40. data/spec/fixtures/person.rb +5 -5
  41. data/spec/lutaml/model/attribute_spec.rb +37 -1
  42. data/spec/lutaml/model/cdata_spec.rb +2 -2
  43. data/spec/lutaml/model/collection_spec.rb +50 -2
  44. data/spec/lutaml/model/comparable_model_spec.rb +92 -27
  45. data/spec/lutaml/model/defaults_spec.rb +1 -1
  46. data/spec/lutaml/model/enum_spec.rb +1 -1
  47. data/spec/lutaml/model/group_spec.rb +316 -14
  48. data/spec/lutaml/model/key_value_mapping_spec.rb +41 -3
  49. data/spec/lutaml/model/polymorphic_spec.rb +348 -0
  50. data/spec/lutaml/model/render_empty_spec.rb +194 -0
  51. data/spec/lutaml/model/render_nil_spec.rb +206 -22
  52. data/spec/lutaml/model/simple_model_spec.rb +9 -9
  53. data/spec/lutaml/model/value_map_spec.rb +240 -0
  54. data/spec/lutaml/model/xml/namespace/nested_with_explicit_namespace_spec.rb +85 -0
  55. data/spec/lutaml/model/xml/xml_element_spec.rb +93 -0
  56. data/spec/lutaml/model/xml_mapping_rule_spec.rb +102 -2
  57. data/spec/lutaml/model/xml_mapping_spec.rb +45 -3
  58. data/spec/sample_model_spec.rb +3 -3
  59. metadata +20 -8
  60. data/lib/lutaml/model/mapping_rule.rb +0 -109
@@ -21,35 +21,80 @@ class RenderNil < Lutaml::Model::Serializable
21
21
  attribute :render_nil_nested, RenderNilNested
22
22
 
23
23
  json do
24
- map "name", to: :name, render_nil: true
25
- map "clay_type", to: :clay_type, render_nil: true
26
- map "glaze", to: :glaze, render_nil: true
27
- map "dimensions", to: :dimensions, render_nil: false
24
+ map "name", to: :name, render_nil: true, render_empty: true
25
+ map "clay_type", to: :clay_type, render_nil: true, render_empty: true
26
+ map "glaze", to: :glaze, render_nil: true, render_empty: true
27
+ map "dimensions", to: :dimensions, render_empty: false
28
28
  end
29
29
 
30
30
  xml do
31
31
  root "render_nil"
32
- map_element "name", to: :name, render_nil: true
33
- map_element "clay_type", to: :clay_type, render_nil: false
34
- map_element "glaze", to: :glaze, render_nil: true
32
+ map_element "name", to: :name, render_nil: true, render_empty: true
33
+ map_element "clay_type", to: :clay_type, render_nil: false, render_empty: true
34
+ map_element "glaze", to: :glaze, render_nil: true, render_empty: true
35
35
  map_element "render_nil_nested", to: :render_nil_nested, render_nil: true,
36
36
  render_default: true
37
- map_element "dimensions", to: :dimensions, render_nil: false
37
+ map_element "dimensions", to: :dimensions, render_empty: false
38
38
  end
39
39
 
40
40
  yaml do
41
- map "name", to: :name, render_nil: true
42
- map "clay_type", to: :clay_type, render_nil: false
43
- map "glaze", to: :glaze, render_nil: true
44
- map "dimensions", to: :dimensions, render_nil: false
41
+ map "name", to: :name, render_nil: true, render_empty: true
42
+ map "clay_type", to: :clay_type, render_nil: false, render_empty: true
43
+ map "glaze", to: :glaze, render_nil: true, render_empty: true
44
+ map "dimensions", to: :dimensions, render_empty: false
45
45
  map "render_nil_nested", to: :render_nil_nested, render_nil: false
46
46
  end
47
47
 
48
48
  toml do
49
- map "name", to: :name, render_nil: true
50
- map "clay_type", to: :clay_type, render_nil: false
51
- map "glaze", to: :glaze, render_nil: true
52
- map "dimensions", to: :dimensions, render_nil: false
49
+ map "name", to: :name, render_nil: :empty, render_empty: true
50
+ map "clay_type", to: :clay_type, render_nil: false, render_empty: true
51
+ map "glaze", to: :glaze, render_nil: false, render_empty: true
52
+ map "dimensions", to: :dimensions, render_empty: false
53
+ end
54
+ end
55
+
56
+ module RenderNilSpec
57
+ class OmitNilModel < Lutaml::Model::Serializable
58
+ attribute :items, :string, collection: true
59
+
60
+ xml do
61
+ root "omit-nil-model"
62
+ map_element "items", to: :items, render_nil: :omit
63
+ end
64
+
65
+ key_value do
66
+ map "items", to: :items, render_nil: :omit
67
+ end
68
+ end
69
+
70
+ class ExplicitNilModel < Lutaml::Model::Serializable
71
+ attribute :items, :string, collection: true
72
+
73
+ xml do
74
+ root "explicit-nil-model"
75
+ map_element "items", to: :items, render_nil: :as_nil
76
+ end
77
+
78
+ yaml do
79
+ map "items", to: :items, render_nil: :as_nil
80
+ end
81
+ end
82
+
83
+ class AsBlankNilModel < Lutaml::Model::Serializable
84
+ attribute :items, :string, collection: true
85
+
86
+ xml do
87
+ root "omit-nil-model"
88
+ map_element "items", to: :items, render_nil: :as_blank
89
+ end
90
+ end
91
+
92
+ class AsEmptyNilModel < Lutaml::Model::Serializable
93
+ attribute :items, :string, collection: true
94
+
95
+ yaml do
96
+ map "items", to: :items, render_nil: :as_empty
97
+ end
53
98
  end
54
99
  end
55
100
 
@@ -82,14 +127,14 @@ RSpec.describe RenderNil do
82
127
  expect(pottery.name).to be_nil
83
128
  expect(pottery.clay_type).to be_nil
84
129
  expect(pottery.glaze).to be_nil
85
- expect(pottery.dimensions).to eq([])
130
+ expect(pottery.dimensions).to be_nil
86
131
  end
87
132
 
88
133
  it "serializes to XML with render_nil option" do
89
134
  expected_xml = <<~XML
90
135
  <render_nil>
91
- <name/>
92
- <glaze/>
136
+ <name xsi:nil="true"/>
137
+ <glaze xsi:nil="true"/>
93
138
  <render_nil_nested/>
94
139
  </render_nil>
95
140
  XML
@@ -100,8 +145,8 @@ RSpec.describe RenderNil do
100
145
  it "deserializes from XML with render_nil option" do
101
146
  xml = <<~XML
102
147
  <render_nil>
103
- <name/>
104
- <glaze/>
148
+ <name xsi:nil="true" />
149
+ <glaze xsi:nil="true" />
105
150
  </render_nil>
106
151
  XML
107
152
 
@@ -148,7 +193,7 @@ RSpec.describe RenderNil do
148
193
  }
149
194
  end
150
195
 
151
- it "does not tread empty string as nil" do
196
+ it "does not treat empty string as nil" do
152
197
  expected_yaml = <<~YAML
153
198
  ---
154
199
  name: ''
@@ -165,4 +210,143 @@ RSpec.describe RenderNil do
165
210
  expect(generated_yaml).to eq(expected_yaml.strip)
166
211
  end
167
212
  end
213
+
214
+ describe "render_nil option" do
215
+ context "when :omit" do
216
+ let(:model) { RenderNilSpec::OmitNilModel.new(items: nil) }
217
+
218
+ describe "YAML" do
219
+ let(:parsed) do
220
+ RenderNilSpec::OmitNilModel.from_yaml(yaml)
221
+ end
222
+
223
+ let(:yaml) do
224
+ <<~YAML
225
+ ---
226
+ items:
227
+ YAML
228
+ end
229
+
230
+ it "omits nil collections while deserialize" do
231
+ expect(model.items).to be_nil
232
+ end
233
+
234
+ it "omits nil collections" do
235
+ expect(parsed.to_yaml.strip).to eq("--- {}")
236
+ end
237
+ end
238
+
239
+ describe "XML" do
240
+ let(:parsed) { RenderNilSpec::OmitNilModel.from_xml(xml) }
241
+
242
+ let(:xml) do
243
+ <<~XML
244
+ <omit-nil-model/>
245
+ XML
246
+ end
247
+
248
+ it "omits nil collection" do
249
+ expect(model.to_xml).not_to include("<items")
250
+ end
251
+
252
+ it "omits nil collections while deserialize" do
253
+ expect(parsed.items).to be_nil
254
+ end
255
+ end
256
+ end
257
+
258
+ context "when :as_nil" do
259
+ let(:model) { RenderNilSpec::ExplicitNilModel.new(items: nil) }
260
+
261
+ describe "YAML" do
262
+ let(:yaml) do
263
+ <<~YAML
264
+ ---
265
+ items:
266
+ YAML
267
+ end
268
+
269
+ let(:parsed) do
270
+ RenderNilSpec::ExplicitNilModel.from_yaml(yaml)
271
+ end
272
+
273
+ it "renders explicit nil" do
274
+ expect(model.to_yaml).to include("items:")
275
+ end
276
+
277
+ it "sets nil values while deserialize" do
278
+ expect(parsed.items).to be_nil
279
+ end
280
+ end
281
+
282
+ describe "XML" do
283
+ let(:xml) do
284
+ <<~XML
285
+ <explicit-nil-model>
286
+ <items xsi:nil="true"/>
287
+ </explicit-nil-model>
288
+ XML
289
+ end
290
+
291
+ let(:parsed) do
292
+ RenderNilSpec::ExplicitNilModel.from_xml(xml)
293
+ end
294
+
295
+ it "renders explicit nil" do
296
+ expect(model.to_xml).to include('<items xsi:nil="true"/>')
297
+ end
298
+
299
+ it "sets nil values while deserialize" do
300
+ expect(parsed.items).to be_nil
301
+ end
302
+ end
303
+ end
304
+
305
+ context "when :as_blank" do
306
+ let(:model) { RenderNilSpec::AsBlankNilModel.new(items: nil) }
307
+
308
+ let(:parsed) do
309
+ RenderNilSpec::AsBlankNilModel.from_xml(xml)
310
+ end
311
+
312
+ let(:xml) do
313
+ <<~XML
314
+ <explicit-nil-model>
315
+ <items/>
316
+ </explicit-nil-model>
317
+ XML
318
+ end
319
+
320
+ it "creates blank element from nil collections" do
321
+ expect(model.to_xml).to include("<items/>")
322
+ end
323
+
324
+ it "sets blank values while deserialize" do
325
+ expect(parsed.items).to eq([])
326
+ end
327
+ end
328
+
329
+ context "when :as_empty" do
330
+ let(:model) { RenderNilSpec::AsEmptyNilModel.new(items: nil) }
331
+
332
+ let(:parsed) do
333
+ RenderNilSpec::AsEmptyNilModel.from_yaml(yaml)
334
+ end
335
+
336
+ let(:yaml) do
337
+ <<~YAML
338
+ ---
339
+ items:
340
+ YAML
341
+ end
342
+
343
+ it "creates key and empty collection" do
344
+ expect(model.to_yaml).to include("items: []")
345
+ end
346
+
347
+ it "sets nil value while deserialize" do
348
+ expect(parsed.items).to be_nil
349
+ end
350
+ end
351
+ end
168
352
  end
@@ -62,26 +62,26 @@ module SimpleModel
62
62
  xml do
63
63
  root "building"
64
64
  map_attribute "name", to: :name
65
- map_element "address", to: :address
66
- map_element "room", to: :rooms
65
+ map_element "address", to: :address, treat_omitted: :omited
66
+ map_element "room", to: :rooms, treat_omitted: :omited
67
67
  end
68
68
 
69
69
  yaml do
70
70
  map "name", to: :name
71
- map "address", to: :address
72
- map "rooms", to: :rooms
71
+ map "address", to: :address, treat_omitted: :omited
72
+ map "rooms", to: :rooms, treat_omitted: :omited
73
73
  end
74
74
 
75
75
  json do
76
76
  map "name", to: :name
77
- map "address", to: :address
78
- map "rooms", to: :rooms
77
+ map "address", to: :address, treat_omitted: :omited
78
+ map "rooms", to: :rooms, treat_omitted: :omited
79
79
  end
80
80
 
81
81
  toml do
82
82
  map "name", to: :name
83
- map "address", to: :address
84
- map "rooms", to: :rooms
83
+ map "address", to: :address, treat_omitted: :omited
84
+ map "rooms", to: :rooms, treat_omitted: :omited
85
85
  end
86
86
  end
87
87
  end
@@ -182,7 +182,7 @@ RSpec.describe SimpleModel do
182
182
  default_model = SimpleModel::Building.new
183
183
  expect(default_model.name).to eq("Unnamed building")
184
184
  expect(default_model.address).to be_nil
185
- expect(default_model.rooms).to eq([])
185
+ expect(default_model.rooms).to be_nil
186
186
  end
187
187
 
188
188
  it "serializes to XML" do
@@ -0,0 +1,240 @@
1
+ # map :x, to: :y, value_map: {
2
+ # from_xml: {omitted: :omitted, xsi_nil: nil, empty: [] },
3
+ # to_xml: {omitted: :omitted, nil: :nil, empty: :empty}
4
+ # }
5
+
6
+ module ValueMapSpec
7
+ class WithValueMaps < Lutaml::Model::Serializable
8
+ attribute :omitted_as_omitted, :string
9
+ attribute :omitted_as_nil, :string
10
+ attribute :omitted_as_empty, :string
11
+
12
+ attribute :nil_as_nil, :string
13
+ attribute :nil_as_omitted, :string
14
+ attribute :nil_as_empty, :string
15
+
16
+ attribute :empty_as_empty, :string
17
+ attribute :empty_as_nil, :string
18
+ attribute :empty_as_omitted, :string
19
+
20
+ xml do
21
+ root "WithValueMaps"
22
+
23
+ map_element "omittedAsOmitted", to: :omitted_as_omitted, value_map: {
24
+ from: { omitted: :omitted },
25
+ to: { omitted: :omitted },
26
+ }
27
+ map_element "omittedAsNil", to: :omitted_as_nil, value_map: {
28
+ from: { omitted: :nil },
29
+ to: { omitted: :nil },
30
+ }
31
+ map_element "omittedAsEmpty", to: :omitted_as_empty, value_map: {
32
+ from: { omitted: :empty },
33
+ to: { omitted: :empty },
34
+ }
35
+
36
+ map_element "nilAsNil", to: :nil_as_nil, value_map: {
37
+ from: { nil: :nil },
38
+ to: { nil: :nil },
39
+ }
40
+ map_element "nilAsOmitted", to: :nil_as_omitted, value_map: {
41
+ from: { nil: :omitted },
42
+ to: { nil: :omitted },
43
+ }
44
+ map_element "nilAsEmpty", to: :nil_as_empty, value_map: {
45
+ from: { nil: :empty },
46
+ to: { nil: :empty },
47
+ }
48
+
49
+ map_element "emptyAsEmpty", to: :empty_as_empty, value_map: {
50
+ from: { empty: :empty },
51
+ to: { empty: :empty },
52
+ }
53
+ map_element "emptyAsNil", to: :empty_as_nil, value_map: {
54
+ from: { empty: :nil },
55
+ to: { empty: :nil },
56
+ }
57
+ map_element "emptyAsOmitted", to: :empty_as_omitted, value_map: {
58
+ from: { empty: :omitted },
59
+ to: { empty: :omitted },
60
+ }
61
+ end
62
+
63
+ key_value do
64
+ map "omitted_as_omitted", to: :omitted_as_omitted, value_map: {
65
+ from: { omitted: :omitted },
66
+ to: { omitted: :omitted },
67
+ }
68
+ map "omitted_as_nil", to: :omitted_as_nil, value_map: {
69
+ from: { omitted: :omitted },
70
+ to: { omitted: :nil },
71
+ }
72
+ map "omitted_as_empty", to: :omitted_as_empty, value_map: {
73
+ from: { omitted: :omitted },
74
+ to: { omitted: :empty },
75
+ }
76
+
77
+ map "nil_as_nil", to: :nil_as_nil, value_map: {
78
+ from: { nil: :nil },
79
+ to: { nil: :nil },
80
+ }
81
+ map "nil_as_omitted", to: :nil_as_omitted, value_map: {
82
+ from: { nil: :nil },
83
+ to: { nil: :omitted },
84
+ }
85
+ map "nil_as_empty", to: :nil_as_empty, value_map: {
86
+ from: { nil: :nil },
87
+ to: { nil: :empty },
88
+ }
89
+
90
+ map "empty_as_empty", to: :empty_as_empty, value_map: {
91
+ from: { empty: :empty },
92
+ to: { empty: :empty },
93
+ }
94
+ map "empty_as_nil", to: :empty_as_nil, value_map: {
95
+ from: { empty: :empty },
96
+ to: { empty: :nil },
97
+ }
98
+ map "empty_as_omitted", to: :empty_as_omitted, value_map: {
99
+ from: { empty: :empty },
100
+ to: { empty: :omitted },
101
+ }
102
+ end
103
+ end
104
+ end
105
+
106
+ RSpec.describe "ValueMap" do
107
+ describe "YAML" do
108
+ let(:model) do
109
+ uninitialized = Lutaml::Model::UninitializedClass.instance
110
+
111
+ ValueMapSpec::WithValueMaps.new(
112
+ omitted_as_omitted: uninitialized,
113
+ omitted_as_nil: uninitialized,
114
+ omitted_as_empty: uninitialized,
115
+ nil_as_nil: nil,
116
+ nil_as_omitted: nil,
117
+ nil_as_empty: nil,
118
+ empty_as_empty: "",
119
+ empty_as_nil: "",
120
+ empty_as_omitted: "",
121
+ )
122
+ end
123
+
124
+ let(:parsed) { ValueMapSpec::WithValueMaps.from_yaml(yaml) }
125
+
126
+ let(:expected_yaml) do
127
+ <<~YAML
128
+ ---
129
+ omitted_as_nil:
130
+ omitted_as_empty: ''
131
+ nil_as_nil:
132
+ nil_as_empty: ''
133
+ empty_as_empty: ''
134
+ empty_as_nil:
135
+ YAML
136
+ end
137
+
138
+ let(:yaml) do
139
+ <<~YAML
140
+ ---
141
+ nil_as_nil:
142
+ nil_as_omitted:
143
+ nil_as_empty:
144
+ empty_as_empty: ''
145
+ empty_as_nil: ''
146
+ empty_as_omitted: ''
147
+ YAML
148
+ end
149
+
150
+ it "serializes correctly" do
151
+ expect(parsed.to_yaml).to eq(expected_yaml)
152
+ end
153
+
154
+ it "deserializes correctly" do
155
+ expected = ValueMapSpec::WithValueMaps.new(
156
+ {
157
+ nil_as_nil: nil,
158
+ nil_as_omitted: nil,
159
+ nil_as_empty: nil,
160
+ empty_as_empty: "",
161
+ empty_as_nil: "",
162
+ empty_as_omitted: "",
163
+ },
164
+ { omitted: :omitted },
165
+ )
166
+
167
+ expect(parsed).to eq(expected)
168
+ end
169
+ end
170
+
171
+ describe "XML" do
172
+ context "when serializing" do
173
+ let(:model) do
174
+ ValueMapSpec::WithValueMaps.new(
175
+ {
176
+ nil_as_nil: nil,
177
+ nil_as_omitted: nil,
178
+ nil_as_empty: nil,
179
+ empty_as_empty: "",
180
+ empty_as_nil: "",
181
+ empty_as_omitted: "",
182
+ },
183
+ { omitted: :omitted },
184
+ )
185
+ end
186
+
187
+ let(:expected_xml) do
188
+ <<~XML.strip
189
+ <WithValueMaps>
190
+ <omittedAsNil xsi:nil="true"/>
191
+ <omittedAsEmpty/>
192
+ <nilAsNil xsi:nil="true"/>
193
+ <nilAsEmpty/>
194
+ <emptyAsEmpty/>
195
+ <emptyAsNil xsi:nil="true"/>
196
+ </WithValueMaps>
197
+ XML
198
+ end
199
+
200
+ it "sets correct values when serializing" do
201
+ expect(model.to_xml).to eq(expected_xml)
202
+ end
203
+ end
204
+
205
+ context "when deserializing" do
206
+ let(:xml) do
207
+ <<~XML
208
+ <WithValueMaps>
209
+ <nilAsNil xsi:nil="true" />
210
+ <nilAsOmitted xsi:nil="true" />
211
+ <nilAsEmpty xsi:nil="true" />
212
+ <emptyAsEmpty/>
213
+ <emptyAsNil/>
214
+ <emptyAsOmitted/>
215
+ </WithValueMaps>
216
+ XML
217
+ end
218
+
219
+ let(:parsed) { ValueMapSpec::WithValueMaps.from_xml(xml) }
220
+
221
+ let(:expected) do
222
+ ValueMapSpec::WithValueMaps.new(
223
+ {
224
+ nil_as_nil: nil,
225
+ nil_as_empty: "",
226
+ empty_as_empty: "",
227
+ empty_as_nil: nil,
228
+ omitted_as_nil: nil,
229
+ omitted_as_empty: "",
230
+ },
231
+ { omitted: :omitted },
232
+ )
233
+ end
234
+
235
+ it "sets correct values when deserializing" do
236
+ expect(parsed).to eq(expected)
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,85 @@
1
+ # <Base xmlns:test="https://test-namespace">
2
+ # <test:Element1>
3
+ # <test:Element>Value</test:Element>
4
+ # <ElementWithoutNamespace>
5
+ # <NestedElementWithoutNamespace>
6
+ # Value for nested element without namespace
7
+ # </NestedElementWithoutNamespace>
8
+ # </ElementWithoutNamespace>
9
+ # </test:Element1>
10
+ # </Base>
11
+
12
+ module NestedWithExplicitNamespaceSpec
13
+ class NestedElementWithoutNamespace < Lutaml::Model::Serializable
14
+ attribute :nested_element_without_namespace, :string
15
+
16
+ xml do
17
+ map_element "NestedElementWithoutNamespace",
18
+ to: :nested_element_without_namespace
19
+ end
20
+ end
21
+
22
+ class ElementWithoutNamespace < Lutaml::Model::Serializable
23
+ attribute :nested_element_without_namespace, :string
24
+
25
+ xml do
26
+ map_element "NestedElementWithoutNamespace",
27
+ to: :nested_element_without_namespace
28
+ end
29
+ end
30
+
31
+ class Element1 < Lutaml::Model::Serializable
32
+ attribute :element, :string
33
+ attribute :element_without_namespace, ElementWithoutNamespace
34
+
35
+ xml do
36
+ map_element "Element", to: :element
37
+ map_element "ElementWithoutNamespace", to: :element_without_namespace,
38
+ namespace: nil,
39
+ prefix: nil
40
+ end
41
+ end
42
+
43
+ class Base < Lutaml::Model::Serializable
44
+ attribute :element1, Element1
45
+
46
+ xml do
47
+ root "Base"
48
+ namespace "https://test-namespace", "test"
49
+
50
+ map_element "Element1", to: :element1
51
+ end
52
+ end
53
+ end
54
+
55
+ RSpec.describe "NestedWithExplicitNamespace" do
56
+ let(:xml) do
57
+ <<~XML
58
+ <Base xmlns:test="https://test-namespace">
59
+ <test:Element1>
60
+ <test:Element>Value</test:Element>
61
+ <ElementWithoutNamespace>
62
+ <NestedElementWithoutNamespace>
63
+ Value for nested element without namespace
64
+ </NestedElementWithoutNamespace>
65
+ </ElementWithoutNamespace>
66
+ </test:Element1>
67
+ </Base>
68
+ XML
69
+ end
70
+
71
+ let(:parsed) { NestedWithExplicitNamespaceSpec::Base.from_xml(xml) }
72
+
73
+ it "parses namespaced element correctly" do
74
+ expect(parsed.element1.element).to eq("Value")
75
+ end
76
+
77
+ it "parses nested element without namespace correclty" do
78
+ generated_value = parsed.element1
79
+ .element_without_namespace
80
+ .nested_element_without_namespace
81
+ .strip
82
+
83
+ expect(generated_value).to eq("Value for nested element without namespace")
84
+ end
85
+ end