lutaml-model 0.3.26 → 0.3.27

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1dc709174fab4f4df2214f08b536e0b1aded39f0c9f48a18eb5a4a53da3fc4b6
4
- data.tar.gz: 9eea83160b8210f84d4b2f9baf2ab577ca91d2a737eaf98b175d52385e6fb5d3
3
+ metadata.gz: e00c3fab326d719d8341687a8411797d60ccaf54820380ba7a2dacead6a89792
4
+ data.tar.gz: e46c1dd3d50f6b2bea7da738d94ace488655205deb049170057490f6d1526bf8
5
5
  SHA512:
6
- metadata.gz: 1e75326adeb9b8804f1bcc99104707edc3656e870d16c8af22e07e32ead9f4d78cd87eb372ebb834f2a5d942d58819e0fd3800e23a8099cf951360765223cd25
7
- data.tar.gz: ecc145fb2d9250cf855243c7b9cf468919f2530eed03039bd6c7a521fa534327a1a67c5348237b3d5959e20fa0fc2b2cadc87e57139f451610cd2d7d695f251b
6
+ metadata.gz: ab260d59203839c5fd9b1aa670501c1953c741fe75f0f7ab7261795c54cd19ed6de9807f9b8252c83ce9eee8cf2e6a9116087066e464ca1f35b8b46e29082351
7
+ data.tar.gz: c579a87612ce8e249edcca0c79f0ee2550d40af899e31ee2405ffdd48509e584df449c19bb3489a6871cdf4dfc08c4bc51f482422ea9a7d91f02d706d653cac6
data/README.adoc CHANGED
@@ -1302,6 +1302,69 @@ end
1302
1302
  ====
1303
1303
 
1304
1304
 
1305
+ ==== Encoding Options in XmlAdapter
1306
+
1307
+ XmlAdapter supports the encoding in the following ways:
1308
+
1309
+ . When encoding is not passed in to_xml:
1310
+ ** Default encoding is UTF-8.
1311
+
1312
+ . When encoding is explicitly passed nil:
1313
+ ** Encoding will be nil, show the HexCode(Nokogiri) or ASCII-8bit(Ox).
1314
+
1315
+ . When encoding is passed with some option:
1316
+ ** Encoding option will be selected as passed.
1317
+
1318
+
1319
+ Syntax:
1320
+
1321
+ [source,ruby]
1322
+ ----
1323
+ Example.new(description: " ∑ is my ∏ moniker µ.").to_xml
1324
+ Example.new(description: " ∑ is my ∏ moniker µ.").to_xml(encoding: nil)
1325
+ Example.new(description: " ∑ is my ∏ moniker µ.").to_xml(encoding: "ASCII")
1326
+ ----
1327
+
1328
+ [example]
1329
+ ====
1330
+ The following class will parse the XML snippet below:
1331
+
1332
+ [source,ruby]
1333
+ ----
1334
+ class Example < Lutaml::Model::Serializable
1335
+ attribute :name, :string
1336
+ attribute :description, :string
1337
+ attribute :value, :integer
1338
+
1339
+ xml do
1340
+ root 'example'
1341
+ map_element 'name', to: :name
1342
+ map_content to: :description
1343
+ end
1344
+ end
1345
+ ----
1346
+
1347
+ [source,xml]
1348
+ ----
1349
+ <example><name>John &#x0026; Doe</name> &#x2211; is my &#x220F; moniker &#xB5;.</example>
1350
+ ----
1351
+
1352
+ [source,ruby]
1353
+ ----
1354
+ > Example.from_xml(xml)
1355
+ > #<Example:0x0000000104ac7240 @name="John & Doe", @description=" ∑ is my ∏ moniker µ.">
1356
+ > Example.new(name: "John & Doe", description: " ∑ is my ∏ moniker µ.").to_xml
1357
+ > #<example><name>John &amp; Doe</name> ∑ is my ∏ moniker µ.</example>
1358
+
1359
+ > Example.new(name: "John & Doe", description: " ∑ is my ∏ moniker µ.").to_xml(encoding: nil)
1360
+ > #<example><name>John &amp; Doe</name> &#x2211; is my &#x220F; moniker &#xB5;.</example>
1361
+
1362
+ > Example.new(name: "John & Doe", description: " ∑ is my ∏ moniker µ.").to_xml(encoding: "ASCII")
1363
+ > #<example><name>John &amp; Doe</name> &#8721; is my &#8719; moniker &#181;.</example>
1364
+ ----
1365
+ ====
1366
+
1367
+
1305
1368
  ==== Namespaces
