lutaml-model 0.3.7 → 0.3.9

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: 8362f4af3671083805d20014ef7e2422358aac08f1c15036a283dbedb91225ca
4
- data.tar.gz: 661838fcd61e972cd1827a1b4889b3d2073e7a8db16a4fce371dcbf09fb79b96
3
+ metadata.gz: 12f6b0d44c864c56f2573bae9a712485e0b266120fe53f342671b8cb144ce022
4
+ data.tar.gz: 3facbc5cc6ef8149f1628415f3d511c2e010de28f8ab5968f2e436eb6aa41b39
5
5
  SHA512:
6
- metadata.gz: 31757feb85022ff8472b8e178ff433a84e2dcbd7a00b6cc2055f3f4d860b4470201c2ee6c39d2a2b96cc86d96ec3654affd7078bb2cad595345afa50fec9826d
7
- data.tar.gz: ff6f2048f11d46a9e4df1ec872bca13e5ebcbbc098aa35689840e3601d18337e2e7a85afd48f8a67b1b39482782258cdc1494f13eb1cd67eac8ac37cc2f5809d
6
+ metadata.gz: 0157ca6aa7a9e0e0368fd1da623068670d033a54385b91aa45082412512f5ee1643d72da168d5b68fdef531034f49363417dbfce31c4b47452c8f1d0136d839d
7
+ data.tar.gz: cf6c69e91f9eb13275a845ee4253809cc60599527a26f28d13942fa26b10ce65bfbc6a6fed8fbc946a721a1d07edd8b98289447c668f7d8cba6dc3cd001bc85b
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2024-08-23 04:30:59 UTC using RuboCop version 1.65.1.
3
+ # on 2024-09-04 07:55:32 UTC using RuboCop version 1.66.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -14,107 +14,14 @@ Gemspec/RequireMFA:
14
14
  Exclude:
15
15
  - 'lutaml-model.gemspec'
16
16
 
17
- # Offense count: 28
18
- # This cop supports safe autocorrection (--autocorrect).
19
- # Configuration parameters: EnforcedStyle, IndentationWidth.
20
- # SupportedStyles: with_first_argument, with_fixed_indentation
21
- Layout/ArgumentAlignment:
22
- Exclude:
23
- - 'lib/lutaml/model/serialize.rb'
24
- - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
25
- - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
26
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
27
- - 'spec/lutaml/model/serializable_spec.rb'
28
-
29
- # Offense count: 1
30
- # This cop supports safe autocorrection (--autocorrect).
31
- # Configuration parameters: IndentationWidth.
32
- Layout/AssignmentIndentation:
33
- Exclude:
34
- - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
35
-
36
- # Offense count: 6
37
- # This cop supports safe autocorrection (--autocorrect).
38
- # Configuration parameters: EnforcedStyleAlignWith.
39
- # SupportedStylesAlignWith: either, start_of_block, start_of_line
40
- Layout/BlockAlignment:
41
- Exclude:
42
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
43
- - 'spec/lutaml/model/serializable_spec.rb'
44
-
45
- # Offense count: 6
46
- # This cop supports safe autocorrection (--autocorrect).
47
- Layout/BlockEndNewline:
48
- Exclude:
49
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
50
- - 'spec/lutaml/model/serializable_spec.rb'
51
-
52
- # Offense count: 1
53
- # This cop supports safe autocorrection (--autocorrect).
54
- Layout/EmptyLineAfterGuardClause:
55
- Exclude:
56
- - 'lib/lutaml/model/serialize.rb'
57
-
58
- # Offense count: 16
59
- # This cop supports safe autocorrection (--autocorrect).
60
- # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
61
- # SupportedHashRocketStyles: key, separator, table
62
- # SupportedColonStyles: key, separator, table
63
- # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
64
- Layout/HashAlignment:
65
- Exclude:
66
- - 'lib/lutaml/model/serialize.rb'
67
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
68
- - 'spec/lutaml/model/serializable_spec.rb'
69
-
70
- # Offense count: 1
71
- # This cop supports safe autocorrection (--autocorrect).
72
- # Configuration parameters: EnforcedStyle.
73
- # SupportedStyles: normal, indented_internal_methods
74
- Layout/IndentationConsistency:
75
- Exclude:
76
- - 'lutaml-model.gemspec'
77
-
78
- # Offense count: 12
79
- # This cop supports safe autocorrection (--autocorrect).
80
- # Configuration parameters: Width, AllowedPatterns.
81
- Layout/IndentationWidth:
82
- Exclude:
83
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
84
- - 'spec/lutaml/model/serializable_spec.rb'
85
-
86
- # Offense count: 83
17
+ # Offense count: 62
87
18
  # This cop supports safe autocorrection (--autocorrect).
88
19
  # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
89
20
  # URISchemes: http, https
90
21
  Layout/LineLength:
