lutaml-model 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +36 -20
- data/README.adoc +1003 -192
- data/lib/lutaml/model/attribute.rb +6 -2
- data/lib/lutaml/model/error/collection_true_missing_error.rb +16 -0
- data/lib/lutaml/model/error/multiple_mappings_error.rb +6 -0
- data/lib/lutaml/model/error.rb +2 -0
- data/lib/lutaml/model/key_value_mapping.rb +25 -4
- data/lib/lutaml/model/key_value_mapping_rule.rb +16 -3
- data/lib/lutaml/model/loggable.rb +15 -0
- data/lib/lutaml/model/mapping_rule.rb +14 -2
- data/lib/lutaml/model/serialize.rb +114 -64
- data/lib/lutaml/model/type/decimal.rb +5 -0
- 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 +14 -12
- data/lib/lutaml/model/xml_mapping.rb +3 -0
- data/lib/lutaml/model/xml_mapping_rule.rb +13 -4
- data/lib/lutaml/model.rb +1 -0
- 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/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 -0
- data/spec/lutaml/model/root_mappings_spec.rb +297 -0
- data/spec/lutaml/model/serializable_spec.rb +42 -7
- data/spec/lutaml/model/type/boolean_spec.rb +62 -0
- data/spec/lutaml/model/with_child_mapping_spec.rb +182 -0
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +11 -11
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +67 -1
- data/spec/lutaml/model/xml_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_mapping_spec.rb +32 -9
- data/spec/sample_model_spec.rb +114 -0
- metadata +12 -2
@@ -77,6 +77,25 @@ module SerializeableSpec
|
|
77
77
|
class GlazeTechnique < Lutaml::Model::Serializable
|
78
78
|
attribute :name, :string, values: ["Celadon", "Raku", "Majolica"]
|
79
79
|
end
|
80
|
+
|
81
|
+
class TranslateHelper < Lutaml::Model::Serializable
|
82
|
+
attribute :id, :string
|
83
|
+
attribute :path, :string
|
84
|
+
attribute :name, :string
|
85
|
+
end
|
86
|
+
|
87
|
+
class TranslateMappings < Lutaml::Model::Serializable
|
88
|
+
attribute :translate, TranslateHelper, collection: true
|
89
|
+
|
90
|
+
key_value do
|
91
|
+
map "translate", to: :translate, child_mappings:
|
92
|
+
{
|
93
|
+
id: :key,
|
94
|
+
path: %i[path link],
|
95
|
+
name: %i[path name],
|
96
|
+
}
|
97
|
+
end
|
98
|
+
end
|
80
99
|
end
|
81
100
|
|
82
101
|
RSpec.describe Lutaml::Model::Serializable do
|
@@ -87,7 +106,7 @@ RSpec.describe Lutaml::Model::Serializable do
|
|
87
106
|
end.to change(
|
88
107
|
described_class, :model
|
89
108
|
)
|
90
|
-
.from(
|
109
|
+
.from(described_class)
|
91
110
|
.to(SerializeableSpec::TestModel)
|
92
111
|
end
|
93
112
|
end
|
@@ -173,7 +192,7 @@ RSpec.describe Lutaml::Model::Serializable do
|
|
173
192
|
end
|
174
193
|
end
|
175
194
|
|
176
|
-
describe ".
|
195
|
+
describe ".translate_mappings" do
|
177
196
|
let(:child_mappings) do
|
178
197
|
{
|
179
198
|
id: :key,
|
@@ -205,17 +224,33 @@ RSpec.describe Lutaml::Model::Serializable do
|
|
205
224
|
}
|
206
225
|
end
|
207
226
|
|
227
|
+
let(:attr) { SerializeableSpec::TranslateMappings.attributes[:translate] }
|
228
|
+
|
208
229
|
let(:expected_value) do
|
209
230
|
[
|
210
|
-
{
|
211
|
-
|
212
|
-
|
231
|
+
SerializeableSpec::TranslateHelper.new({
|
232
|
+
"id" => "foo",
|
233
|
+
"name" => "one",
|
234
|
+
"path" => "link one",
|
235
|
+
}),
|
236
|
+
SerializeableSpec::TranslateHelper.new({
|
237
|
+
"id" => "abc",
|
238
|
+
"name" => "two",
|
239
|
+
"path" => "link two",
|
240
|
+
}),
|
241
|
+
SerializeableSpec::TranslateHelper.new({
|
242
|
+
"id" => "hello",
|
243
|
+
"name" => "three",
|
244
|
+
"path" => "link three",
|
245
|
+
}),
|
213
246
|
]
|
214
247
|
end
|
215
248
|
|
216
249
|
it "generates hash based on child_mappings" do
|
217
|
-
|
218
|
-
|
250
|
+
actual_value = described_class.translate_mappings(hash, child_mappings, attr, :yaml)
|
251
|
+
|
252
|
+
expect(actual_value.map { |obj| [obj.id, obj.name, obj.path] })
|
253
|
+
.to eq(expected_value.map { |obj| [obj.id, obj.name, obj.path] })
|
219
254
|
end
|
220
255
|
end
|
221
256
|
|
@@ -1,5 +1,23 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
+
module BooleanSpec
|
4
|
+
class Employee < Lutaml::Model::Serializable
|
5
|
+
attribute :name, :string
|
6
|
+
attribute :full_time, :boolean
|
7
|
+
attribute :on_leave, :boolean
|
8
|
+
attribute :remote, :boolean
|
9
|
+
attribute :active, :boolean
|
10
|
+
|
11
|
+
key_value do
|
12
|
+
map "name", to: :name
|
13
|
+
map "full_time", to: :full_time
|
14
|
+
map "on_leave", to: :on_leave
|
15
|
+
map "remote", to: :remote, render_nil: true
|
16
|
+
map "active", to: :active, render_nil: false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
3
21
|
RSpec.describe Lutaml::Model::Type::Boolean do
|
4
22
|
describe ".cast" do
|
5
23
|
let(:truthy_values) { [true, "true", "t", "yes", "y", "1"] }
|
@@ -51,4 +69,48 @@ RSpec.describe Lutaml::Model::Type::Boolean do
|
|
51
69
|
expect(described_class.serialize(true)).to be true
|
52
70
|
end
|
53
71
|
end
|
72
|
+
|
73
|
+
context "with key-value serialization" do
|
74
|
+
let(:yaml) do
|
75
|
+
{
|
76
|
+
"name" => "John Smith",
|
77
|
+
"full_time" => true,
|
78
|
+
"on_leave" => false,
|
79
|
+
"remote" => nil,
|
80
|
+
"active" => nil,
|
81
|
+
}.to_yaml
|
82
|
+
end
|
83
|
+
|
84
|
+
let(:expected_yaml) do
|
85
|
+
{
|
86
|
+
"name" => "John Smith",
|
87
|
+
"full_time" => true,
|
88
|
+
"on_leave" => false,
|
89
|
+
"remote" => nil,
|
90
|
+
}.to_yaml
|
91
|
+
end
|
92
|
+
|
93
|
+
it "deserializes boolean values correctly" do
|
94
|
+
employee = BooleanSpec::Employee.from_yaml(yaml)
|
95
|
+
|
96
|
+
expect(employee.name).to eq("John Smith")
|
97
|
+
expect(employee.full_time).to be true
|
98
|
+
expect(employee.on_leave).to be false
|
99
|
+
expect(employee.remote).to be_nil
|
100
|
+
expect(employee.active).to be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it "serializes boolean values correctly" do
|
104
|
+
employee = BooleanSpec::Employee.new(
|
105
|
+
name: "John Smith",
|
106
|
+
full_time: true,
|
107
|
+
on_leave: false,
|
108
|
+
remote: nil,
|
109
|
+
active: nil,
|
110
|
+
)
|
111
|
+
|
112
|
+
yaml_output = employee.to_yaml
|
113
|
+
expect(yaml_output).to eq(expected_yaml)
|
114
|
+
end
|
115
|
+
end
|
54
116
|
end
|
@@ -37,6 +37,63 @@ module ChildMapping
|
|
37
37
|
}
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
class JS < Lutaml::Model::Serializable
|
42
|
+
attribute :prop, :string
|
43
|
+
attribute :hook, :string
|
44
|
+
|
45
|
+
key_value do
|
46
|
+
map :prop, to: :prop
|
47
|
+
map :hook, to: :hook
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Symbol < Lutaml::Model::Serializable
|
52
|
+
attribute :ascii, :string
|
53
|
+
attribute :html, :string
|
54
|
+
attribute :latex, :string
|
55
|
+
attribute :unicode, :string
|
56
|
+
attribute :js, JS
|
57
|
+
|
58
|
+
key_value do
|
59
|
+
map :ascii, to: :ascii
|
60
|
+
map :html, to: :html
|
61
|
+
map :latex, to: :latex
|
62
|
+
map :unicode, to: :unicode
|
63
|
+
map :js, to: :js
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Prefix < Lutaml::Model::Serializable
|
68
|
+
attribute :id, :string
|
69
|
+
attribute :name, :string
|
70
|
+
attribute :symbol, Symbol
|
71
|
+
attribute :base, :integer
|
72
|
+
attribute :power, :integer
|
73
|
+
|
74
|
+
key_value do
|
75
|
+
map :prefix_id, to: :id
|
76
|
+
map :name, to: :name
|
77
|
+
map :symbol, to: :symbol
|
78
|
+
map :base, to: :base
|
79
|
+
map :power, to: :power
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Prefixes < Lutaml::Model::Serializable
|
84
|
+
attribute :prefixes, Prefix, collection: true
|
85
|
+
|
86
|
+
key_value do
|
87
|
+
map "prefixes", to: :prefixes, child_mappings:
|
88
|
+
{
|
89
|
+
id: :key,
|
90
|
+
name: :name,
|
91
|
+
symbol: :symbol,
|
92
|
+
base: :base,
|
93
|
+
power: :power,
|
94
|
+
}
|
95
|
+
end
|
96
|
+
end
|
40
97
|
end
|
41
98
|
|
42
99
|
RSpec.describe ChildMapping do
|
@@ -72,11 +129,52 @@ RSpec.describe ChildMapping do
|
|
72
129
|
let(:expected_paths) { ["link one", "link two", "link three"] }
|
73
130
|
let(:expected_names) { ["one", "two", "three"] }
|
74
131
|
|
132
|
+
let(:prefixes_hash) do
|
133
|
+
{
|
134
|
+
"prefixes" => {
|
135
|
+
"NISTp10_30" => {
|
136
|
+
"name" => "quetta",
|
137
|
+
"symbol" => {
|
138
|
+
"ascii" => "Q",
|
139
|
+
"html" => "Q",
|
140
|
+
"latex" => "Q",
|
141
|
+
"unicode" => "Q",
|
142
|
+
"js" => {
|
143
|
+
"prop" => "head",
|
144
|
+
"hook" => "async",
|
145
|
+
},
|
146
|
+
},
|
147
|
+
"base" => 10,
|
148
|
+
"power" => 30,
|
149
|
+
},
|
150
|
+
"NISTp10_27" => {
|
151
|
+
"name" => "ronna",
|
152
|
+
"symbol" => {
|
153
|
+
"ascii" => "R",
|
154
|
+
"html" => "R",
|
155
|
+
"latex" => "R",
|
156
|
+
"unicode" => "R",
|
157
|
+
"js" => {
|
158
|
+
"prop" => "head",
|
159
|
+
"hook" => "async",
|
160
|
+
},
|
161
|
+
},
|
162
|
+
"base" => 10,
|
163
|
+
"power" => 27,
|
164
|
+
},
|
165
|
+
},
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
75
169
|
context "with json" do
|
76
170
|
let(:json) do
|
77
171
|
hash.to_json
|
78
172
|
end
|
79
173
|
|
174
|
+
let(:prefixes_json) do
|
175
|
+
prefixes_hash.to_json
|
176
|
+
end
|
177
|
+
|
80
178
|
describe ".from_json" do
|
81
179
|
it "create model according to json" do
|
82
180
|
instance = mapper.from_json(json)
|
@@ -86,6 +184,14 @@ RSpec.describe ChildMapping do
|
|
86
184
|
expect(instance.schemas.map(&:path)).to eq(expected_paths)
|
87
185
|
expect(instance.schemas.map(&:name)).to eq(expected_names)
|
88
186
|
end
|
187
|
+
|
188
|
+
it "create model according to json with nesting values" do
|
189
|
+
instance = ChildMapping::Prefixes.from_json(prefixes_json)
|
190
|
+
|
191
|
+
expect(instance.prefixes.first.id).to eq("NISTp10_30")
|
192
|
+
expect(instance.prefixes.first.symbol.ascii).to eq("Q")
|
193
|
+
expect(instance.prefixes.first.symbol.js.hook).to eq("async")
|
194
|
+
end
|
89
195
|
end
|
90
196
|
|
91
197
|
describe ".to_json" do
|
@@ -98,6 +204,13 @@ RSpec.describe ChildMapping do
|
|
98
204
|
|
99
205
|
expect(instance.to_json).to eq(json)
|
100
206
|
end
|
207
|
+
|
208
|
+
it "converts object to json with nesting values" do
|
209
|
+
instance = ChildMapping::Prefixes.from_json(prefixes_json)
|
210
|
+
serialized = instance.to_json
|
211
|
+
|
212
|
+
expect(serialized).to be_equivalent_to(prefixes_json)
|
213
|
+
end
|
101
214
|
end
|
102
215
|
end
|
103
216
|
|
@@ -106,6 +219,10 @@ RSpec.describe ChildMapping do
|
|
106
219
|
hash.to_yaml
|
107
220
|
end
|
108
221
|
|
222
|
+
let(:prefixes_yaml) do
|
223
|
+
prefixes_hash.to_yaml
|
224
|
+
end
|
225
|
+
|
109
226
|
describe ".from_yaml" do
|
110
227
|
it "create model according to yaml" do
|
111
228
|
instance = mapper.from_yaml(yaml)
|
@@ -115,6 +232,14 @@ RSpec.describe ChildMapping do
|
|
115
232
|
expect(instance.schemas.map(&:path)).to eq(expected_paths)
|
116
233
|
expect(instance.schemas.map(&:name)).to eq(expected_names)
|
117
234
|
end
|
235
|
+
|
236
|
+
it "create model according to yaml with nesting values" do
|
237
|
+
instance = ChildMapping::Prefixes.from_yaml(prefixes_yaml)
|
238
|
+
|
239
|
+
expect(instance.prefixes.first.id).to eq("NISTp10_30")
|
240
|
+
expect(instance.prefixes.first.symbol.ascii).to eq("Q")
|
241
|
+
expect(instance.prefixes.first.symbol.js.hook).to eq("async")
|
242
|
+
end
|
118
243
|
end
|
119
244
|
|
120
245
|
describe ".to_yaml" do
|
@@ -127,6 +252,13 @@ RSpec.describe ChildMapping do
|
|
127
252
|
|
128
253
|
expect(instance.to_yaml).to eq(yaml)
|
129
254
|
end
|
255
|
+
|
256
|
+
it "converts object to yaml with nesting values" do
|
257
|
+
instance = ChildMapping::Prefixes.from_yaml(prefixes_yaml)
|
258
|
+
serialized = instance.to_yaml
|
259
|
+
|
260
|
+
expect(YAML.safe_load(serialized)).to eq(YAML.safe_load(prefixes_yaml))
|
261
|
+
end
|
130
262
|
end
|
131
263
|
end
|
132
264
|
|
@@ -145,6 +277,40 @@ RSpec.describe ChildMapping do
|
|
145
277
|
TOML
|
146
278
|
end
|
147
279
|
|
280
|
+
let(:prefixes_toml) do
|
281
|
+
<<~TOML
|
282
|
+
[prefixes.NISTp10_30]
|
283
|
+
name = "quetta"
|
284
|
+
base = 10
|
285
|
+
power = 30
|
286
|
+
|
287
|
+
[prefixes.NISTp10_30.symbol]
|
288
|
+
ascii = "Q"
|
289
|
+
html = "Q"
|
290
|
+
latex = "Q"
|
291
|
+
unicode = "Q"
|
292
|
+
|
293
|
+
[prefixes.NISTp10_30.symbol.js]
|
294
|
+
prop = "head"
|
295
|
+
hook = "async"
|
296
|
+
|
297
|
+
[prefixes.NISTp10_27]
|
298
|
+
name = "ronna"
|
299
|
+
base = 10
|
300
|
+
power = 27
|
301
|
+
|
302
|
+
[prefixes.NISTp10_27.symbol]
|
303
|
+
ascii = "R"
|
304
|
+
html = "R"
|
305
|
+
latex = "R"
|
306
|
+
unicode = "R"
|
307
|
+
|
308
|
+
[prefixes.NISTp10_27.symbol.js]
|
309
|
+
prop = "head"
|
310
|
+
hook = "async"
|
311
|
+
TOML
|
312
|
+
end
|
313
|
+
|
148
314
|
describe ".from_toml" do
|
149
315
|
it "create model according to toml" do
|
150
316
|
instance = mapper.from_toml(toml)
|
@@ -154,6 +320,14 @@ RSpec.describe ChildMapping do
|
|
154
320
|
expect(instance.schemas.map(&:path)).to eq(expected_paths)
|
155
321
|
expect(instance.schemas.map(&:name)).to eq(expected_names)
|
156
322
|
end
|
323
|
+
|
324
|
+
it "create model according to toml with nesting values" do
|
325
|
+
instance = ChildMapping::Prefixes.from_toml(prefixes_toml)
|
326
|
+
|
327
|
+
expect(instance.prefixes.first.id).to eq("NISTp10_30")
|
328
|
+
expect(instance.prefixes.first.symbol.ascii).to eq("Q")
|
329
|
+
expect(instance.prefixes.first.symbol.js.hook).to eq("async")
|
330
|
+
end
|
157
331
|
end
|
158
332
|
|
159
333
|
describe ".to_toml" do
|
@@ -169,6 +343,14 @@ RSpec.describe ChildMapping do
|
|
169
343
|
|
170
344
|
expect(actual.attributes).to eq(expected.attributes)
|
171
345
|
end
|
346
|
+
|
347
|
+
it "converts object to toml with nesting values" do
|
348
|
+
instance = ChildMapping::Prefixes.from_toml(prefixes_toml)
|
349
|
+
actual = Lutaml::Model::Config.toml_adapter.parse(instance.to_toml)
|
350
|
+
expected = Lutaml::Model::Config.toml_adapter.parse(prefixes_toml)
|
351
|
+
|
352
|
+
expect(actual.attributes).to eq(expected.attributes)
|
353
|
+
end
|
172
354
|
end
|
173
355
|
end
|
174
356
|
end
|
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
require "oga"
|
3
3
|
require_relative "../../../../lib/lutaml/model/xml_adapter/oga_adapter"
|
4
4
|
|
5
|
-
RSpec.
|
5
|
+
RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
|
6
6
|
let(:xml_string) do
|
7
7
|
<<~XML
|
8
8
|
<root xmlns="http://example.com/default" xmlns:prefix="http://example.com/prefixed">
|
@@ -14,21 +14,21 @@ RSpec.xdescribe Lutaml::Model::XmlAdapter::OgaAdapter do
|
|
14
14
|
let(:document) { described_class.parse(xml_string) }
|
15
15
|
|
16
16
|
context "parsing XML with namespaces" do
|
17
|
+
let(:child) { document.root.children[1] }
|
18
|
+
|
17
19
|
it "parses the root element with default namespace" do
|
18
20
|
expect(document.root.name).to eq("root")
|
19
|
-
expect(document.root.namespace).to eq("http://example.com/default")
|
20
|
-
expect(document.root.
|
21
|
+
expect(document.root.namespace.uri).to eq("http://example.com/default")
|
22
|
+
expect(document.root.namespace.prefix).to be_nil
|
21
23
|
end
|
22
24
|
|
23
25
|
it "parses child element with prefixed namespace" do
|
24
|
-
child
|
25
|
-
expect(child.
|
26
|
-
expect(child.namespace).to eq("
|
27
|
-
expect(child.namespace_prefix).to eq("prefix")
|
26
|
+
expect(child.name).to eq("prefix:child")
|
27
|
+
expect(child.namespace.uri).to eq("http://example.com/prefixed")
|
28
|
+
expect(child.namespace.prefix).to eq("prefix")
|
28
29
|
end
|
29
30
|
|
30
31
|
it "parses attributes with and without namespaces" do
|
31
|
-
child = document.root.children.first
|
32
32
|
expect(child.attributes["attr"].value).to eq("value")
|
33
33
|
expect(child.attributes["attr"].namespace).to be_nil
|
34
34
|
expect(child.attributes["prefix:attr"].value).to eq("prefixed_value")
|
@@ -42,12 +42,12 @@ RSpec.xdescribe Lutaml::Model::XmlAdapter::OgaAdapter do
|
|
42
42
|
xml_output = document.to_xml
|
43
43
|
parsed_output = Oga.parse_xml(xml_output)
|
44
44
|
|
45
|
-
root = parsed_output.
|
45
|
+
root = parsed_output.children.first
|
46
46
|
expect(root.name).to eq("root")
|
47
47
|
expect(root.namespace.uri).to eq("http://example.com/default")
|
48
48
|
|
49
|
-
child = root.children
|
50
|
-
expect(child.
|
49
|
+
child = root.children[1]
|
50
|
+
expect(child.expanded_name).to eq("prefix:child")
|
51
51
|
expect(child.namespace.uri).to eq("http://example.com/prefixed")
|
52
52
|
expect(child.get("attr")).to eq("value")
|
53
53
|
expect(child.get("prefix:attr")).to eq("prefixed_value")
|
@@ -86,6 +86,43 @@ RSpec.shared_context "XML namespace models" do
|
|
86
86
|
prefix: nil
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
90
|
+
class Body < Lutaml::Model::Serializable
|
91
|
+
attribute :paragraph, :string
|
92
|
+
|
93
|
+
xml do
|
94
|
+
map_element "p", to: :paragraph
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Element < Lutaml::Model::Serializable
|
99
|
+
attribute :text, :string
|
100
|
+
xml do
|
101
|
+
root "test-element"
|
102
|
+
namespace "http://www.test.com/schemas/test/1.0/", "test"
|
103
|
+
map_content to: :text
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Front < Lutaml::Model::Serializable
|
108
|
+
attribute :test_element, Element
|
109
|
+
|
110
|
+
xml do
|
111
|
+
namespace "http://www.test.com/schemas/test/1.0/", "test"
|
112
|
+
map_element "test-element", to: :test_element
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Article < Lutaml::Model::Serializable
|
117
|
+
attribute :front, Front
|
118
|
+
attribute :body, Body
|
119
|
+
|
120
|
+
xml do
|
121
|
+
root "article"
|
122
|
+
map_element "front", to: :front, prefix: "test", namespace: "http://www.test.com/schemas/test/1.0/"
|
123
|
+
map_element "body", to: :body
|
124
|
+
end
|
125
|
+
end
|
89
126
|
end
|
90
127
|
|
91
128
|
RSpec.shared_examples "XML serialization with namespace" do |model_class, xml_string|
|
@@ -236,6 +273,35 @@ RSpec.shared_examples "an XML namespace parser" do |adapter_class|
|
|
236
273
|
expect(generated_xml).to be_equivalent_to(xml)
|
237
274
|
end
|
238
275
|
end
|
276
|
+
|
277
|
+
context "when custom namespace is used" do
|
278
|
+
let(:xml_input) do
|
279
|
+
<<~XML
|
280
|
+
<article xmlns:test="http://www.test.com/schemas/test/1.0/">
|
281
|
+
<test:front>
|
282
|
+
<test:test-element>Text Here</test:test-element>
|
283
|
+
</test:front>
|
284
|
+
<body>
|
285
|
+
<p>This is a paragraph</p>
|
286
|
+
</body>
|
287
|
+
</article>
|
288
|
+
XML
|
289
|
+
end
|
290
|
+
|
291
|
+
describe "XML serialization" do
|
292
|
+
it "correctly deserializes from XML" do
|
293
|
+
article = Article.from_xml(xml_input)
|
294
|
+
expect(article.body.paragraph).to eq("This is a paragraph")
|
295
|
+
end
|
296
|
+
|
297
|
+
it "round-trips XML" do
|
298
|
+
article = Article.from_xml(xml_input)
|
299
|
+
output_xml = article.to_xml(pretty: true)
|
300
|
+
|
301
|
+
expect(output_xml).to be_equivalent_to(xml_input)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
239
305
|
end
|
240
306
|
|
241
307
|
RSpec.describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
|
@@ -246,6 +312,6 @@ RSpec.describe Lutaml::Model::XmlAdapter::OxAdapter do
|
|
246
312
|
it_behaves_like "an XML namespace parser", described_class
|
247
313
|
end
|
248
314
|
|
249
|
-
RSpec.
|
315
|
+
RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
|
250
316
|
it_behaves_like "an XML namespace parser", described_class
|
251
317
|
end
|
@@ -119,7 +119,7 @@ RSpec.shared_examples "an XML adapter" do |adapter_class|
|
|
119
119
|
|
120
120
|
parsed = XmlAdapterSpec::Maths.from_xml(input_xml)
|
121
121
|
|
122
|
-
expect(parsed.to_xml.strip).to
|
122
|
+
expect(parsed.to_xml.strip).to be_equivalent_to(output_xml.strip)
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
@@ -173,6 +173,6 @@ RSpec.describe Lutaml::Model::XmlAdapter::OxAdapter do
|
|
173
173
|
it_behaves_like "an XML adapter", described_class
|
174
174
|
end
|
175
175
|
|
176
|
-
RSpec.
|
176
|
+
RSpec.describe Lutaml::Model::XmlAdapter::OgaAdapter do
|
177
177
|
it_behaves_like "an XML adapter", described_class
|
178
178
|
end
|
@@ -325,7 +325,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
|
|
325
325
|
end
|
326
326
|
|
327
327
|
# Skipping for OX because it does not handle namespaces
|
328
|
-
context "overriding child namespace prefix", skip: adapter_class
|
328
|
+
context "overriding child namespace prefix", skip: adapter_class == Lutaml::Model::XmlAdapter::OxAdapter do
|
329
329
|
let(:input_xml) do
|
330
330
|
<<~XML
|
331
331
|
<OverrideDefaultNamespacePrefix
|
@@ -342,9 +342,20 @@ RSpec.describe Lutaml::Model::XmlMapping do
|
|
342
342
|
XML
|
343
343
|
end
|
344
344
|
|
345
|
+
let(:oga_expected_xml) do
|
346
|
+
"<OverrideDefaultNamespacePrefix xmlns:abc=\"http://www.omg.org/spec/XMI/20131001\">" +
|
347
|
+
"<abc:SameElementName App=\"hello\" xmlns:GML=\"http://www.sparxsystems.com/profiles/GML/1.0\" xmlns:CityGML=\"http://www.sparxsystems.com/profiles/CityGML/1.0\">" +
|
348
|
+
"<GML:ApplicationSchema>GML App</GML:ApplicationSchema>" +
|
349
|
+
"<CityGML:ApplicationSchema>CityGML App</CityGML:ApplicationSchema>" +
|
350
|
+
"<abc:ApplicationSchema>App</abc:ApplicationSchema>" +
|
351
|
+
"</abc:SameElementName>" +
|
352
|
+
"</OverrideDefaultNamespacePrefix>"
|
353
|
+
end
|
354
|
+
|
345
355
|
it "expect to round-trips" do
|
346
356
|
parsed = XmlMapping::OverrideDefaultNamespacePrefix.from_xml(input_xml)
|
347
|
-
|
357
|
+
expected_xml = adapter_class.type == "oga" ? oga_expected_xml : input_xml
|
358
|
+
expect(parsed.to_xml).to be_equivalent_to(expected_xml)
|
348
359
|
end
|
349
360
|
end
|
350
361
|
|
@@ -379,6 +390,15 @@ RSpec.describe Lutaml::Model::XmlMapping do
|
|
379
390
|
"ApplicationSchema",
|
380
391
|
"ApplicationSchema",
|
381
392
|
],
|
393
|
+
Lutaml::Model::XmlAdapter::OgaAdapter => [
|
394
|
+
"text",
|
395
|
+
"ApplicationSchema",
|
396
|
+
"text",
|
397
|
+
"ApplicationSchema",
|
398
|
+
"text",
|
399
|
+
"ApplicationSchema",
|
400
|
+
"text",
|
401
|
+
],
|
382
402
|
}
|
383
403
|
end
|
384
404
|
|
@@ -600,6 +620,14 @@ RSpec.describe Lutaml::Model::XmlMapping do
|
|
600
620
|
it "contain schemaLocation attributes" do
|
601
621
|
expect(Paragraph.from_xml(xml).to_xml).to be_equivalent_to(xml)
|
602
622
|
end
|
623
|
+
|
624
|
+
it "prints warning if defined explicitly in class" do
|
625
|
+
error_regex = /\[Lutaml::Model\] WARN: `schemaLocation` is handled by default\. No need to explecitly define at `xml_mapping_spec.rb:\d+`/
|
626
|
+
|
627
|
+
expect do
|
628
|
+
Lutaml::Model::XmlMapping.new.map_attribute("schemaLocation", to: :schema_location)
|
629
|
+
end.to output(error_regex).to_stderr
|
630
|
+
end
|
603
631
|
end
|
604
632
|
|
605
633
|
context "when mixed: true" do
|
@@ -1032,12 +1060,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
|
|
1032
1060
|
end
|
1033
1061
|
|
1034
1062
|
it "round-trips xml" do
|
1035
|
-
expected_xml =
|
1036
|
-
expected_nokogiri_xml
|
1037
|
-
else
|
1038
|
-
expected_ox_xml
|
1039
|
-
end
|
1040
|
-
|
1063
|
+
expected_xml = adapter_class.type == "ox" ? expected_ox_xml : expected_nokogiri_xml
|
1041
1064
|
expect(XmlMapping::SpecialCharContentWithMapAll.from_xml(xml).to_xml).to eq(expected_xml)
|
1042
1065
|
end
|
1043
1066
|
end
|
@@ -1066,7 +1089,7 @@ RSpec.describe Lutaml::Model::XmlMapping do
|
|
1066
1089
|
it_behaves_like "having XML Mappings", described_class
|
1067
1090
|
end
|
1068
1091
|
|
1069
|
-
describe Lutaml::Model::XmlAdapter::OgaAdapter
|
1092
|
+
describe Lutaml::Model::XmlAdapter::OgaAdapter do
|
1070
1093
|
it_behaves_like "having XML Mappings", described_class
|
1071
1094
|
end
|
1072
1095
|
end
|