1306
1369
 
1307
1370
  [[root-namespace]]
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.3.26"
5
+ VERSION = "0.3.27"
6
6
  end
7
7
  end
@@ -13,7 +13,15 @@ module Lutaml
13
13
  end
14
14
 
15
15
  def to_xml(options = {})
16
- builder = Builder::Nokogiri.build(encoding: "UTF-8") do |xml|
16
+ builder_options = {}
17
+
18
+ if options.key?(:encoding)
19
+ builder_options[:encoding] = options[:encoding] unless options[:encoding].nil?
20
+ else
21
+ builder_options[:encoding] = "UTF-8"
22
+ end
23
+
24
+ builder = Builder::Nokogiri.build(builder_options) do |xml|
17
25
  if root.is_a?(Lutaml::Model::XmlAdapter::NokogiriElement)
18
26
  root.build_xml(xml)
19
27
  else
@@ -35,12 +43,11 @@ module Lutaml
35
43
 
36
44
  def prefix_xml(xml, mapping, options)
37
45
  if options.key?(:namespace_prefix)
38
- options[:namespace_prefix] ? xml[options[:namespace_prefix]] : xml
46
+ xml[options[:namespace_prefix]] if options[:namespace_prefix]
39
47
  elsif mapping.namespace_prefix
40
48
  xml[mapping.namespace_prefix]
41
- else
42
- xml
43
49
  end
50
+ xml
44
51
  end
45
52
 
46
53
  def build_ordered_element(xml, element, options = {})
@@ -14,8 +14,15 @@ module Lutaml
14
14
 
15
15
  def to_xml(options = {})
16
16
  builder = Builder::Ox.build
17
- builder.xml.instruct(:xml, encoding: options[:encoding] || "UTF-8", version: options[:version])
17
+ builder_options = { version: options[:version] }
18
18
 
19
+ if options.key?(:encoding)
20
+ builder_options[:encoding] = options[:encoding] unless options[:encoding].nil?
21
+ else
22
+ builder_options[:encoding] = "UTF-8"
23
+ end
24
+
25
+ builder.xml.instruct(:xml, builder_options)
19
26
  if @root.is_a?(Lutaml::Model::XmlAdapter::OxElement)
20
27
  @root.build_xml(builder)
21
28
  elsif ordered?(@root, options)
@@ -66,7 +66,7 @@ module Lutaml
66
66
  options[:tag_name] = rule.name
67
67
 
68
68
  options[:mapper_class] = attribute&.type if attribute
69
- options[:namespace_set] = set_namespace?(rule)
69
+ options[:set_namespace] = set_namespace?(rule)
70
70
 
71
71
  options
72
72
  end
@@ -185,6 +185,7 @@ module Lutaml
185
185
  attributes = options[:xml_attributes] ||= {}
186
186
  attributes = build_attributes(element,
187
187
  xml_mapping, options).merge(attributes)&.compact
188
+
188
189
  if element.respond_to?(:schema_location) && element.schema_location
189
190
  attributes.merge!(element.schema_location.to_xml_attributes)
190
191
  end
@@ -275,7 +276,7 @@ module Lutaml
275
276
  end
276
277
 
277
278
  def set_namespace?(rule)
278
- rule.nil? || !rule.namespace_set? || !rule.namespace.nil?
279
+ rule.nil? || !rule.namespace_set?
279
280
  end
280
281
 
281
282
  def render_element?(rule, element, value)
@@ -336,7 +337,7 @@ module Lutaml
336
337
  end
337
338
 
338
339
  def build_attributes(element, xml_mapping, options = {})
339
- attrs = if options.fetch(:namespace_set, true)
340
+ attrs = if options.fetch(:set_namespace, true)
340
341
  namespace_attributes(xml_mapping)
341
342
  else
342
343
  {}