91
- Exclude:
92
- - 'lib/lutaml/model/cli.rb'
93
- - 'lib/lutaml/model/comparable_model.rb'
94
- - 'lib/lutaml/model/serialize.rb'
95
- - 'lib/lutaml/model/type.rb'
96
- - 'lib/lutaml/model/utils.rb'
97
- - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
98
- - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
99
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
100
- - 'spec/lutaml/model/comparable_model_spec.rb'
101
- - 'spec/lutaml/model/custom_serialization_spec.rb'
102
- - 'spec/lutaml/model/delegation_spec.rb'
103
- - 'spec/lutaml/model/schema/json_schema_spec.rb'
104
- - 'spec/lutaml/model/serializable_spec.rb'
105
-
106
- # Offense count: 24
107
- # This cop supports safe autocorrection (--autocorrect).
108
- # Configuration parameters: AllowInHeredoc.
109
- Layout/TrailingWhitespace:
110
- Exclude:
111
- - 'lib/lutaml/model/serialize.rb'
112
- - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
113
- - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
114
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
115
- - 'spec/lutaml/model/serializable_spec.rb'
22
+ Enabled: false
116
23
 
117
- # Offense count: 4
24
+ # Offense count: 10
118
25
  # Configuration parameters: AllowedMethods.
119
26
  # AllowedMethods: enums
120
27
  Lint/ConstantDefinitionInBlock:
@@ -123,8 +30,9 @@ Lint/ConstantDefinitionInBlock:
123
30
  - 'spec/lutaml/model/schema/relaxng_schema_spec.rb'
124
31
  - 'spec/lutaml/model/schema/xsd_schema_spec.rb'
125
32
  - 'spec/lutaml/model/schema/yaml_schema_spec.rb'
33
+ - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
126
34
 
127
- # Offense count: 28
35
+ # Offense count: 29
128
36
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
129
37
  Metrics/AbcSize:
130
38
  Exclude:
@@ -137,16 +45,17 @@ Metrics/AbcSize:
137
45
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
138
46
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
139
47
 
140
- # Offense count: 5
48
+ # Offense count: 6
141
49
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
142
50
  # AllowedMethods: refine
143
51
  Metrics/BlockLength:
144
- Max: 29
52
+ Max: 42
145
53
 
146
- # Offense count: 20
54
+ # Offense count: 22
147
55
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
148
56
  Metrics/CyclomaticComplexity:
149
57
  Exclude:
58
+ - 'lib/lutaml/model/attribute.rb'
150
59
  - 'lib/lutaml/model/comparable_model.rb'
151
60
  - 'lib/lutaml/model/serialize.rb'
152
61
  - 'lib/lutaml/model/type.rb'
@@ -154,27 +63,28 @@ Metrics/CyclomaticComplexity:
154
63
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
155
64
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
156
65
 
157
- # Offense count: 37
66
+ # Offense count: 36
158
67
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
159
68
  Metrics/MethodLength:
160
- Max: 45
69
+ Max: 43
161
70
 
162
71
  # Offense count: 4
163
72
  # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
164
73
  Metrics/ParameterLists:
165
74
  Max: 9
166
75
 
167
- # Offense count: 16
76
+ # Offense count: 18
168
77
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
169
78
  Metrics/PerceivedComplexity:
170
79
  Exclude:
80
+ - 'lib/lutaml/model/attribute.rb'
171
81
  - 'lib/lutaml/model/comparable_model.rb'
172
82
  - 'lib/lutaml/model/serialize.rb'
173
83
  - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
174
84
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
175
85
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
176
86
 
177
- # Offense count: 6
87
+ # Offense count: 7
178
88
  # Configuration parameters: Prefixes, AllowedPatterns.
179
89
  # Prefixes: when, with, without
180
90
  RSpec/ContextWording:
@@ -182,8 +92,9 @@ RSpec/ContextWording:
182
92
  - 'spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb'
183
93
  - 'spec/lutaml/model/xml_adapter/oga_adapter_spec.rb'
184
94
  - 'spec/lutaml/model/xml_adapter/ox_adapter_spec.rb'
95
+ - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
185
96
 
186
- # Offense count: 76
97
+ # Offense count: 86
187
98
  # Configuration parameters: CountAsOne.
188
99
  RSpec/ExampleLength:
189
100
  Max: 57
@@ -194,13 +105,14 @@ RSpec/IndexedLet:
194
105
  Exclude:
195
106
  - 'spec/address_spec.rb'
196
107
 
197
- # Offense count: 12
108
+ # Offense count: 18
198
109
  RSpec/LeakyConstantDeclaration:
199
110
  Exclude:
200
111
  - 'spec/lutaml/model/schema/json_schema_spec.rb'
201
112
  - 'spec/lutaml/model/schema/relaxng_schema_spec.rb'
202
113
  - 'spec/lutaml/model/schema/xsd_schema_spec.rb'
203
114
  - 'spec/lutaml/model/schema/yaml_schema_spec.rb'
115
+ - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
204
116
 
205
117
  # Offense count: 4
206
118
  RSpec/MultipleDescribes:
@@ -210,18 +122,19 @@ RSpec/MultipleDescribes:
210
122
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
211
123
  - 'spec/lutaml/model/xml_adapter_spec.rb'
212
124
 
213
- # Offense count: 70
125
+ # Offense count: 75
214
126
  RSpec/MultipleExpectations:
