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.
@@ -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
- let(:mapping) { described_class.new }
263
-
264
- context "attribute namespace" do
265
- input_xml = '<ns1:example ex1:alpha="hello" beta="bye" xmlns:ns1="http://www.check.com" xmlns:ex1="http://www.example.com"></ns1:example>'
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
- it "checks the attribute with and without namespace" do
268
- parsed = XmlMapping::AttributeNamespace.from_xml(input_xml)
269
- expect(parsed.alpha).to eq("hello")
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
- it "nil namespace" do
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
- context "overriding child namespace prefix" do
285
- let(:input_xml) do
286
- <<~XML
287
- <OverrideDefaultNamespacePrefix xmlns:abc="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">
288
- <abc:SameElementName App="hello">
289
- <GML:ApplicationSchema>GML App</GML:ApplicationSchema>
290
- <CityGML:ApplicationSchema>CityGML App</CityGML:ApplicationSchema>
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
- it "parses XML and serializes elements with the same name" do
315
- parsed = XmlMapping::SameNameDifferentNamespace.from_xml(input_xml)
316
-
317
- expect(parsed.citygml_application_schema).to eq("CityGML App")
318
- expect(parsed.gml_application_schema).to eq("GML App")
319
- expect(parsed.application_schema).to eq("App")
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
- context "with child having explicit namespaces" do
360
- let(:xml) do
361
- <<~XML.strip
362
- <pn:WithChildExplicitNamespaceNil xmlns:pn="http://parent-namespace" xmlns:cn="http://child-namespace">
363
- <pn:DefaultNamespace>default namespace text</pn:DefaultNamespace>
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
- let(:parsed) do
371
- XmlMapping::WithChildExplicitNamespace.from_xml(xml)
372
- end
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
- it "round-trips xml with child explicit namespace" do
387
- expect(parsed.to_xml).to be_equivalent_to(xml)
388
- end
389
- end
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
- context "with default namespace" do
392
- before do
393
- mapping.root("ceramic")
394
- mapping.namespace("https://example.com/ceramic/1.2")
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
- it "sets the default namespace for the root element" do
401
- expect(mapping.namespace_uri).to eq("https://example.com/ceramic/1.2")
402
- expect(mapping.namespace_prefix).to be_nil
403
- end
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
- it "maps elements correctly" do
406
- expect(mapping.elements.size).to eq(3)
407
- expect(mapping.elements[0].name).to eq("type")
408
- expect(mapping.elements[1].delegate).to eq(:glaze)
409
- end
410
- end
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
- context "with prefixed namespace" do
413
- before do
414
- mapping.root("ceramic")
415
- mapping.namespace("https://example.com/ceramic/1.2", "cera")
416
- mapping.map_element("type", to: :type)
417
- mapping.map_element("color", to: :color, delegate: :glaze)
418
- mapping.map_element("finish", to: :finish, delegate: :glaze)
419
- end
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
- it "sets the namespace with prefix for the root element" do
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
- it "maps elements correctly" do
427
- expect(mapping.elements.size).to eq(3)
428
- expect(mapping.elements[0].name).to eq("type")
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
- context "with element-level namespace" do
434
- before do
435
- mapping.root("ceramic")
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
- context "with attribute-level namespace" do
455
- before do
456
- mapping.root("ceramic")
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
- context "with nil element-level namespace" do
476
- let(:expected_xml) do
477
- <<~XML
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
- let(:model) do
487
- XmlMapping::ChildNamespaceNil.new(
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
- it "expect to apply correct namespaces" do
497
- expect(model.to_xml).to be_equivalent_to(expected_xml)
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
- context "with schemaLocation" do
502
- context "when mixed: false" do
503
- let(:xml) do
504
- <<~XML
505
- <p xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
506
- xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd">
507
- <p xmlns:xsi="http://another-instance"
508
- xsi:schemaLocation="http://www.opengis.net/gml/3.7">
509
- Some text inside paragraph
510
- </p>
511
- </p>
512
- XML
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 "contain schemaLocation attributes" do
516
- expect(Paragraph.from_xml(xml).to_xml).to be_equivalent_to(xml)
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 "when mixed: true" do
444
+ context "with child having explicit namespaces" do
521
445
  let(:xml) do
522
- <<~XML
523
- <schemaLocationOrdered xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
524
- xsi:schemaLocation="http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd">
525
- <schemaLocationOrdered xmlns:xsi="http://another-instance"
526
- xsi:schemaLocation="http://www.opengis.net/gml/3.7">
527
- Some text inside paragraph
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
- it "contain schemaLocation attributes" do
534
- expect(XmlMapping::SchemaLocationOrdered.from_xml(xml).to_xml).to be_equivalent_to(xml)
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
- serialized = parsed.to_xml
561
- expect(serialized).to be_equivalent_to(xml)
562
- expect(serialized).to include('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"')
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
- it "handles nested elements with different schemaLocations" do
567
- parsed = Paragraph.from_xml(xml)
568
- nested_p = parsed.paragraph
463
+ it "reads element with explicit namespace" do
464
+ expect(parsed.with_namespace).to eq("explicit namespace text")
465
+ end
569
466
 
570
- expect(nested_p).to be_a(Paragraph)
571
- expect(nested_p.schema_location.size).to eq(2)
572
- expect(nested_p.schema_location[0].namespace).to eq("http://www.opengis.net/gml/3.7")
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
- serialized = parsed.to_xml
578
- expect(serialized).to include('xmlns:xsi="http://another-instance"')
579
- 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"')
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
- it "creates XML with multiple schemaLocations" do
583
- paragraph = Paragraph.new(
584
- schema_location: Lutaml::Model::SchemaLocation.new(
585
- schema_location: {
586
- "http://www.opengis.net/gml/3.2" => "http://schemas.opengis.net/gml/3.2.1/gml.xsd",
587
- "http://www.w3.org/1999/xlink" => "http://www.w3.org/1999/xlink.xsd",
588
- },
589
- prefix: "xsi",
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
- serialized = paragraph.to_xml
605
- expect(serialized).to be_equivalent_to(xml)
606
- end
607
- end
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
- context "with raw mapping" do
610
- let(:input_xml) do
611
- <<~XML
612
- <person>
613
- <name>John Doe</name>
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
- let(:expected_street) do
626
- if Lutaml::Model::Config.xml_adapter == Lutaml::Model::XmlAdapter::OxAdapter
627
- "<a>N</a>\n<p>adf</p>\n"
628
- else
629
- "\n <a>N</a>\n <p>adf</p>\n "
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
- let(:model) { XmlMapping::Person.from_xml(input_xml) }
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
- it "expect to contain raw xml" do
636
- expect(model.address.street).to eq(expected_street)
637
- expect(model.address.city.strip).to eq("<a>M</a>")
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
- context "with content mapping" do
642
- let(:xml_data) { "<i>my text <b>bold</b> is in italics</i>" }
643
- let(:italic) { Italic.from_xml(xml_data) }
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
- it "parses the textual content of an XML element" do
646
- expect(italic.text).to eq(["my text ", " is in italics"])
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
- context "with p object" do
651
- describe "convert from xml containing p tag" do
652
- let(:xml_data) { "<p>my text for paragraph</p>" }
653
- let(:paragraph) { Paragraph.from_xml(xml_data) }
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 "parses the textual content of an XML element" do
656
- expect(paragraph.text).to eq("my text for paragraph")
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
- describe "generate xml with p tag" do
661
- let(:paragraph) { Paragraph.new(text: "my text for paragraph") }
662
- let(:expected_xml) { "<p>my text for paragraph</p>" }
663
-
664
- it "converts to xml correctly" do
665
- expect(paragraph.to_xml).to eq(expected_xml)
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
- describe "#deep_dup" do
671
- let(:orig_mappings) do
672
- XmlMapping::ToBeDuplicated.mappings_for(:xml)
673
- end
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
- let(:dup_mappings) do
676
- orig_mappings.deep_dup
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
- it "duplicates root_element" do
680
- orig_root = orig_mappings.root_element
681
- dup_root = dup_mappings.root_element
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
- expect(orig_root).to eq(dup_root)
684
- expect(orig_root.object_id).not_to eq(dup_root.object_id)
685
- end
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
- it "duplicates namespace_uri" do
688
- orig_namespace_uri = orig_mappings.namespace_uri
689
- dup_namespace_uri = dup_mappings.namespace_uri
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
- expect(orig_namespace_uri).to eq(dup_namespace_uri)
692
- expect(orig_namespace_uri.object_id).not_to eq(dup_namespace_uri.object_id)
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
- it "duplicates namespace_prefix" do
696
- orig_namespace_prefix = orig_mappings.namespace_prefix
697
- dup_namespace_prefix = dup_mappings.namespace_prefix
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
- expect(orig_namespace_prefix).to eq(dup_namespace_prefix)
700
- expect(orig_namespace_prefix.object_id).not_to eq(dup_namespace_prefix.object_id)
701
- end
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
- context "when duplicating mapping" do
704
- let(:orig_mapping) { orig_mappings.mappings[0] }
705
- let(:dup_mapping) { dup_mappings.mappings[0] }
651
+ it "handles nested elements with different schemaLocations" do
652
+ parsed = Paragraph.from_xml(xml)
653
+ nested_p = parsed.paragraph
706
654
 
707
- it "duplicates custom_methods" do
708
- orig_custom_methods = orig_mapping.custom_methods
709
- dup_custom_methods = dup_mapping.custom_methods
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
- expect(orig_custom_methods).to eq(dup_custom_methods)
712
- expect(orig_custom_methods.object_id).not_to eq(dup_custom_methods.object_id)
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 "duplicates default_namespace" do
716
- orig_default_namespace = orig_mapping.default_namespace
717
- dup_default_namespace = dup_mapping.default_namespace
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
- expect(orig_default_namespace).to eq(dup_default_namespace)
720
- expect(orig_default_namespace.object_id).not_to eq(dup_default_namespace.object_id)
689
+ serialized = paragraph.to_xml
690
+ expect(serialized).to be_equivalent_to(xml)
721
691
  end
692
+ end
722
693
 
723
- it "duplicates delegate" do
724
- # `delegate` is symbol which are constant so object_id will be same
725
- expect(orig_mapping.delegate).to eq(dup_mapping.delegate)
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
- it "duplicates mixed_content" do
729
- # boolean value is constant so object_id will be same
730
- expect(orig_mapping.mixed_content).to eq(dup_mapping.mixed_content)
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
- it "duplicates name" do
734
- orig_name = orig_mapping.name
735
- dup_name = dup_mapping.name
718
+ let(:model) { XmlMapping::Person.from_xml(input_xml) }
736
719
 
737
- expect(orig_name).to eq(dup_name)
738
- expect(orig_name.object_id).not_to eq(dup_name.object_id)
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
- it "duplicates namespace" do
742
- orig_namespace = orig_mapping.namespace
743
- dup_namespace = dup_mapping.namespace
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 "duplicates namespace_set" do
750
- # boolean value is constant so object_id will be same
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
- it "duplicates prefix" do
755
- orig_prefix = orig_mapping.prefix
756
- dup_prefix = dup_mapping.prefix
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
- expect(orig_prefix).to eq(dup_prefix)
759
- expect(orig_prefix.object_id).not_to eq(dup_prefix.object_id)
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
- it "duplicates prefix_set" do
763
- # boolean value is constant so object_id will be same
764
- expect(orig_mapping.prefix_set?).to eq(dup_mapping.prefix_set?)
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
- it "duplicates render_nil" do
768
- # boolean value is constant so object_id will be same
769
- expect(orig_mapping.render_nil?).to eq(dup_mapping.render_nil?)
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
- describe "#map_all" do
780
- context "when map_all is defined before any other mapping" do
781
- it "raise error when for map_element with map_all" do
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
- it "raise error when for map_content with map_all" do
793
- expect do
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 "does not raise error for map_attribute with map_all" do
804
- expect do
805
- XmlMapping::WithMapAll.xml do
806
- map_attribute "attr", to: :attr
807
- end
808
- end.not_to raise_error
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
- context "when map_all is defined after other mappings" do
813
- let(:error_message) { "map_all is not allowed with other mappings" }
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
- it "raise error when for map_element with map_all" do
816
- expect do
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
- it "maps all the content including tags" do
825
- inner_xml = "Str<sub>2</sub>text<sup>1</sup>123"
826
- xml = "<WithMapAll>#{inner_xml}</WithMapAll>"
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
- parsed = XmlMapping::WithMapAll.from_xml(xml)
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
- expect(parsed.all_content).to eq(inner_xml)
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
- it "round-trips xml" do
834
- xml = "<WithMapAll>Str<sub>2</sub>text<sup>1</sup>123</WithMapAll>"
835
- expected_xml = "<WithMapAll>Str&lt;sub&gt;2&lt;/sub&gt;text&lt;sup&gt;1&lt;/sup&gt;123</WithMapAll>"
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
- expect(XmlMapping::WithMapAll.from_xml(xml).to_xml).to eq(expected_xml)
838
- end
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
- context "when nested content has map_all" do
841
- let(:description) do
842
- <<~DESCRIPTION
843
- I'm a <b>web developer</b> with <strong>years</strong> of
844
- <i>experience</i> in many programing languages.
845
- DESCRIPTION
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
- let(:expected_description) do
849
- <<~DESCRIPTION
850
- I'm a &lt;b&gt;web developer&lt;/b&gt; with &lt;strong&gt;years&lt;/strong&gt; of
851
- &lt;i&gt;experience&lt;/i&gt; in many programing languages.
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
- let(:xml) do
856
- <<~XML
857
- <WithNestedMapAll age="23">
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
- let(:expected_xml) do
867
- <<~XML
868
- <WithNestedMapAll age="23">
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
- let(:parsed) do
878
- XmlMapping::WithNestedMapAll.from_xml(xml)
879
- end
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
- it "maps description correctly" do
882
- expect(parsed.description.all_content.strip).to eq(description.strip)
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 name correctly" do
886
- expect(parsed.name).to eq("John Doe")
887
- end
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
- it "maps age correctly" do
890
- expect(parsed.age).to eq(23)
891
- end
935
+ parsed = XmlMapping::WithMapAll.from_xml(xml)
892
936
 
893
- it "round-trips xml" do
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 = <<~XML
901
- <SpecialCharContentWithMapAll>
902
- B <p>R&#x0026;C</p>
903
- C <p>J&#8212;C</p>
904
- O <p>A &amp; B </p>
905
- F <p>Z &#x00A9; </p>
906
- </SpecialCharContentWithMapAll>
907
- XML
941
+ xml = "<WithMapAll>Str<sub>2</sub>text<sup>1</sup>123</WithMapAll>"
908
942
 
909
- expected_xml = <<~XML.strip
910
- <SpecialCharContentWithMapAll>
911
- B &lt;p&gt;R&amp;amp;C&lt;/p&gt;
912
- C &lt;p&gt;J&amp;#x2014;C&lt;/p&gt;
913
- O &lt;p&gt;A &amp;amp; B &lt;/p&gt;
914
- F &lt;p&gt;Z &amp;#xA9; &lt;/p&gt;
915
- </SpecialCharContentWithMapAll>
916
- XML
943
+ expect(XmlMapping::WithMapAll.from_xml(xml).to_xml.chomp).to eq(xml)
944
+ end
917
945
 
918
- expect(XmlMapping::SpecialCharContentWithMapAll.from_xml(xml).to_xml).to eq(expected_xml)
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
- context "when mixed content is true and child is content_mapping" do
923
- let(:xml) do
924
- <<~XML
925
- <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
926
- <xsd:documentation>asdf</xsd:documentation>
927
- </xsd:schema>
928
- XML
1002
+ context "when special char used in content with map all" do
1003
+ let(:xml) do
1004
+ <<~XML
1005
+ <SpecialCharContentWithMapAll>
1006
+ B <p>R&#x0026;C</p>
1007
+ C <p>J&#8212;C</p>
1008
+ O <p>A &amp; B </p>
1009
+ F <p>Z &#x00A9; </p>
1010
+ </SpecialCharContentWithMapAll>
1011
+ XML
1012
+ end
1013
+
1014
+ let(:expected_nokogiri_xml) do
1015
+ <<~XML.strip
1016
+ <SpecialCharContentWithMapAll>
1017
+ B <p>R&amp;C</p>
1018
+ C <p>J—C</p>
1019
+ O <p>A &amp; 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&amp;C</p> " \
1028
+ "C <p>J—C</p> " \
1029
+ "O <p>A &amp; 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
- it "round-trips xml" do
932
- expect(XmlMapping::Schema.from_xml(xml).to_xml).to be_equivalent_to(xml)
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