@@ -148,11 +148,11 @@ RSpec.describe Delegation do
148
148
  end
149
149
 
150
150
  it "provides XML declaration with UTF-8 encoding" \
151
- "if encoding: true option provided" do
151
+ "if encoding: 'UTF-8' option provided" do
152
152
  xml_data = delegation.to_xml(
153
153
  pretty: true,
154
154
  declaration: true,
155
- encoding: true,
155
+ encoding: "UTF-8",
156
156
  )
157
157
  expect(xml_data).to include('<?xml version="1.0" encoding="UTF-8"?>')
158
158
  end
@@ -170,6 +170,15 @@ module MixedContentSpec
170
170
  map_element :value, to: :value
171
171
  end
172
172
  end
173
+
174
+ class HexCode < Lutaml::Model::Serializable
175
+ attribute :content, :string
176
+
177
+ xml do
178
+ root "HexCode"
179
+ map_content to: :content
180
+ end
181
+ end
173
182
  end
174
183
 
175
184
  RSpec.describe "MixedContent" do
@@ -449,7 +458,7 @@ RSpec.describe "MixedContent" do
449
458
 
450
459
  it "serializes special char mixed content correctly" do
451
460
  parsed = MixedContentSpec::SpecialCharContentWithMixedTrue.from_xml(xml)
452
- serialized = parsed.to_xml
461
+ serialized = parsed.to_xml(encoding: "UTF-8")
453
462
 
454
463
  expect(serialized).to include(expected_xml)
455
464
  end
@@ -608,10 +617,68 @@ RSpec.describe "MixedContent" do
608
617
  end
609
618
  end
610
619
  end
620
+
621
+ context "when special char used as full entities, it persist as entities if no encoding provided" do
622
+ let(:xml) do
623
+ <<~XML
624
+ <HexCode>
625
+ &#x2211;computer security&#x220F; type of &#x200B; operation specified &#xB5; by an access right
626
+ </HexCode>
627
+ XML
628
+ end
629
+
630
+ describe ".from_xml" do
631
+ let(:expected_content) { "∑computer security∏ type of ​ operation specified µ by an access right" }
632
+
633
+ it "deserializes special char mixed content correctly" do
634
+ parsed = MixedContentSpec::HexCode.from_xml(xml)
635
+
636
+ expect(parsed.content.strip).to eq(expected_content)
637
+ end
638
+ end
639
+
640
+ describe ".to_xml" do
641
+ context "when default encoding xml" do
642
+ let(:expected_default_encoding_xml) { "∑computer security∏ type of ​ operation specified µ by an access right" }
643
+
644
+ it "serializes special char mixed content correctly with default encoding: UTF-8" do
645
+ parsed = MixedContentSpec::HexCode.from_xml(xml)
646
+ serialized = parsed.to_xml
647
+
648
+ expect(serialized.strip).to include(expected_default_encoding_xml)
649
+ end
650
+ end
651
+
652
+ context "when encoding: nil xml" do
653
+ let(:expected_encoding_nil_nokogiri_xml) { "&#x2211;computer security&#x220F; type of &#x200B; operation specified &#xB5; by an access right" }
654
+ let(:expected_encoding_nil_ox_xml) { "\xE2\x88\x91computer security\xE2\x88\x8F type of \xE2\x80\x8B operation specified \xC2\xB5 by an access right" }
655
+
656
+ it "serializes special char mixed content correctly with encoding: nil to get hexcode" do
657
+ parsed = MixedContentSpec::HexCode.from_xml(xml)
658
+ serialized = parsed.to_xml(encoding: nil)
659
+
660
+ if adapter_class == Lutaml::Model::XmlAdapter::OxAdapter
661
+ expected_output = expected_encoding_nil_ox_xml
662
+ expected_output.force_encoding("ASCII-8BIT")
663
+ else
664
+ expected_output = expected_encoding_nil_nokogiri_xml
665
+ end
666
+
667
+ expect(serialized.strip).to include(expected_output)
668
+ end
669
+ end
670
+ end
671
+ end
611
672
  end
612
673
 
613
674
  describe Lutaml::Model::XmlAdapter::NokogiriAdapter do
614
675
  it_behaves_like "mixed content behavior", described_class