215
- Max: 10
127
+ Max: 11
216
128
 
217
129
  # Offense count: 11
218
130
  # Configuration parameters: AllowSubject.
219
131
  RSpec/MultipleMemoizedHelpers:
220
132
  Max: 9
221
133
 
222
- # Offense count: 3
134
+ # Offense count: 4
223
135
  RSpec/PendingWithoutReason:
224
136
  Exclude:
137
+ - 'spec/lutaml/model/mixed_content_spec.rb'
225
138
  - 'spec/lutaml/model/xml_adapter/oga_adapter_spec.rb'
226
139
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
227
140
  - 'spec/lutaml/model/xml_adapter_spec.rb'
@@ -239,35 +152,9 @@ Security/CompoundHash:
239
152
  Exclude:
240
153
  - 'lib/lutaml/model/comparable_model.rb'
241
154
 
242
- # Offense count: 10
243
- # This cop supports safe autocorrection (--autocorrect).
244
- # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
245
- # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
246
- # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
247
- # FunctionalMethods: let, let!, subject, watch
248
- # AllowedMethods: lambda, proc, it
249
- Style/BlockDelimiters:
250
- Exclude:
251
- - 'lib/lutaml/model/xml_adapter/xml_document.rb'
252
- - 'spec/lutaml/model/serializable_spec.rb'
253
-
254
- # Offense count: 2
255
- # This cop supports safe autocorrection (--autocorrect).
256
- Style/MultilineIfModifier:
257
- Exclude:
258
- - 'lib/lutaml/model/serialize.rb'
259
-
260
155
  # Offense count: 1
261
156
  # Configuration parameters: AllowedMethods.
262
157
  # AllowedMethods: respond_to_missing?
263
158
  Style/OptionalBooleanParameter:
264
159
  Exclude:
265
160
  - 'lib/lutaml/model/comparable_model.rb'
266
-
267
- # Offense count: 2
268
- # This cop supports safe autocorrection (--autocorrect).
269
- # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
270
- # SupportedStyles: single_quotes, double_quotes
271
- Style/StringLiterals:
272
- Exclude:
273
- - 'lutaml-model.gemspec'
data/README.adoc CHANGED
@@ -652,6 +652,7 @@ end
652
652
 
653
653
  ==== Namespaces
654
654
 
655
+ [[root-namespace]]
655
656
  ===== Namespace at root
656
657
 
657
658
  The `namespace` method in the `xml` block sets the namespace for the root
@@ -659,6 +660,7 @@ element.
659
660
 
660
661
  Syntax:
661
662
 
663
+ .Setting default namespace at the root element
662
664
  [source,ruby]
663
665
  ----
664
666
  xml do
@@ -666,6 +668,15 @@ xml do
666
668
  end
667
669
  ----
668
670
 
671
+ .Setting a prefixed namespace at the root element
672
+ [source,ruby]
673
+ ----
674
+ xml do
675
+ namespace 'http://example.com/namespace', 'prefix'
676
+ end
677
+ ----
678
+
679
+
669
680
  .Using the `namespace` method to set the namespace for the root element
670
681
  [example]
671
682
  ====
@@ -698,10 +709,43 @@ end
698
709
  ----
699
710
  ====
700
711
 
712
+ .Using the `namespace` method to set a prefixed namespace for the root element
713
+ [example]
714
+ ====
715
+ [source,ruby]
716
+ ----
717
+ class Ceramic < Lutaml::Model::Serializable
718
+ attribute :type, :string
719
+ attribute :glaze, :string
720
+
721
+ xml do
722
+ root 'Ceramic'
723
+ namespace 'http://example.com/ceramic', 'cer'
724
+ map_element 'Type', to: :type
725
+ map_element 'Glaze', to: :glaze
726
+ end
727
+ end
728
+ ----
729
+
730
+ [source,xml]
731
+ ----
732
+ <cer:Ceramic xmlns='http://example.com/ceramic'><cer:Type>Porcelain</cer:Type><cer:Glaze>Clear</cer:Glaze></cer:Ceramic>
733
+ ----
734
+
735
+ [source,ruby]
736
+ ----
737
+ > Ceramic.from_xml(xml_file)
738
+ > #<Ceramic:0x0000000104ac7240 @type="Porcelain", @glaze="Clear">
739
+ > Ceramic.new(type: "Porcelain", glaze: "Clear").to_xml
740
+ > #<cer:Ceramic xmlns="http://example.com/ceramic"><cer:Type>Porcelain</cer:Type><cer:Glaze>Clear</cer:Glaze></cer:Ceramic>
741
+ ----
742
+ ====
743
+
744
+
701
745
  ===== Namespace on attribute
702
746
 
703
- If the namespace is defined on an XML attribute, then that will be given
704
- priority over the one defined in the class.
747
+ If the namespace is defined on a model attribute that already has a namespace,
748
+ the mapped namespace will be given priority over the one defined in the class.
705
749
 
706
750
  Syntax:
707
751
 
@@ -725,6 +769,19 @@ In this example, `glz` will be used for `Glaze` if it is added inside the
725
769
 
