lutaml-model 0.3.29 → 0.3.30
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/.github/workflows/dependent-repos.json +15 -0
- data/.github/workflows/dependent-tests.yml +14 -0
- data/.rubocop_todo.yml +15 -7
- data/lib/lutaml/model/json_adapter/json_document.rb +1 -1
- data/lib/lutaml/model/json_adapter/multi_json_adapter.rb +1 -1
- data/lib/lutaml/model/json_adapter/standard_json_adapter.rb +1 -1
- data/lib/lutaml/model/serialize.rb +16 -14
- data/lib/lutaml/model/toml_adapter/toml_document.rb +1 -1
- data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +1 -1
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +1 -1
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/nokogiri.rb +10 -0
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +5 -1
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +5 -3
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +1 -1
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +25 -10
- data/lib/lutaml/model/xml_adapter/xml_document.rb +12 -24
- data/lib/lutaml/model/yaml_adapter/standard_yaml_adapter.rb +1 -1
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +1 -1
- data/spec/fixtures/xml/latin_encoding.xml +5 -0
- data/spec/fixtures/xml/shift_jis.xml +4 -0
- data/spec/lutaml/model/defaults_spec.rb +74 -0
- data/spec/lutaml/model/mixed_content_spec.rb +190 -7
- data/spec/lutaml/model/xml_mapping_spec.rb +679 -543
- metadata +6 -2
@@ -1,4 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
|
+
|
3
|
+
require "lutaml/model/xml_adapter/ox_adapter"
|
4
|
+
require "lutaml/model/xml_adapter/oga_adapter"
|
5
|
+
|
2
6
|
require_relative "../../../lib/lutaml/model/xml_mapping"
|
3
7
|
require_relative "../../../lib/lutaml/model/xml_mapping_rule"
|
4
8
|
|
@@ -177,6 +181,25 @@ module XmlMapping
|
|
177
181
|
end
|
178
182
|
end
|
179
183
|
|
184
|
+
class MapAllWithCustomMethod < Lutaml::Model::Serializable
|
185
|
+
attribute :all_content, :string
|
186
|
+
|
187
|
+
xml do
|
188
|
+
root "MapAllWithCustomMethod"
|
189
|
+
|
190
|
+
map_all to: :all_content, with: { to: :content_to_xml, from: :content_from_xml }
|
191
|
+
end
|
192
|
+
|
193
|
+
def content_to_xml(model, parent, doc)
|
194
|
+
content = model.all_content.sub(/^<div>/, "").sub(/<\/div>$/, "")
|
195
|
+
doc.add_xml_fragment(parent, content)
|
196
|
+
end
|
197
|
+
|
198
|
+
def content_from_xml(model, value)
|
199
|
+
model.all_content = "<div>#{value}</div>"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
180
203
|
class WithMapAll < Lutaml::Model::Serializable
|
181
204
|
attribute :all_content, :string
|
182
205
|
attribute :attr, :string
|
@@ -259,678 +282,791 @@ module XmlMapping
|
|
259
282
|
end
|
260
283
|
|
261
284
|
RSpec.describe Lutaml::Model::XmlMapping do
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
285
|
+
shared_examples "having XML Mappings" do |adapter_class|
|
286
|
+
around do |example|
|
287
|
+
old_adapter = Lutaml::Model::Config.xml_adapter
|
288
|
+
Lutaml::Model::Config.xml_adapter = adapter_class
|
266
289
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
expect(parsed.beta).to eq("bye")
|
271
|
-
expect(parsed.to_xml).to be_equivalent_to(input_xml)
|
290
|
+
example.run
|
291
|
+
ensure
|
292
|
+
Lutaml::Model::Config.xml_adapter = old_adapter
|
272
293
|
end
|
273
|
-
end
|
274
|
-
|
275
|
-
context "explicit namespace" do
|
276
|
-
mml = '<math xmlns="http://www.w3.org/1998/Math/MathML"><mfenced open="("></mfenced></math>'
|
277
294
|
|
278
|
-
|
279
|
-
parsed = XmlMapping::MmlMath.from_xml(mml)
|
280
|
-
expect(parsed.to_xml).to be_equivalent_to(mml)
|
281
|
-
end
|
282
|
-
end
|
295
|
+
let(:mapping) { Lutaml::Model::XmlMapping.new }
|
283
296
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
<abc:ApplicationSchema>App</abc:ApplicationSchema>
|
292
|
-
</abc:SameElementName>
|
293
|
-
</OverrideDefaultNamespacePrefix>
|
297
|
+
context "attribute namespace" do
|
298
|
+
input_xml = <<~XML
|
299
|
+
<ns1:example ex1:alpha="hello"
|
300
|
+
beta="bye"
|
301
|
+
xmlns:ns1="http://www.check.com"
|
302
|
+
xmlns:ex1="http://www.example.com">
|
303
|
+
</ns1:example>
|
294
304
|
XML
|
295
|
-
end
|
296
|
-
|
297
|
-
it "expect to round-trips" do
|
298
|
-
parsed = XmlMapping::OverrideDefaultNamespacePrefix.from_xml(input_xml)
|
299
|
-
expect(parsed.to_xml).to be_equivalent_to(input_xml)
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
context "with same name elements" do
|
304
|
-
let(:input_xml) do
|
305
|
-
<<~XML
|
306
|
-
<SameElementName App="hello" xmlns="http://www.omg.org/spec/XMI/20131001" xmlns:GML="http://www.sparxsystems.com/profiles/GML/1.0" xmlns:CityGML="http://www.sparxsystems.com/profiles/CityGML/1.0">
|
307
|
-
<GML:ApplicationSchema>GML App</GML:ApplicationSchema>
|
308
|
-
<CityGML:ApplicationSchema>CityGML App</CityGML:ApplicationSchema>
|
309
|
-
<ApplicationSchema>App</ApplicationSchema>
|
310
|
-
</SameElementName>
|
311
|
-
XML
|
312
|
-
end
|
313
305
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
expect(parsed.app).to eq("hello")
|
321
|
-
expect(parsed.element_order).to eq(["text", "ApplicationSchema", "text",
|
322
|
-
"ApplicationSchema", "text", "ApplicationSchema", "text"])
|
323
|
-
expect(XmlMapping::SameNameDifferentNamespace.from_xml(input_xml).to_xml).to be_equivalent_to(input_xml)
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
context "with elements have different prefixed namespaces" do
|
328
|
-
before do
|
329
|
-
mapping.root("XMI")
|
330
|
-
mapping.namespace("http://www.omg.org/spec/XMI/20131001")
|
331
|
-
mapping.map_element(
|
332
|
-
"ApplicationSchema",
|
333
|
-
to: :gml_application_schema,
|
334
|
-
namespace: "http://www.sparxsystems.com/profiles/GML/1.0",
|
335
|
-
prefix: "GML",
|
336
|
-
)
|
337
|
-
mapping.map_element(
|
338
|
-
"ApplicationSchema",
|
339
|
-
to: :citygml_application_schema,
|
340
|
-
namespace: "http://www.sparxsystems.com/profiles/CityGML/1.0",
|
341
|
-
prefix: "CityGML",
|
342
|
-
)
|
343
|
-
mapping.map_element(
|
344
|
-
"ApplicationSchema",
|
345
|
-
to: :citygml_application_schema,
|
346
|
-
namespace: "http://www.sparxsystems.com/profiles/CGML/1.0",
|
347
|
-
prefix: "CGML",
|
348
|
-
)
|
349
|
-
end
|
350
|
-
|
351
|
-
it "maps elements correctly" do
|
352
|
-
expect(mapping.elements[0].namespace).to eq("http://www.sparxsystems.com/profiles/GML/1.0")
|
353
|
-
expect(mapping.elements[1].namespace).to eq("http://www.sparxsystems.com/profiles/CityGML/1.0")
|
354
|
-
expect(mapping.elements[2].namespace).to eq("http://www.sparxsystems.com/profiles/CGML/1.0")
|
355
|
-
expect(mapping.elements.size).to eq(3)
|
306
|
+
it "checks the attribute with and without namespace" do
|
307
|
+
parsed = XmlMapping::AttributeNamespace.from_xml(input_xml)
|
308
|
+
expect(parsed.alpha).to eq("hello")
|
309
|
+
expect(parsed.beta).to eq("bye")
|
310
|
+
expect(parsed.to_xml).to be_equivalent_to(input_xml)
|
311
|
+
end
|
356
312
|
end
|
357
|
-
end
|
358
313
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
<cn:WithNamespace>explicit namespace text</cn:WithNamespace>
|
365
|
-
<WithoutNamespace>without namespace text</WithoutNamespace>
|
366
|
-
</pn:WithChildExplicitNamespaceNil>
|
314
|
+
context "explicit namespace" do
|
315
|
+
mml = <<~XML
|
316
|
+
<math xmlns="http://www.w3.org/1998/Math/MathML">
|
317
|
+
<mfenced open="("></mfenced>
|
318
|
+
</math>
|
367
319
|
XML
|
368
|
-
end
|
369
320
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
it "reads element with default namespace" do
|
375
|
-
expect(parsed.with_default_namespace).to eq("default namespace text")
|
376
|
-
end
|
377
|
-
|
378
|
-
it "reads element with explicit namespace" do
|
379
|
-
expect(parsed.with_namespace).to eq("explicit namespace text")
|
380
|
-
end
|
381
|
-
|
382
|
-
it "reads element without namespace" do
|
383
|
-
expect(parsed.without_namespace).to eq("without namespace text")
|
321
|
+
it "nil namespace" do
|
322
|
+
parsed = XmlMapping::MmlMath.from_xml(mml)
|
323
|
+
expect(parsed.to_xml).to be_equivalent_to(mml)
|
324
|
+
end
|
384
325
|
end
|
385
326
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
327
|
+
# Skipping for OX because it does not handle namespaces
|
328
|
+
context "overriding child namespace prefix", skip: adapter_class != Lutaml::Model::XmlAdapter::NokogiriAdapter do
|
329
|
+
let(:input_xml) do
|
330
|
+
<<~XML
|
331
|
+
<OverrideDefaultNamespacePrefix
|
332
|
+
xmlns:abc="http://www.omg.org/spec/XMI/20131001"
|
333
|
+
xmlns:GML="http://www.sparxsystems.com/profiles/GML/1.0"
|
334
|
+
xmlns:CityGML="http://www.sparxsystems.com/profiles/CityGML/1.0">
|
335
|
+
|
336
|
+
<abc:SameElementName App="hello">
|
337
|
+
<GML:ApplicationSchema>GML App</GML:ApplicationSchema>
|
338
|
+
<CityGML:ApplicationSchema>CityGML App</CityGML:ApplicationSchema>
|
339
|
+
<abc:ApplicationSchema>App</abc:ApplicationSchema>
|
340
|
+
</abc:SameElementName>
|
341
|
+
</OverrideDefaultNamespacePrefix>
|
342
|
+
XML
|
343
|
+
end
|
390
344
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
mapping.map_element("type", to: :type)
|
396
|
-
mapping.map_element("color", to: :color, delegate: :glaze)
|
397
|
-
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
345
|
+
it "expect to round-trips" do
|
346
|
+
parsed = XmlMapping::OverrideDefaultNamespacePrefix.from_xml(input_xml)
|
347
|
+
expect(parsed.to_xml).to be_equivalent_to(input_xml)
|
348
|
+
end
|
398
349
|
end
|
399
350
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
351
|
+
context "with same name elements" do
|
352
|
+
let(:input_xml) do
|
353
|
+
<<~XML
|
354
|
+
<SameElementName App="hello"
|
355
|
+
xmlns="http://www.omg.org/spec/XMI/20131001"
|
356
|
+
xmlns:GML="http://www.sparxsystems.com/profiles/GML/1.0"
|
357
|
+
xmlns:CityGML="http://www.sparxsystems.com/profiles/CityGML/1.0">
|
404
358
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
359
|
+
<GML:ApplicationSchema>GML App</GML:ApplicationSchema>
|
360
|
+
<CityGML:ApplicationSchema>CityGML App</CityGML:ApplicationSchema>
|
361
|
+
<ApplicationSchema>App</ApplicationSchema>
|
362
|
+
</SameElementName>
|
363
|
+
XML
|
364
|
+
end
|
411
365
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
366
|
+
let(:expected_order) do
|
367
|
+
{
|
368
|
+
Lutaml::Model::XmlAdapter::NokogiriAdapter => [
|
369
|
+
"text",
|
370
|
+
"ApplicationSchema",
|
371
|
+
"text",
|
372
|
+
"ApplicationSchema",
|
373
|
+
"text",
|
374
|
+
"ApplicationSchema",
|
375
|
+
"text",
|
376
|
+
],
|
377
|
+
Lutaml::Model::XmlAdapter::OxAdapter => [
|
378
|
+
"ApplicationSchema",
|
379
|
+
"ApplicationSchema",
|
380
|
+
"ApplicationSchema",
|
381
|
+
],
|
382
|
+
}
|
383
|
+
end
|
420
384
|
|
421
|
-
|
422
|
-
expect(mapping.namespace_uri).to eq("https://example.com/ceramic/1.2")
|
423
|
-
expect(mapping.namespace_prefix).to eq("cera")
|
424
|
-
end
|
385
|
+
let(:parsed) { XmlMapping::SameNameDifferentNamespace.from_xml(input_xml) }
|
425
386
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
expect(mapping.elements[1].delegate).to eq(:glaze)
|
430
|
-
end
|
431
|
-
end
|
387
|
+
it "citygml_application_schema should be correct" do
|
388
|
+
expect(parsed.citygml_application_schema).to eq("CityGML App")
|
389
|
+
end
|
432
390
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
mapping.map_element(
|
437
|
-
"type",
|
438
|
-
to: :type,
|
439
|
-
namespace: "https://example.com/ceramic/1.2",
|
440
|
-
prefix: "cera",
|
441
|
-
)
|
442
|
-
mapping.map_element("color", to: :color, delegate: :glaze)
|
443
|
-
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
444
|
-
end
|
445
|
-
|
446
|
-
it "sets the namespace for individual elements" do
|
447
|
-
expect(mapping.elements.size).to eq(3)
|
448
|
-
expect(mapping.elements[0].namespace).to eq("https://example.com/ceramic/1.2")
|
449
|
-
expect(mapping.elements[0].prefix).to eq("cera")
|
450
|
-
expect(mapping.elements[1].delegate).to eq(:glaze)
|
451
|
-
end
|
452
|
-
end
|
391
|
+
it "gml_application_schema should be correct" do
|
392
|
+
expect(parsed.gml_application_schema).to eq("GML App")
|
393
|
+
end
|
453
394
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
mapping.map_attribute(
|
458
|
-
"date",
|
459
|
-
to: :date,
|
460
|
-
namespace: "https://example.com/ceramic/1.2",
|
461
|
-
prefix: "cera",
|
462
|
-
)
|
463
|
-
mapping.map_element("type", to: :type)
|
464
|
-
mapping.map_element("color", to: :color, delegate: :glaze)
|
465
|
-
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
466
|
-
end
|
467
|
-
|
468
|
-
it "sets the namespace for individual attributes" do
|
469
|
-
expect(mapping.attributes.size).to eq(1)
|
470
|
-
expect(mapping.attributes[0].namespace).to eq("https://example.com/ceramic/1.2")
|
471
|
-
expect(mapping.attributes[0].prefix).to eq("cera")
|
472
|
-
end
|
473
|
-
end
|
395
|
+
it "application_schema should be correct" do
|
396
|
+
expect(parsed.application_schema).to eq("App")
|
397
|
+
end
|
474
398
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
<xmi:ChildNamespaceNil xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:new="http://www.omg.org/spec/XMI/20161001">
|
479
|
-
<xmi:ElementDefaultNamespace>Default namespace</xmi:ElementDefaultNamespace>
|
480
|
-
<ElementNilNamespace>No namespace</ElementNilNamespace>
|
481
|
-
<new:ElementNewNamespace>New namespace</new:ElementNewNamespace>
|
482
|
-
</xmi:ChildNamespaceNil>
|
483
|
-
XML
|
484
|
-
end
|
399
|
+
it "app should be correct" do
|
400
|
+
expect(parsed.app).to eq("hello")
|
401
|
+
end
|
485
402
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
element_default_namespace: "Default namespace",
|
490
|
-
element_nil_namespace: "No namespace",
|
491
|
-
element_new_namespace: "New namespace",
|
492
|
-
},
|
493
|
-
)
|
494
|
-
end
|
403
|
+
it "element_order should be correct" do
|
404
|
+
expect(parsed.element_order).to eq(expected_order[adapter_class])
|
405
|
+
end
|
495
406
|
|
496
|
-
|
497
|
-
|
407
|
+
it "to_xml should be correct" do
|
408
|
+
expect(parsed.to_xml).to be_equivalent_to(input_xml)
|
409
|
+
end
|
498
410
|
end
|
499
|
-
end
|
500
411
|
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
412
|
+
context "with elements have different prefixed namespaces" do
|
413
|
+
before do
|
414
|
+
mapping.root("XMI")
|
415
|
+
mapping.namespace("http://www.omg.org/spec/XMI/20131001")
|
416
|
+
mapping.map_element(
|
417
|
+
"ApplicationSchema",
|
418
|
+
to: :gml_application_schema,
|
419
|
+
namespace: "http://www.sparxsystems.com/profiles/GML/1.0",
|
420
|
+
prefix: "GML",
|
421
|
+
)
|
422
|
+
mapping.map_element(
|
423
|
+
"ApplicationSchema",
|
424
|
+
to: :citygml_application_schema,
|
425
|
+
namespace: "http://www.sparxsystems.com/profiles/CityGML/1.0",
|
426
|
+
prefix: "CityGML",
|
427
|
+
)
|
428
|
+
mapping.map_element(
|
429
|
+
"ApplicationSchema",
|
430
|
+
to: :citygml_application_schema,
|
431
|
+
namespace: "http://www.sparxsystems.com/profiles/CGML/1.0",
|
432
|
+
prefix: "CGML",
|
433
|
+
)
|
513
434
|
end
|
514
435
|
|
515
|
-
it "
|
516
|
-
expect(
|
436
|
+
it "maps elements correctly" do
|
437
|
+
expect(mapping.elements[0].namespace).to eq("http://www.sparxsystems.com/profiles/GML/1.0")
|
438
|
+
expect(mapping.elements[1].namespace).to eq("http://www.sparxsystems.com/profiles/CityGML/1.0")
|
439
|
+
expect(mapping.elements[2].namespace).to eq("http://www.sparxsystems.com/profiles/CGML/1.0")
|
440
|
+
expect(mapping.elements.size).to eq(3)
|
517
441
|
end
|
518
442
|
end
|
519
443
|
|
520
|
-
context "
|
444
|
+
context "with child having explicit namespaces" do
|
521
445
|
let(:xml) do
|
522
|
-
<<~XML
|
523
|
-
<
|
524
|
-
|
525
|
-
<
|
526
|
-
|
527
|
-
|
528
|
-
</schemaLocationOrdered>
|
529
|
-
</schemaLocationOrdered>
|
446
|
+
<<~XML.strip
|
447
|
+
<pn:WithChildExplicitNamespaceNil xmlns:pn="http://parent-namespace" xmlns:cn="http://child-namespace">
|
448
|
+
<pn:DefaultNamespace>default namespace text</pn:DefaultNamespace>
|
449
|
+
<cn:WithNamespace>explicit namespace text</cn:WithNamespace>
|
450
|
+
<WithoutNamespace>without namespace text</WithoutNamespace>
|
451
|
+
</pn:WithChildExplicitNamespaceNil>
|
530
452
|
XML
|
531
453
|
end
|
532
454
|
|
533
|
-
|
534
|
-
|
455
|
+
let(:parsed) do
|
456
|
+
XmlMapping::WithChildExplicitNamespace.from_xml(xml)
|
535
457
|
end
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
|
-
context "with multiple schemaLocations" do
|
540
|
-
let(:xml) do
|
541
|
-
<<~XML
|
542
|
-
<p xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
543
|
-
xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd">
|
544
|
-
<p xmlns:xsi="http://another-instance"
|
545
|
-
xsi:schemaLocation="http://www.opengis.net/gml/3.7 http://schemas.opengis.net/gml/3.7.1/gml.xsd http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd">
|
546
|
-
Some text inside paragraph
|
547
|
-
</p>
|
548
|
-
</p>
|
549
|
-
XML
|
550
|
-
end
|
551
|
-
|
552
|
-
it "parses and serializes multiple schemaLocation attributes" do
|
553
|
-
parsed = Paragraph.from_xml(xml)
|
554
|
-
expect(parsed.schema_location.size).to eq(2)
|
555
|
-
expect(parsed.schema_location[0].namespace).to eq("http://www.opengis.net/gml/3.2")
|
556
|
-
expect(parsed.schema_location[0].location).to eq("http://schemas.opengis.net/gml/3.2.1/gml.xsd")
|
557
|
-
expect(parsed.schema_location[1].namespace).to eq("http://www.w3.org/1999/xlink")
|
558
|
-
expect(parsed.schema_location[1].location).to eq("http://www.w3.org/1999/xlink.xsd")
|
559
458
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
expect(serialized).to include('xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd"')
|
564
|
-
end
|
459
|
+
it "reads element with default namespace" do
|
460
|
+
expect(parsed.with_default_namespace).to eq("default namespace text")
|
461
|
+
end
|
565
462
|
|
566
|
-
|
567
|
-
|
568
|
-
|
463
|
+
it "reads element with explicit namespace" do
|
464
|
+
expect(parsed.with_namespace).to eq("explicit namespace text")
|
465
|
+
end
|
569
466
|
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
expect(nested_p.schema_location[0].location).to eq("http://schemas.opengis.net/gml/3.7.1/gml.xsd")
|
574
|
-
expect(nested_p.schema_location[1].namespace).to eq("http://www.isotc211.org/2005/gmd")
|
575
|
-
expect(nested_p.schema_location[1].location).to eq("http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd")
|
467
|
+
it "reads element without namespace" do
|
468
|
+
expect(parsed.without_namespace).to eq("without namespace text")
|
469
|
+
end
|
576
470
|
|
577
|
-
|
578
|
-
|
579
|
-
|
471
|
+
it "round-trips xml with child explicit namespace" do
|
472
|
+
expect(parsed.to_xml).to be_equivalent_to(xml)
|
473
|
+
end
|
580
474
|
end
|
581
475
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
),
|
591
|
-
paragraph: Paragraph.new(
|
592
|
-
schema_location: Lutaml::Model::SchemaLocation.new(
|
593
|
-
schema_location: {
|
594
|
-
"http://www.opengis.net/gml/3.7" => "http://schemas.opengis.net/gml/3.7.1/gml.xsd",
|
595
|
-
"http://www.isotc211.org/2005/gmd" => "http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd",
|
596
|
-
},
|
597
|
-
prefix: "xsi",
|
598
|
-
namespace: "http://another-instance",
|
599
|
-
),
|
600
|
-
text: ["Some text inside paragraph"],
|
601
|
-
),
|
602
|
-
)
|
476
|
+
context "with default namespace" do
|
477
|
+
before do
|
478
|
+
mapping.root("ceramic")
|
479
|
+
mapping.namespace("https://example.com/ceramic/1.2")
|
480
|
+
mapping.map_element("type", to: :type)
|
481
|
+
mapping.map_element("color", to: :color, delegate: :glaze)
|
482
|
+
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
483
|
+
end
|
603
484
|
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
485
|
+
it "sets the default namespace for the root element" do
|
486
|
+
expect(mapping.namespace_uri).to eq("https://example.com/ceramic/1.2")
|
487
|
+
expect(mapping.namespace_prefix).to be_nil
|
488
|
+
end
|
608
489
|
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
<address>
|
615
|
-
<street>
|
616
|
-
<a>N</a>
|
617
|
-
<p>adf</p>
|
618
|
-
</street>
|
619
|
-
<city><a>M</a></city>
|
620
|
-
</address>
|
621
|
-
</person>
|
622
|
-
XML
|
490
|
+
it "maps elements correctly" do
|
491
|
+
expect(mapping.elements.size).to eq(3)
|
492
|
+
expect(mapping.elements[0].name).to eq("type")
|
493
|
+
expect(mapping.elements[1].delegate).to eq(:glaze)
|
494
|
+
end
|
623
495
|
end
|
624
496
|
|
625
|
-
|
626
|
-
|
627
|
-
"
|
628
|
-
|
629
|
-
"
|
497
|
+
context "with prefixed namespace" do
|
498
|
+
before do
|
499
|
+
mapping.root("ceramic")
|
500
|
+
mapping.namespace("https://example.com/ceramic/1.2", "cera")
|
501
|
+
mapping.map_element("type", to: :type)
|
502
|
+
mapping.map_element("color", to: :color, delegate: :glaze)
|
503
|
+
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
630
504
|
end
|
631
|
-
end
|
632
505
|
|
633
|
-
|
506
|
+
it "sets the namespace with prefix for the root element" do
|
507
|
+
expect(mapping.namespace_uri).to eq("https://example.com/ceramic/1.2")
|
508
|
+
expect(mapping.namespace_prefix).to eq("cera")
|
509
|
+
end
|
634
510
|
|
635
|
-
|
636
|
-
|
637
|
-
|
511
|
+
it "maps elements correctly" do
|
512
|
+
expect(mapping.elements.size).to eq(3)
|
513
|
+
expect(mapping.elements[0].name).to eq("type")
|
514
|
+
expect(mapping.elements[1].delegate).to eq(:glaze)
|
515
|
+
end
|
638
516
|
end
|
639
|
-
end
|
640
517
|
|
641
|
-
|
642
|
-
|
643
|
-
|
518
|
+
context "with element-level namespace" do
|
519
|
+
before do
|
520
|
+
mapping.root("ceramic")
|
521
|
+
mapping.map_element(
|
522
|
+
"type",
|
523
|
+
to: :type,
|
524
|
+
namespace: "https://example.com/ceramic/1.2",
|
525
|
+
prefix: "cera",
|
526
|
+
)
|
527
|
+
mapping.map_element("color", to: :color, delegate: :glaze)
|
528
|
+
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
529
|
+
end
|
644
530
|
|
645
|
-
|
646
|
-
|
531
|
+
it "sets the namespace for individual elements" do
|
532
|
+
expect(mapping.elements.size).to eq(3)
|
533
|
+
expect(mapping.elements[0].namespace).to eq("https://example.com/ceramic/1.2")
|
534
|
+
expect(mapping.elements[0].prefix).to eq("cera")
|
535
|
+
expect(mapping.elements[1].delegate).to eq(:glaze)
|
536
|
+
end
|
647
537
|
end
|
648
|
-
end
|
649
538
|
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
539
|
+
context "with attribute-level namespace" do
|
540
|
+
before do
|
541
|
+
mapping.root("ceramic")
|
542
|
+
mapping.map_attribute(
|
543
|
+
"date",
|
544
|
+
to: :date,
|
545
|
+
namespace: "https://example.com/ceramic/1.2",
|
546
|
+
prefix: "cera",
|
547
|
+
)
|
548
|
+
mapping.map_element("type", to: :type)
|
549
|
+
mapping.map_element("color", to: :color, delegate: :glaze)
|
550
|
+
mapping.map_element("finish", to: :finish, delegate: :glaze)
|
551
|
+
end
|
654
552
|
|
655
|
-
it "
|
656
|
-
expect(
|
553
|
+
it "sets the namespace for individual attributes" do
|
554
|
+
expect(mapping.attributes.size).to eq(1)
|
555
|
+
expect(mapping.attributes[0].namespace).to eq("https://example.com/ceramic/1.2")
|
556
|
+
expect(mapping.attributes[0].prefix).to eq("cera")
|
657
557
|
end
|
658
558
|
end
|
659
559
|
|
660
|
-
|
661
|
-
let(:
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
560
|
+
context "with nil element-level namespace" do
|
561
|
+
let(:expected_xml) do
|
562
|
+
<<~XML
|
563
|
+
<xmi:ChildNamespaceNil xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:new="http://www.omg.org/spec/XMI/20161001">
|
564
|
+
<xmi:ElementDefaultNamespace>Default namespace</xmi:ElementDefaultNamespace>
|
565
|
+
<ElementNilNamespace>No namespace</ElementNilNamespace>
|
566
|
+
<new:ElementNewNamespace>New namespace</new:ElementNewNamespace>
|
567
|
+
</xmi:ChildNamespaceNil>
|
568
|
+
XML
|
666
569
|
end
|
667
|
-
end
|
668
|
-
end
|
669
570
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
571
|
+
let(:model) do
|
572
|
+
XmlMapping::ChildNamespaceNil.new(
|
573
|
+
{
|
574
|
+
element_default_namespace: "Default namespace",
|
575
|
+
element_nil_namespace: "No namespace",
|
576
|
+
element_new_namespace: "New namespace",
|
577
|
+
},
|
578
|
+
)
|
579
|
+
end
|
674
580
|
|
675
|
-
|
676
|
-
|
581
|
+
it "expect to apply correct namespaces" do
|
582
|
+
expect(model.to_xml).to be_equivalent_to(expected_xml)
|
583
|
+
end
|
677
584
|
end
|
678
585
|
|
679
|
-
|
680
|
-
|
681
|
-
|
586
|
+
context "with schemaLocation" do
|
587
|
+
context "when mixed: false" do
|
588
|
+
let(:xml) do
|
589
|
+
<<~XML
|
590
|
+
<p xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
591
|
+
xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd">
|
592
|
+
<p xmlns:xsi="http://another-instance"
|
593
|
+
xsi:schemaLocation="http://www.opengis.net/gml/3.7">
|
594
|
+
Some text inside paragraph
|
595
|
+
</p>
|
596
|
+
</p>
|
597
|
+
XML
|
598
|
+
end
|
682
599
|
|
683
|
-
|
684
|
-
|
685
|
-
|
600
|
+
it "contain schemaLocation attributes" do
|
601
|
+
expect(Paragraph.from_xml(xml).to_xml).to be_equivalent_to(xml)
|
602
|
+
end
|
603
|
+
end
|
686
604
|
|
687
|
-
|
688
|
-
|
689
|
-
|
605
|
+
context "when mixed: true" do
|
606
|
+
let(:xml) do
|
607
|
+
<<~XML
|
608
|
+
<schemaLocationOrdered xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
609
|
+
xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd">
|
610
|
+
<schemaLocationOrdered xmlns:xsi="http://another-instance"
|
611
|
+
xsi:schemaLocation="http://www.opengis.net/gml/3.7">
|
612
|
+
Some text inside paragraph
|
613
|
+
</schemaLocationOrdered>
|
614
|
+
</schemaLocationOrdered>
|
615
|
+
XML
|
616
|
+
end
|
690
617
|
|
691
|
-
|
692
|
-
|
618
|
+
it "contain schemaLocation attributes" do
|
619
|
+
expect(XmlMapping::SchemaLocationOrdered.from_xml(xml).to_xml).to be_equivalent_to(xml)
|
620
|
+
end
|
621
|
+
end
|
693
622
|
end
|
694
623
|
|
695
|
-
|
696
|
-
|
697
|
-
|
624
|
+
context "with multiple schemaLocations" do
|
625
|
+
let(:xml) do
|
626
|
+
<<~XML
|
627
|
+
<p xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
628
|
+
xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd">
|
629
|
+
<p xmlns:xsi="http://another-instance"
|
630
|
+
xsi:schemaLocation="http://www.opengis.net/gml/3.7 http://schemas.opengis.net/gml/3.7.1/gml.xsd http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd">
|
631
|
+
Some text inside paragraph
|
632
|
+
</p>
|
633
|
+
</p>
|
634
|
+
XML
|
635
|
+
end
|
698
636
|
|
699
|
-
|
700
|
-
|
701
|
-
|
637
|
+
it "parses and serializes multiple schemaLocation attributes" do
|
638
|
+
parsed = Paragraph.from_xml(xml)
|
639
|
+
expect(parsed.schema_location.size).to eq(2)
|
640
|
+
expect(parsed.schema_location[0].namespace).to eq("http://www.opengis.net/gml/3.2")
|
641
|
+
expect(parsed.schema_location[0].location).to eq("http://schemas.opengis.net/gml/3.2.1/gml.xsd")
|
642
|
+
expect(parsed.schema_location[1].namespace).to eq("http://www.w3.org/1999/xlink")
|
643
|
+
expect(parsed.schema_location[1].location).to eq("http://www.w3.org/1999/xlink.xsd")
|
644
|
+
|
645
|
+
serialized = parsed.to_xml
|
646
|
+
expect(serialized).to be_equivalent_to(xml)
|
647
|
+
expect(serialized).to include('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"')
|
648
|
+
expect(serialized).to include('xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd"')
|
649
|
+
end
|
702
650
|
|
703
|
-
|
704
|
-
|
705
|
-
|
651
|
+
it "handles nested elements with different schemaLocations" do
|
652
|
+
parsed = Paragraph.from_xml(xml)
|
653
|
+
nested_p = parsed.paragraph
|
706
654
|
|
707
|
-
|
708
|
-
|
709
|
-
|
655
|
+
expect(nested_p).to be_a(Paragraph)
|
656
|
+
expect(nested_p.schema_location.size).to eq(2)
|
657
|
+
expect(nested_p.schema_location[0].namespace).to eq("http://www.opengis.net/gml/3.7")
|
658
|
+
expect(nested_p.schema_location[0].location).to eq("http://schemas.opengis.net/gml/3.7.1/gml.xsd")
|
659
|
+
expect(nested_p.schema_location[1].namespace).to eq("http://www.isotc211.org/2005/gmd")
|
660
|
+
expect(nested_p.schema_location[1].location).to eq("http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd")
|
710
661
|
|
711
|
-
|
712
|
-
expect(
|
662
|
+
serialized = parsed.to_xml
|
663
|
+
expect(serialized).to include('xmlns:xsi="http://another-instance"')
|
664
|
+
expect(serialized).to include('xsi:schemaLocation="http://www.opengis.net/gml/3.7 http://schemas.opengis.net/gml/3.7.1/gml.xsd http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd"')
|
713
665
|
end
|
714
666
|
|
715
|
-
it "
|
716
|
-
|
717
|
-
|
667
|
+
it "creates XML with multiple schemaLocations" do
|
668
|
+
paragraph = Paragraph.new(
|
669
|
+
schema_location: Lutaml::Model::SchemaLocation.new(
|
670
|
+
schema_location: {
|
671
|
+
"http://www.opengis.net/gml/3.2" => "http://schemas.opengis.net/gml/3.2.1/gml.xsd",
|
672
|
+
"http://www.w3.org/1999/xlink" => "http://www.w3.org/1999/xlink.xsd",
|
673
|
+
},
|
674
|
+
prefix: "xsi",
|
675
|
+
),
|
676
|
+
paragraph: Paragraph.new(
|
677
|
+
schema_location: Lutaml::Model::SchemaLocation.new(
|
678
|
+
schema_location: {
|
679
|
+
"http://www.opengis.net/gml/3.7" => "http://schemas.opengis.net/gml/3.7.1/gml.xsd",
|
680
|
+
"http://www.isotc211.org/2005/gmd" => "http://schemas.opengis.net/iso/19139/20070417/gmd/gmd.xsd",
|
681
|
+
},
|
682
|
+
prefix: "xsi",
|
683
|
+
namespace: "http://another-instance",
|
684
|
+
),
|
685
|
+
text: ["Some text inside paragraph"],
|
686
|
+
),
|
687
|
+
)
|
718
688
|
|
719
|
-
|
720
|
-
expect(
|
689
|
+
serialized = paragraph.to_xml
|
690
|
+
expect(serialized).to be_equivalent_to(xml)
|
721
691
|
end
|
692
|
+
end
|
722
693
|
|
723
|
-
|
724
|
-
|
725
|
-
|
694
|
+
context "with raw mapping" do
|
695
|
+
let(:input_xml) do
|
696
|
+
<<~XML
|
697
|
+
<person>
|
698
|
+
<name>John Doe</name>
|
699
|
+
<address>
|
700
|
+
<street>
|
701
|
+
<a>N</a>
|
702
|
+
<p>adf</p>
|
703
|
+
</street>
|
704
|
+
<city><a>M</a></city>
|
705
|
+
</address>
|
706
|
+
</person>
|
707
|
+
XML
|
726
708
|
end
|
727
709
|
|
728
|
-
|
729
|
-
|
730
|
-
|
710
|
+
let(:expected_street) do
|
711
|
+
if Lutaml::Model::Config.xml_adapter == Lutaml::Model::XmlAdapter::OxAdapter
|
712
|
+
"<a>N</a>\n<p>adf</p>\n"
|
713
|
+
else
|
714
|
+
"\n <a>N</a>\n <p>adf</p>\n "
|
715
|
+
end
|
731
716
|
end
|
732
717
|
|
733
|
-
|
734
|
-
orig_name = orig_mapping.name
|
735
|
-
dup_name = dup_mapping.name
|
718
|
+
let(:model) { XmlMapping::Person.from_xml(input_xml) }
|
736
719
|
|
737
|
-
|
738
|
-
expect(
|
720
|
+
it "expect to contain raw xml" do
|
721
|
+
expect(model.address.street).to eq(expected_street)
|
722
|
+
expect(model.address.city.strip).to eq("<a>M</a>")
|
739
723
|
end
|
724
|
+
end
|
740
725
|
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
expect(orig_namespace).to eq(dup_namespace)
|
746
|
-
expect(orig_namespace.object_id).not_to eq(dup_namespace.object_id)
|
747
|
-
end
|
726
|
+
context "with content mapping" do
|
727
|
+
let(:xml_data) { "<i>my text <b>bold</b> is in italics</i>" }
|
728
|
+
let(:italic) { Italic.from_xml(xml_data) }
|
748
729
|
|
749
|
-
it "
|
750
|
-
|
751
|
-
expect(orig_mapping.namespace_set?).to eq(dup_mapping.namespace_set?)
|
730
|
+
it "parses the textual content of an XML element" do
|
731
|
+
expect(italic.text).to eq(["my text ", " is in italics"])
|
752
732
|
end
|
733
|
+
end
|
753
734
|
|
754
|
-
|
755
|
-
|
756
|
-
|
735
|
+
context "with p object" do
|
736
|
+
describe "convert from xml containing p tag" do
|
737
|
+
let(:xml_data) { "<p>my text for paragraph</p>" }
|
738
|
+
let(:paragraph) { Paragraph.from_xml(xml_data) }
|
757
739
|
|
758
|
-
|
759
|
-
|
740
|
+
it "parses the textual content of an XML element" do
|
741
|
+
expect(paragraph.text).to eq("my text for paragraph")
|
742
|
+
end
|
760
743
|
end
|
761
744
|
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
end
|
745
|
+
describe "generate xml with p tag" do
|
746
|
+
let(:paragraph) { Paragraph.new(text: "my text for paragraph") }
|
747
|
+
let(:expected_xml) { "<p>my text for paragraph</p>" }
|
766
748
|
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
end
|
771
|
-
|
772
|
-
it "duplicates to" do
|
773
|
-
# `to` is symbol which are constant so object_id will be same
|
774
|
-
expect(orig_mapping.to).to eq(dup_mapping.to)
|
749
|
+
it "converts to xml correctly" do
|
750
|
+
expect(paragraph.to_xml.chomp).to eq(expected_xml)
|
751
|
+
end
|
775
752
|
end
|
776
753
|
end
|
777
|
-
end
|
778
754
|
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
expect do
|
783
|
-
XmlMapping::WithMapAll.xml do
|
784
|
-
map_element "ele", to: :ele
|
785
|
-
end
|
786
|
-
end.to raise_error(
|
787
|
-
StandardError,
|
788
|
-
"map_element is not allowed, only map_attribute is allowed with map_all",
|
789
|
-
)
|
755
|
+
describe "#deep_dup" do
|
756
|
+
let(:orig_mappings) do
|
757
|
+
XmlMapping::ToBeDuplicated.mappings_for(:xml)
|
790
758
|
end
|
791
759
|
|
792
|
-
|
793
|
-
|
794
|
-
XmlMapping::WithMapAll.xml do
|
795
|
-
map_content to: :text
|
796
|
-
end
|
797
|
-
end.to raise_error(
|
798
|
-
StandardError,
|
799
|
-
"map_content is not allowed, only map_attribute is allowed with map_all",
|
800
|
-
)
|
760
|
+
let(:dup_mappings) do
|
761
|
+
orig_mappings.deep_dup
|
801
762
|
end
|
802
763
|
|
803
|
-
it "
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
764
|
+
it "duplicates root_element" do
|
765
|
+
orig_root = orig_mappings.root_element
|
766
|
+
dup_root = dup_mappings.root_element
|
767
|
+
|
768
|
+
expect(orig_root).to eq(dup_root)
|
769
|
+
expect(orig_root.object_id).not_to eq(dup_root.object_id)
|
809
770
|
end
|
810
|
-
end
|
811
771
|
|
812
|
-
|
813
|
-
|
772
|
+
it "duplicates namespace_uri" do
|
773
|
+
orig_namespace_uri = orig_mappings.namespace_uri
|
774
|
+
dup_namespace_uri = dup_mappings.namespace_uri
|
814
775
|
|
815
|
-
|
816
|
-
expect
|
817
|
-
XmlMapping::WithoutMapAll.xml do
|
818
|
-
map_all to: :all_content
|
819
|
-
end
|
820
|
-
end.to raise_error(StandardError, error_message)
|
776
|
+
expect(orig_namespace_uri).to eq(dup_namespace_uri)
|
777
|
+
expect(orig_namespace_uri.object_id).not_to eq(dup_namespace_uri.object_id)
|
821
778
|
end
|
822
|
-
end
|
823
779
|
|
824
|
-
|
825
|
-
|
826
|
-
|
780
|
+
it "duplicates namespace_prefix" do
|
781
|
+
orig_namespace_prefix = orig_mappings.namespace_prefix
|
782
|
+
dup_namespace_prefix = dup_mappings.namespace_prefix
|
827
783
|
|
828
|
-
|
784
|
+
expect(orig_namespace_prefix).to eq(dup_namespace_prefix)
|
785
|
+
expect(orig_namespace_prefix.object_id).not_to eq(dup_namespace_prefix.object_id)
|
786
|
+
end
|
829
787
|
|
830
|
-
|
788
|
+
context "when duplicating mapping" do
|
789
|
+
let(:orig_mapping) { orig_mappings.mappings[0] }
|
790
|
+
let(:dup_mapping) { dup_mappings.mappings[0] }
|
791
|
+
|
792
|
+
it "duplicates custom_methods" do
|
793
|
+
orig_custom_methods = orig_mapping.custom_methods
|
794
|
+
dup_custom_methods = dup_mapping.custom_methods
|
795
|
+
|
796
|
+
expect(orig_custom_methods).to eq(dup_custom_methods)
|
797
|
+
expect(orig_custom_methods.object_id).not_to eq(dup_custom_methods.object_id)
|
798
|
+
end
|
799
|
+
|
800
|
+
it "duplicates default_namespace" do
|
801
|
+
orig_default_namespace = orig_mapping.default_namespace
|
802
|
+
dup_default_namespace = dup_mapping.default_namespace
|
803
|
+
|
804
|
+
expect(orig_default_namespace).to eq(dup_default_namespace)
|
805
|
+
expect(orig_default_namespace.object_id).not_to eq(dup_default_namespace.object_id)
|
806
|
+
end
|
807
|
+
|
808
|
+
it "duplicates delegate" do
|
809
|
+
# `delegate` is symbol which are constant so object_id will be same
|
810
|
+
expect(orig_mapping.delegate).to eq(dup_mapping.delegate)
|
811
|
+
end
|
812
|
+
|
813
|
+
it "duplicates mixed_content" do
|
814
|
+
# boolean value is constant so object_id will be same
|
815
|
+
expect(orig_mapping.mixed_content).to eq(dup_mapping.mixed_content)
|
816
|
+
end
|
817
|
+
|
818
|
+
it "duplicates name" do
|
819
|
+
orig_name = orig_mapping.name
|
820
|
+
dup_name = dup_mapping.name
|
821
|
+
|
822
|
+
expect(orig_name).to eq(dup_name)
|
823
|
+
expect(orig_name.object_id).not_to eq(dup_name.object_id)
|
824
|
+
end
|
825
|
+
|
826
|
+
it "duplicates namespace" do
|
827
|
+
orig_namespace = orig_mapping.namespace
|
828
|
+
dup_namespace = dup_mapping.namespace
|
829
|
+
|
830
|
+
expect(orig_namespace).to eq(dup_namespace)
|
831
|
+
expect(orig_namespace.object_id).not_to eq(dup_namespace.object_id)
|
832
|
+
end
|
833
|
+
|
834
|
+
it "duplicates namespace_set" do
|
835
|
+
# boolean value is constant so object_id will be same
|
836
|
+
expect(orig_mapping.namespace_set?).to eq(dup_mapping.namespace_set?)
|
837
|
+
end
|
838
|
+
|
839
|
+
it "duplicates prefix" do
|
840
|
+
orig_prefix = orig_mapping.prefix
|
841
|
+
dup_prefix = dup_mapping.prefix
|
842
|
+
|
843
|
+
expect(orig_prefix).to eq(dup_prefix)
|
844
|
+
expect(orig_prefix.object_id).not_to eq(dup_prefix.object_id)
|
845
|
+
end
|
846
|
+
|
847
|
+
it "duplicates prefix_set" do
|
848
|
+
# boolean value is constant so object_id will be same
|
849
|
+
expect(orig_mapping.prefix_set?).to eq(dup_mapping.prefix_set?)
|
850
|
+
end
|
851
|
+
|
852
|
+
it "duplicates render_nil" do
|
853
|
+
# boolean value is constant so object_id will be same
|
854
|
+
expect(orig_mapping.render_nil?).to eq(dup_mapping.render_nil?)
|
855
|
+
end
|
856
|
+
|
857
|
+
it "duplicates to" do
|
858
|
+
# `to` is symbol which are constant so object_id will be same
|
859
|
+
expect(orig_mapping.to).to eq(dup_mapping.to)
|
860
|
+
end
|
861
|
+
end
|
831
862
|
end
|
832
863
|
|
833
|
-
|
834
|
-
|
835
|
-
|
864
|
+
describe "#map_all" do
|
865
|
+
context "when map_all is defined before any other mapping" do
|
866
|
+
it "raise error when for map_element with map_all" do
|
867
|
+
expect do
|
868
|
+
XmlMapping::WithMapAll.xml do
|
869
|
+
map_element "ele", to: :ele
|
870
|
+
end
|
871
|
+
end.to raise_error(
|
872
|
+
StandardError,
|
873
|
+
"map_element is not allowed, only map_attribute is allowed with map_all",
|
874
|
+
)
|
875
|
+
end
|
876
|
+
|
877
|
+
it "raise error when for map_content with map_all" do
|
878
|
+
expect do
|
879
|
+
XmlMapping::WithMapAll.xml do
|
880
|
+
map_content to: :text
|
881
|
+
end
|
882
|
+
end.to raise_error(
|
883
|
+
StandardError,
|
884
|
+
"map_content is not allowed, only map_attribute is allowed with map_all",
|
885
|
+
)
|
886
|
+
end
|
887
|
+
|
888
|
+
it "does not raise error for map_attribute with map_all" do
|
889
|
+
expect do
|
890
|
+
XmlMapping::WithMapAll.xml do
|
891
|
+
map_attribute "attr", to: :attr
|
892
|
+
end
|
893
|
+
end.not_to raise_error
|
894
|
+
end
|
895
|
+
end
|
836
896
|
|
837
|
-
|
838
|
-
|
897
|
+
context "when map_all is defined after other mappings" do
|
898
|
+
let(:error_message) { "map_all is not allowed with other mappings" }
|
839
899
|
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
900
|
+
it "raise error when for map_element with map_all" do
|
901
|
+
expect do
|
902
|
+
XmlMapping::WithoutMapAll.xml do
|
903
|
+
map_all to: :all_content
|
904
|
+
end
|
905
|
+
end.to raise_error(StandardError, error_message)
|
906
|
+
end
|
846
907
|
end
|
847
908
|
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
DESCRIPTION
|
853
|
-
end
|
909
|
+
context "with custom methods" do
|
910
|
+
let(:inner_xml) do
|
911
|
+
"Str<sub>2</sub>text<sup>1</sup>123"
|
912
|
+
end
|
854
913
|
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
<name>John Doe</name>
|
859
|
-
<description>
|
860
|
-
#{description}
|
861
|
-
</description>
|
862
|
-
</WithNestedMapAll>
|
863
|
-
XML
|
864
|
-
end
|
914
|
+
let(:xml) do
|
915
|
+
"<MapAllWithCustomMethod>#{inner_xml}</MapAllWithCustomMethod>"
|
916
|
+
end
|
865
917
|
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
<name>John Doe</name>
|
870
|
-
<description>
|
871
|
-
#{expected_description}
|
872
|
-
</description>
|
873
|
-
</WithNestedMapAll>
|
874
|
-
XML
|
875
|
-
end
|
918
|
+
let(:parsed) do
|
919
|
+
XmlMapping::MapAllWithCustomMethod.from_xml(xml)
|
920
|
+
end
|
876
921
|
|
877
|
-
|
878
|
-
|
879
|
-
|
922
|
+
it "uses custom method when parsing XML" do
|
923
|
+
expect(parsed.all_content).to eq("<div>#{inner_xml}</div>")
|
924
|
+
end
|
880
925
|
|
881
|
-
|
882
|
-
|
926
|
+
it "generates correct XML" do
|
927
|
+
expect(parsed.to_xml.chomp).to be_equivalent_to(xml)
|
928
|
+
end
|
883
929
|
end
|
884
930
|
|
885
|
-
it "maps
|
886
|
-
|
887
|
-
|
931
|
+
it "maps all the content including tags" do
|
932
|
+
inner_xml = "Str<sub>2</sub>text<sup>1</sup>123"
|
933
|
+
xml = "<WithMapAll>#{inner_xml}</WithMapAll>"
|
888
934
|
|
889
|
-
|
890
|
-
expect(parsed.age).to eq(23)
|
891
|
-
end
|
935
|
+
parsed = XmlMapping::WithMapAll.from_xml(xml)
|
892
936
|
|
893
|
-
|
894
|
-
expect(parsed.to_xml).to be_equivalent_to(expected_xml)
|
937
|
+
expect(parsed.all_content).to eq(inner_xml)
|
895
938
|
end
|
896
|
-
end
|
897
939
|
|
898
|
-
context "when special char used in content with map all" do
|
899
940
|
it "round-trips xml" do
|
900
|
-
xml =
|
901
|
-
<SpecialCharContentWithMapAll>
|
902
|
-
B <p>R&C</p>
|
903
|
-
C <p>J—C</p>
|
904
|
-
O <p>A & B </p>
|
905
|
-
F <p>Z © </p>
|
906
|
-
</SpecialCharContentWithMapAll>
|
907
|
-
XML
|
941
|
+
xml = "<WithMapAll>Str<sub>2</sub>text<sup>1</sup>123</WithMapAll>"
|
908
942
|
|
909
|
-
|
910
|
-
|
911
|
-
B <p>R&amp;C</p>
|
912
|
-
C <p>J&#x2014;C</p>
|
913
|
-
O <p>A &amp; B </p>
|
914
|
-
F <p>Z &#xA9; </p>
|
915
|
-
</SpecialCharContentWithMapAll>
|
916
|
-
XML
|
943
|
+
expect(XmlMapping::WithMapAll.from_xml(xml).to_xml.chomp).to eq(xml)
|
944
|
+
end
|
917
945
|
|
918
|
-
|
946
|
+
context "when nested content has map_all" do
|
947
|
+
let(:description) do
|
948
|
+
<<~DESCRIPTION
|
949
|
+
I'm a <b>web developer</b> with <strong>years</strong> of <i>experience</i> in many programing languages.
|
950
|
+
DESCRIPTION
|
951
|
+
end
|
952
|
+
|
953
|
+
let(:expected_description) do
|
954
|
+
<<~DESCRIPTION
|
955
|
+
I'm a <b>web developer</b> with <strong>years</strong> of <i>experience</i> in many programing languages.
|
956
|
+
DESCRIPTION
|
957
|
+
end
|
958
|
+
|
959
|
+
let(:xml) do
|
960
|
+
<<~XML
|
961
|
+
<WithNestedMapAll age="23">
|
962
|
+
<name>John Doe</name>
|
963
|
+
<description>
|
964
|
+
#{description}
|
965
|
+
</description>
|
966
|
+
</WithNestedMapAll>
|
967
|
+
XML
|
968
|
+
end
|
969
|
+
|
970
|
+
let(:expected_xml) do
|
971
|
+
<<~XML
|
972
|
+
<WithNestedMapAll age="23">
|
973
|
+
<name>John Doe</name>
|
974
|
+
<description>
|
975
|
+
#{expected_description}
|
976
|
+
</description>
|
977
|
+
</WithNestedMapAll>
|
978
|
+
XML
|
979
|
+
end
|
980
|
+
|
981
|
+
let(:parsed) do
|
982
|
+
XmlMapping::WithNestedMapAll.from_xml(xml)
|
983
|
+
end
|
984
|
+
|
985
|
+
it "maps description correctly" do
|
986
|
+
expect(parsed.description.all_content.strip).to eq(description.strip)
|
987
|
+
end
|
988
|
+
|
989
|
+
it "maps name correctly" do
|
990
|
+
expect(parsed.name).to eq("John Doe")
|
991
|
+
end
|
992
|
+
|
993
|
+
it "maps age correctly" do
|
994
|
+
expect(parsed.age).to eq(23)
|
995
|
+
end
|
996
|
+
|
997
|
+
it "round-trips xml" do
|
998
|
+
expect(parsed.to_xml).to be_equivalent_to(expected_xml)
|
999
|
+
end
|
919
1000
|
end
|
920
|
-
end
|
921
1001
|
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
1002
|
+
context "when special char used in content with map all" do
|
1003
|
+
let(:xml) do
|
1004
|
+
<<~XML
|
1005
|
+
<SpecialCharContentWithMapAll>
|
1006
|
+
B <p>R&C</p>
|
1007
|
+
C <p>J—C</p>
|
1008
|
+
O <p>A & B </p>
|
1009
|
+
F <p>Z © </p>
|
1010
|
+
</SpecialCharContentWithMapAll>
|
1011
|
+
XML
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
let(:expected_nokogiri_xml) do
|
1015
|
+
<<~XML.strip
|
1016
|
+
<SpecialCharContentWithMapAll>
|
1017
|
+
B <p>R&C</p>
|
1018
|
+
C <p>J—C</p>
|
1019
|
+
O <p>A & B </p>
|
1020
|
+
F <p>Z © </p>
|
1021
|
+
</SpecialCharContentWithMapAll>
|
1022
|
+
XML
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
let(:expected_ox_xml) do
|
1026
|
+
"<SpecialCharContentWithMapAll> " \
|
1027
|
+
"B <p>R&C</p> " \
|
1028
|
+
"C <p>J—C</p> " \
|
1029
|
+
"O <p>A & B </p> " \
|
1030
|
+
"F <p>Z © </p>" \
|
1031
|
+
"</SpecialCharContentWithMapAll>\n"
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
it "round-trips xml" do
|
1035
|
+
expected_xml = if adapter_class == Lutaml::Model::XmlAdapter::NokogiriAdapter
|
1036
|
+
expected_nokogiri_xml
|
1037
|
+
else
|
1038
|
+
expected_ox_xml
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
expect(XmlMapping::SpecialCharContentWithMapAll.from_xml(xml).to_xml).to eq(expected_xml)
|
1042
|
+
end
|
929
1043
|
end
|
930
1044
|
|
931
|
-
|
932
|
-
|
1045
|
+
context "when mixed content is true and child is content_mapping" do
|
1046
|
+
let(:xml) do
|
1047
|
+
<<~XML
|
1048
|
+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
1049
|
+
<xsd:documentation>asdf</xsd:documentation>
|
1050
|
+
</xsd:schema>
|
1051
|
+
XML
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
it "round-trips xml" do
|
1055
|
+
expect(XmlMapping::Schema.from_xml(xml).to_xml).to be_equivalent_to(xml)
|
1056
|
+
end
|
933
1057
|
end
|
934
1058
|
end
|
935
1059
|
end
|
1060
|
+
|
1061
|
+
describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
|
1062
|
+
it_behaves_like "having XML Mappings", described_class
|
1063
|
+
end
|
1064
|
+
|
1065
|
+
describe Lutaml::Model::XmlAdapter::OxAdapter do
|
1066
|
+
it_behaves_like "having XML Mappings", described_class
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
describe Lutaml::Model::XmlAdapter::OgaAdapter, skip: "Not implemented yet" do
|
1070
|
+
it_behaves_like "having XML Mappings", described_class
|
1071
|
+
end
|
936
1072
|
end
|