676
+
677
+ it "raises error when serializes special char content with false encoding: 'ABC'" do
678
+ parsed = MixedContentSpec::HexCode.from_xml("<HexCode>&#x2211;computer security</HexCode>")
679
+
680
+ expect { parsed.to_xml(encoding: "ABC") }.to raise_error(StandardError, "unknown encoding name - ABC")
681
+ end
615
682
  end
616
683
 
617
684
  describe Lutaml::Model::XmlAdapter::OxAdapter do
@@ -127,6 +127,17 @@ module XmlMapping
127
127
  end
128
128
  end
129
129
 
130
+ class OverrideDefaultNamespacePrefix < Lutaml::Model::Serializable
131
+ attribute :same_element_name, SameNameDifferentNamespace
132
+
133
+ xml do
134
+ root "OverrideDefaultNamespacePrefix"
135
+ map_element :SameElementName, to: :same_element_name,
136
+ namespace: "http://www.omg.org/spec/XMI/20131001",
137
+ prefix: "abc"
138
+ end
139
+ end
140
+
130
141
  class SchemaLocationOrdered < Lutaml::Model::Serializable
131
142
  attribute :content, :string
132
143
  attribute :second, SchemaLocationOrdered
@@ -220,6 +231,30 @@ module XmlMapping
220
231
  prefix: nil
221
232
  end
222
233
  end
234
+
235
+ class Documentation < Lutaml::Model::Serializable
236
+ attribute :content, :string
237
+
238
+ xml do
239
+ root "documentation", mixed: true
240
+ namespace "http://www.w3.org/2001/XMLSchema", "xsd"
241
+
242
+ map_content to: :content
243
+ end
244
+ end
245
+
246
+ class Schema < Lutaml::Model::Serializable
247
+ attribute :documentation, Documentation, collection: true
248
+
249
+ xml do
250
+ root "schema"
251
+ namespace "http://www.w3.org/2001/XMLSchema", "xsd"
252
+
253
+ map_element :documentation, to: :documentation,
254
+ namespace: "http://www.w3.org/2001/XMLSchema",
255
+ prefix: "xsd"
256
+ end
257
+ end
223
258
  end
224
259
 
225
260
  RSpec.describe Lutaml::Model::XmlMapping do
@@ -245,6 +280,25 @@ RSpec.describe Lutaml::Model::XmlMapping do
245
280
  end
246
281
  end
247
282
 
283
+ context "overriding child namespace prefix" do
284
+ let(:input_xml) do
285
+ <<~XML
286
+ <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">
287
+ <abc:SameElementName App="hello">
288
+ <GML:ApplicationSchema>GML App</GML:ApplicationSchema>
289
+ <CityGML:ApplicationSchema>CityGML App</CityGML:ApplicationSchema>
290
+ <abc:ApplicationSchema>App</abc:ApplicationSchema>
291
+ </abc:SameElementName>
292
+ </OverrideDefaultNamespacePrefix>
293
+ XML
294
+ end
295
+
296
+ it "expect to round-trips" do
297
+ parsed = XmlMapping::OverrideDefaultNamespacePrefix.from_xml(input_xml)
298
+ expect(parsed.to_xml).to be_equivalent_to(input_xml)
299
+ end
300
+ end
301
+
248
302
  context "with same name elements" do
249
303
  let(:input_xml) do
250
304
  <<~XML
@@ -859,5 +913,19 @@ RSpec.describe Lutaml::Model::XmlMapping do
859
913
  expect(XmlMapping::SpecialCharContentWithMapAll.from_xml(xml).to_xml).to eq(expected_xml)
860
914
  end
861
915
  end
916
+
917
+ context "when mixed content is true and child is content_mapping" do
918
+ let(:xml) do
919
+ <<~XML
920
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
921
+ <xsd:documentation>asdf</xsd:documentation>
922
+ </xsd:schema>
923
+ XML
924
+ end
925
+
926
+ it "round-trips xml" do
927
+ expect(XmlMapping::Schema.from_xml(xml).to_xml).to be_equivalent_to(xml)
928
+ end
929
+ end
862
930
  end
863
931
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.26
4
+ version: 0.3.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-12 00:00:00.000000000 Z
11
+ date: 2024-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor