lutaml-model 0.3.29 → 0.3.30

Sign up to get free protection for your applications and to get access to all the features.
@@ -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