726
770
  [source,ruby]
727
771
  ----
772
+ class Ceramic < Lutaml::Model::Serializable
773
+ attribute :type, :string
774
+ attribute :glaze, Glaze
775
+
776
+ xml do
777
+ root 'Ceramic'
778
+ namespace 'http://example.com/ceramic'
779
+
780
+ map_element 'Type', to: :type
781
+ map_element 'Glaze', to: :glaze, namespace: 'http://example.com/glaze', prefix: "glz"
782
+ end
783
+ end
784
+
728
785
  class Glaze < Lutaml::Model::Serializable
729
786
  attribute :color, :string
730
787
  attribute :temperature, :integer
@@ -737,18 +794,6 @@ class Glaze < Lutaml::Model::Serializable
737
794
  map_element 'temperature', to: :temperature
738
795
  end
739
796
  end
740
-
741
- class Ceramic < Lutaml::Model::Serializable
742
- attribute :type, :string
743
- attribute :glaze, Glaze
744
-
745
- xml do
746
- root 'Ceramic'
747
- map_element 'Type', to: :type
748
- map_element 'Glaze', to: :glaze, namespace: 'http://example.com/glaze', prefix: "glz"
749
- map_attribute 'xmlns', to: :namespace, namespace: 'http://example.com/ceramic'
750
- end
751
- end
752
797
  ----
753
798
 
754
799
  [source,xml]
@@ -764,6 +809,11 @@ end
764
809
 
765
810
  [source,ruby]
766
811
  ----
812
+ > # Using the original Glaze class namespace
813
+ > Glaze.new(color: "Clear", temperature: 1050).to_xml
814
+ > #<glaze:Glaze xmlns="http://example.com/old_glaze"><color>Clear</color><temperature>1050</temperature></glaze:Glaze>
815
+
816
+ > # Using the Ceramic class namespace for Glaze
767
817
  > Ceramic.from_xml(xml_file)
768
818
  > #<Ceramic:0x0000000104ac7240 @type="Porcelain", @glaze=#<Glaze:0x0000000104ac7240 @color="Clear", @temperature=1050>>
769
819
  > Ceramic.new(type: "Porcelain", glaze: Glaze.new(color: "Clear", temperature: 1050)).to_xml
@@ -800,7 +850,7 @@ class Ceramic < Lutaml::Model::Serializable
800
850
 
801
851
  xml do
802
852
  root 'Ceramic'
803
- namespace 'http://example.com/ceramic', prefix: 'cera'
853
+ namespace 'http://example.com/ceramic', 'cera'
804
854
  map_element 'Type', to: :type, namespace: :inherit
805
855
  map_element 'Glaze', to: :glaze
806
856
  map_attribute 'color', to: :color, namespace: 'http://example.com/color', prefix: 'clr'
@@ -810,13 +860,13 @@ end
810
860
 
811
861
  [source,xml]
812
862
  ----
813
- <Ceramic
863
+ <cera:Ceramic
814
864
  xmlns:cera='http://example.com/ceramic'
815
865
  xmlns:clr='http://example.com/color'
816
866
  clr:color="navy-blue">
817
867
  <cera:Type>Porcelain</cera:Type>
818
868
  <Glaze>Clear</Glaze>
819
- </Ceramic>
869
+ </cera:Ceramic>
820
870
  ----
821
871
 
822
872
  [source,ruby]
@@ -824,20 +874,18 @@ end
824
874
  > Ceramic.from_xml(xml_file)
825
875
  > #<Ceramic:0x0000000104ac7240 @type="Porcelain", @glaze="Clear", @color="navy-blue">
826
876
  > Ceramic.new(type: "Porcelain", glaze: "Clear", color: "navy-blue").to_xml
827
- > #<Ceramic xmlns:cera="http://example.com/ceramic"
877
+ > #<cera:Ceramic xmlns:cera="http://example.com/ceramic"
828
878
  # xmlns:clr='http://example.com/color'
829
879
  # clr:color="navy-blue">
830
880
  # <cera:Type>Porcelain</cera:Type>
831
881
  # <Glaze>Clear</Glaze>
832
- # </Ceramic>
882
+ # </cera:Ceramic>
833
883
  ----
834
884
  ====
835
885
 
836
886
  [[mixed-content]]
837
887
  ==== Mixed content
838
888
 
839
- ===== General
840
-
841
889
  In XML there can be tags that contain content mixed with other tags and where
842
890
  whitespace is significant, such as to represent rich text.
843
891
 
@@ -857,9 +905,8 @@ To map this to Lutaml::Model we can use the `mixed` option in either way:
857
905
  NOTE: This feature is not supported by Shale.
858
906
 
859
907
 
860
- ===== Specifying the `mixed` option at `root`
861
-
862
- This will always treat the content of the element itself as mixed content.
908
+ To specify mixed content, the `mixed: true` option needs to be set at the
909
+ `xml` block's `root` method.
863
910
 
864
911
  Syntax:
865
912
 
@@ -876,7 +923,7 @@ end
876
923
  [source,ruby]
877
924
  ----
878
925
  class Paragraph < Lutaml::Model::Serializable
879
- attribute :bold, :string
926
+ attribute :bold, :string, collection: true # allows multiple bold tags
880
927
  attribute :italic, :string
881
928
 
882
929
  xml do
@@ -900,57 +947,6 @@ end
900
947
  TODO: How to create mixed content from `#new`?
901
948
 
902
949
 
903
- ===== Specifying the `mixed` option when referencing a model
904
-
905
- This will only treat the content of the referenced model as mixed content if the
906
- `mixed: true` is added when referencing it.
907
-
908
- Syntax:
909
-
910
- [source,ruby]
911
- ----
912
- xml do
913
- map_element 'xml_element_name', to: :name_of_attribute, mixed: true
914
- end
915
- ----
916
-
917
- .Applying `mixed` to treat an inner element as mixed content
918
- [example]
919
- ====
920
- [source,ruby]
921
- ----
922
- class Paragraph < Lutaml::Model::Serializable
923
- attribute :bold, :string
924
- attribute :italic, :string
925
-
926
- xml do
927
- root 'p'
928
-
929
- map_element 'bold', to: :bold
930
- map_element 'i', to: :italic
931
- end
932
- end
933
-
934
- class Description < Lutaml::Model::Serializable
935
- attribute :paragraph, Paragraph
936
-
937
- xml do
938
- root 'description'
939
-
940
- map_element 'p', to: :paragraph, mixed: true
941
- end
942
- end
943
- ----
944
-
945
- [source,ruby]
946
- ----
947
- > Description.from_xml("<description><p>My name is <bold>John Doe</bold>, and I'm <i>28</i> years old</p></description>")
948
- > #<Description:0x0000000104ac7240 @paragraph=#<Paragraph:0x0000000104ac7240 @bold="John Doe", @italic="28">>
949
- > Description.new(paragraph: Paragraph.new(bold: "John Doe", italic: "28")).to_xml
950
- > #<description><p>My name is <bold>John Doe</bold>, and I'm <i>28</i> years old</p></description>
951
- ----
952
- ====
953
-
954
950
 
955
951
  === Key value data models
956
952
 
@@ -1579,7 +1575,7 @@ Lutaml::Model::Config.configure do |config|
1579
1575
  end
1580
1576
  ----
1581
1577
 
1582
- You can also provide the adapter type by using symbols like
1578
+ You can also provide the adapter type by using symbols like
1583
1579
 
1584
1580
  [source,ruby]
1585
1581
  ----
@@ -1765,6 +1761,11 @@ differences in implementation.
1765
1761
 
1766
1762
  4+h| XML features
1767
1763
 
1764
+ | <<root-namespace,XML default namespace>>
1765
+ | Yes. Supports `<root xmlns='http://example.com'>` through the `namespace` option without prefix.
1766
+ | No. Only supports `<root xmlns:prefix='http://example.com'>`.
1767
+ |
1768
+
1768
1769
  | XML mixed content support
1769
1770
  | Yes. Supports the following kind of XML through <<mixed-content,mixed content>> support.
1770
1771
 
@@ -61,7 +61,7 @@ module Lutaml
61
61
  value.map do |v|
62
62
  cast(v, format, instance: instance)
63
63
  end
64
- elsif type <= Serialize
64
+ elsif type <= Serialize && value.is_a?(Hash)
65
65
  type.apply_mappings(value, format, options)
66
66
  else
67
67
  Lutaml::Model::Type.cast(value, type)
@@ -84,27 +84,46 @@ module Lutaml
84
84
 
85
85
  define_method(:"from_#{format}") do |data|
86
86
  adapter = Lutaml::Model::Config.send(:"#{format}_adapter")
87
- doc = adapter.parse(data)
88
87
 
89
- apply_mappings(doc.to_h, format)
88
+ doc = adapter.parse(data)
89
+ public_send(:"of_#{format}", doc.to_h)
90
90
  end
91
91
 
92
- define_method(:"to_#{format}") do |instance|
93
- unless instance.is_a?(model)
94
- msg = "argument is a '#{instance.class}' but should be a '#{model}'"
95
- raise Lutaml::Model::IncorrectModelError, msg
92
+ define_method(:"of_#{format}") do |hash|
93
+ if hash.is_a?(Array)
94
+ return hash.map do |item|
95
+ apply_mappings(item, format)
96
+ end
96
97
  end
97
98
 
99
+ apply_mappings(hash, format)
100
+ end
101
+
102
+ define_method(:"to_#{format}") do |instance|
103
+ value = public_send(:"as_#{format}", instance)
98
104
  adapter = Lutaml::Model::Config.public_send(:"#{format}_adapter")
99
105
 
100
106
  if format == :xml
101
107
  xml_options = { mapper_class: self }
102
-
103
- adapter.new(instance).public_send(:"to_#{format}", xml_options)
108
+ adapter.new(value).public_send(:"to_#{format}", xml_options)
104
109
  else
105
- hash = hash_representation(instance, format)
106
- adapter.new(hash).public_send(:"to_#{format}")
110
+ adapter.new(value).public_send(:"to_#{format}")
111
+ end
112
+ end
113
+
114
+ define_method(:"as_#{format}") do |instance|
115
+ if instance.is_a?(Array)
116
+ return instance.map { |item| public_send(:"as_#{format}", item) }
117
+ end
118
+
119
+ unless instance.is_a?(model)
120
+ msg = "argument is a '#{instance.class}' but should be a '#{model}'"
121
+ raise Lutaml::Model::IncorrectModelError, msg
107
122
  end
123
+
124
+ return instance if format == :xml
125
+
126
+ hash_representation(instance, format)
108
127
  end
109
128
  end
110
129
 
@@ -120,8 +139,7 @@ module Lutaml
120
139
  next handle_delegate(instance, rule, hash, format) if rule.delegate
121
140
 
122
141
  if rule.custom_methods[:to]
123
- next instance.send(rule.custom_methods[:to], instance,
124
- hash)
142
+ next instance.send(rule.custom_methods[:to], instance, hash)
125
143
  end
126
144
 
127
145
  value = instance.send(name)
@@ -238,6 +256,7 @@ module Lutaml
238
256
 
239
257
  def apply_mappings(doc, format, options = {})
240
258
  instance = options[:instance] || model.new
259
+ return instance if !doc || doc.empty?
241
260
  return apply_xml_mapping(doc, instance, options) if format == :xml
242
261
 
243
262
  mappings = mappings_for(format).mappings
@@ -257,7 +276,10 @@ module Lutaml
257
276
  end
258
277
 
259
278
  if rule.custom_methods[:from]
260
- value = new.send(rule.custom_methods[:from], instance, value)
279
+ if value && !value.empty?
280
+ value = new.send(rule.custom_methods[:from], instance,
281
+ value)
282
+ end
261
283
  next
262
284
  end
263
285
 
@@ -289,7 +311,7 @@ module Lutaml
289
311
  "missing for #{self} in #{options[:caller_class]}"
290
312
  end
291
313
 
292
- if instance.respond_to?(:ordered=)
314
+ if instance.respond_to?(:ordered=) && doc.is_a?(Lutaml::Model::MappingHash)
293
315
  instance.element_order = doc.item_order
294
316
  instance.ordered = mappings_for(:xml).mixed_content? || options[:mixed_content]
295
317
  end
@@ -299,12 +321,15 @@ module Lutaml
299
321
  raise "Attribute '#{rule.to}' not found in #{self}" unless attr
300
322
 
301
323
  is_content_mapping = rule.name.nil?
324
+
302
325
  value = if is_content_mapping
303
326
  doc["text"]
304
327
  else
305
328
  doc[rule.name.to_s] || doc[rule.name.to_sym]
306
329
  end
307
330
 
331
+ value = [value].compact if attr.collection? && !value.is_a?(Array)
332
+
308
333
  if value.is_a?(Array)
309
334
  value = value.map do |v|
310
335
  v.is_a?(Hash) && !(attr.type <= Serialize) ? v["text"] : v
@@ -22,11 +22,13 @@ module Lutaml
22
22
  class #{t} # class Integer
23
23
  def self.cast(value) # def self.cast(value)
24
24
  return if value.nil? # return if value.nil?
25
+ #
25
26
  Type.cast(value, #{t}) # Type.cast(value, Integer)
26
27
  end # end
27
28
 
28
29
  def self.serialize(value) # def self.serialize(value)
29
30
  return if value.nil? # return if value.nil?
31
+ #
30
32
  Type.serialize(value, #{t}) # Type.serialize(value, Integer)
31
33
  end # end
32
34
  end # end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.3.7"
5
+ VERSION = "0.3.9"
6
6
  end
7
7
  end
@@ -17,9 +17,14 @@ module Lutaml
17
17
 
18
18
  def initialize(xml)
19
19
  @xml = xml
20
+ @current_namespace = nil
20
21
  end
21
22
 
22
23
  def create_element(name, attributes = {})
24
+ if @current_namespace && !name.start_with?("#{@current_namespace}:")
25
+ name = "#{@current_namespace}:#{name}"
26
+ end
27
+
23
28
  if block_given?
24
29
  xml.element(name, attributes) do |element|
25
30
  yield(self.class.new(element))
@@ -36,6 +41,8 @@ module Lutaml
36
41
  def create_and_add_element(element_name, prefix: nil, attributes: {})
37
42
  prefixed_name = if prefix
38
43
  "#{prefix}:#{element_name}"
44
+ elsif @current_namespace && !element_name.start_with?("#{@current_namespace}:")
45
+ "#{@current_namespace}:#{element_name}"
39
46
  else
40
47
  element_name
41
48
  end
@@ -47,6 +54,8 @@ module Lutaml
47
54
  else
48
55
  xml.element(prefixed_name, attributes)
49
56
  end
57
+
58
+ @current_namespace = nil
50
59
  end
51
60
 
52
61
  def <<(text)
@@ -59,9 +68,10 @@ module Lutaml
59
68
 
60
69
  # Add XML namespace to document
61
70
  #
62
- # Ox doesn't support XML namespaces so this method does nothing.
63
- def add_namespace_prefix(_prefix)
64
- # :noop:
71
+ # Ox doesn't support XML namespaces so we only save the
72
+ # current namespace prefix to add it to the element's name later.
73
+ def add_namespace_prefix(prefix)
74
+ @current_namespace = prefix
65
75
  self
66
76
  end
67
77
 
@@ -72,17 +72,18 @@ module Lutaml
72
72
  text = text[curr_index] if text.is_a?(Array)
73
73
 
74
74
  prefixed_xml.text text
75
- elsif attribute_def.collection?
75
+ elsif !value.nil? || element_rule.render_nil?
76
+ value = value[curr_index] if attribute_def.collection?
77
+
76
78
  add_to_xml(
77
79
  xml,
78
80
  element_rule.prefix,
79
- value[curr_index],
80
- attribute_def,
81
- element_rule,
81
+ value,
82
+ options.merge(
83
+ attribute: attribute_def,
84
+ rule: element_rule,
85
+ ),
82
86
  )
83
- elsif !value.nil? || element_rule.render_nil?
84
- add_to_xml(xml, element_rule.prefix, value, attribute_def,
85
- element_rule)
86
87
  end
87
88
  end
88
89
  end
@@ -158,7 +159,7 @@ module Lutaml
158
159
  end
159
160
  end
160
161
 
161
- def build_attributes(node)
162
+ def build_attributes(node, _options = {})
162
163
  attrs = node.attributes.transform_values(&:value)
163
164
 
164
165
  attrs.merge(build_namespace_attributes(node))
@@ -20,6 +20,8 @@ module Lutaml
20
20
  elsif ordered?(@root, options)
21
21
  build_ordered_element(builder, @root, options)
22
22
  else
23
+ mapper_class = options[:mapper_class] || @root.class
24
+ options[:xml_attributes] = build_namespace_attributes(mapper_class)
23
25
  build_element(builder, @root, options)
24
26
  end
25
27
 
@@ -46,6 +48,7 @@ module Lutaml
46
48
  curr_index = index_hash[name] += 1
47
49
 
48
50
  element_rule = xml_mapping.find_by_name(name)
51
+ next if element_rule.nil?
49
52
 
50
53
  attribute_def = attribute_definition_for(element, element_rule,
51
54
  mapper_class: mapper_class)
@@ -56,11 +59,18 @@ module Lutaml
56
59
  text = text[curr_index] if text.is_a?(Array)
57
60
 
58
61
  el.add_text(el, text)
59
- elsif attribute_def.collection?
60
- add_to_xml(el, nil, value[curr_index], attribute_def,
61
- element_rule)
62
62
  elsif !value.nil? || element_rule.render_nil?
63
- add_to_xml(el, nil, value, attribute_def, element_rule)
63
+ value = value[curr_index] if attribute_def.collection?
64
+
65
+ add_to_xml(
66
+ el,
67
+ nil,
68
+ value,
69
+ options.merge(
70
+ attribute: attribute_def,
71
+ rule: element_rule,
72
+ ),
73
+ )
64
74
  end
65
75
  end
66
76
  end
@@ -42,21 +42,24 @@ module Lutaml
42
42
  @root.order
43
43
  end
44
44
 
45
- def handle_nested_elements(builder, value, rule: nil, attribute: nil)
46
- options = build_options_for_nested_elements(attribute, rule)
45
+ def handle_nested_elements(builder, value, options = {})
46
+ element_options = build_options_for_nested_elements(options)
47
47
 
48
48
  case value
49
49
  when Array
50
- value.each { |val| build_element(builder, val, options) }
50
+ value.each { |val| build_element(builder, val, element_options) }
51
51
  else
52
- build_element(builder, value, options)
52
+ build_element(builder, value, element_options)
53
53
  end
54
54
  end
55
55
 
56
- def build_options_for_nested_elements(attribute, rule)
56
+ def build_options_for_nested_elements(options = {})
57
+ attribute = options.delete(:attribute)
58
+ rule = options.delete(:rule)
59
+
57
60
  return {} unless rule
58
61
 
59
- options = {}
62
+ # options = {}
60
63
 
61
64
  options[:namespace_prefix] = rule.prefix if rule&.namespace_set?
62
65
  options[:mixed_content] = rule.mixed_content
@@ -97,7 +100,18 @@ module Lutaml
97
100
  end
98
101
  end
99
102
 
100
- def add_to_xml(xml, prefix, value, attribute, rule)
103
+ def add_to_xml(xml, prefix, value, options = {})
104
+ if value.is_a?(Array)
105
+ value.each do |item|
106
+ add_to_xml(xml, prefix, item, options)
107
+ end
108
+
109
+ return
110
+ end
111
+
112
+ attribute = options[:attribute]
113
+ rule = options[:rule]
114
+
101
115
  if rule.custom_methods[:to]
102
116
  @root.send(rule.custom_methods[:to], @root, xml.parent, xml)
103
117
  return
@@ -107,8 +121,7 @@ module Lutaml
107
121
  handle_nested_elements(
108
122
  xml,
109
123
  value,
110
- rule: rule,
111
- attribute: attribute,
124
+ options.merge({ rule: rule, attribute: attribute }),
112
125
  )
113
126
  else
114
127
  xml.create_and_add_element(rule.name, prefix: prefix) do
@@ -136,7 +149,7 @@ module Lutaml
136
149
 
137
150
  attributes = options[:xml_attributes] ||= {}
138
151
  attributes = build_attributes(element,
139
- xml_mapping).merge(attributes)&.compact
152
+ xml_mapping, options).merge(attributes)&.compact
140
153
 
141
154
  prefix = if options.key?(:namespace_prefix)
142
155
  options[:namespace_prefix]
@@ -147,30 +160,28 @@ module Lutaml
147
160
  prefixed_xml = xml.add_namespace_prefix(prefix)
148
161
  tag_name = options[:tag_name] || xml_mapping.root_element
149
162
 
150
- xml.create_and_add_element(tag_name, prefix: prefix,
151
- attributes: attributes) do
163
+ prefixed_xml.create_and_add_element(tag_name, prefix: prefix,
164
+ attributes: attributes) do
152
165
  if options.key?(:namespace_prefix) && !options[:namespace_prefix]
153
- xml.add_namespace_prefix(nil)
166
+ prefixed_xml.add_namespace_prefix(nil)
154
167
  end
155
168
 
156
169
  xml_mapping.elements.each do |element_rule|
157
170
  attribute_def = attribute_definition_for(element, element_rule,
158
171
  mapper_class: mapper_class)
172
+
159
173
  value = attribute_value_for(element, element_rule)
160
174
 
161
175
  next if value.nil? && !element_rule.render_nil?
162
176
 
163
- if attribute_def.collection?
164
- value = [value] unless value.is_a?(Array)
177
+ value = [value] if attribute_def.collection? && !value.is_a?(Array)
165
178
 
166
- value.each do |v|
167
- add_to_xml(xml, element_rule.prefix, v, attribute_def,
168
- element_rule)
169
- end
170
- elsif !value.nil? || element_rule.render_nil?
171
- add_to_xml(xml, element_rule.prefix, value, attribute_def,
172
- element_rule)
173
- end
179
+ add_to_xml(
180
+ prefixed_xml,
181
+ element_rule.prefix,
182
+ value,
183
+ options.merge({ attribute: attribute_def, rule: element_rule }),
184
+ )
174
185
  end
175
186
 
176
187
  if (content_rule = xml_mapping.content_mapping)
@@ -201,9 +212,11 @@ module Lutaml
201
212
 
202
213
  attrs = {}
203
214
 
204
- if xml_mappings.namespace_prefix
205
- attrs["xmlns:#{xml_mappings.namespace_prefix}"] =
206
- xml_mappings.namespace_uri
215
+ if xml_mappings.namespace_uri
216
+ prefixed_name = ["xmlns",
217
+ xml_mappings.namespace_prefix].compact.join(":")
218
+
219
+ attrs[prefixed_name] = xml_mappings.namespace_uri
207
220
  end
208
221
 
209
222
  xml_mappings.mappings.each do |mapping_rule|
@@ -231,10 +244,12 @@ module Lutaml
231
244
  attrs
232
245
  end
233
246
 
234
- def build_attributes(element, xml_mapping)
247
+ def build_attributes(element, xml_mapping, options = {})
235
248
  attrs = namespace_attributes(xml_mapping)
236
249
 
237
250
  xml_mapping.attributes.each_with_object(attrs) do |mapping_rule, hash|
251
+ next if options[:except]&.include?(mapping_rule.to)
252
+
238
253
  if mapping_rule.namespace
239
254
  hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
240
255
  end
@@ -243,6 +258,8 @@ module Lutaml
243
258
  end
244
259
 
245
260
  xml_mapping.elements.each_with_object(attrs) do |mapping_rule, hash|
261
+ next if options[:except]&.include?(mapping_rule.to)
262
+
246
263
  if mapping_rule.namespace
247
264
  hash["xmlns:#{mapping_rule.prefix}"] = mapping_rule.namespace
248
265
  end
@@ -44,8 +44,7 @@ module Lutaml
44
44
  delegate: nil,
45
45
  namespace: (namespace_set = false
46
46
  nil),
47
- prefix: nil,
48
- mixed: false
47
+ prefix: nil
49
48
  )
50
49
  @elements[name] = XmlMappingRule.new(
51
50
  name,
@@ -55,7 +54,6 @@ module Lutaml
55
54
  delegate: delegate,
56
55
  namespace: namespace,
57
56
  prefix: prefix,
58
- mixed_content: mixed,
59
57
  namespace_set: namespace_set != false,
60
58
  )
61
59
  end
data/lutaml-model.gemspec CHANGED
@@ -30,5 +30,6 @@ Gem::Specification.new do |spec|
30
30
  end
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
32
 
33
+ spec.add_dependency "bigdecimal"
33
34
  spec.add_dependency "thor"
34
35
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.3.9
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-08-23 00:00:00.000000000 Z
11
+ date: 2024-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bigdecimal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: thor
15
29
  requirement: !ruby/object:Gem::Requirement