lutaml-model 0.8.12 → 0.8.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +116 -103
  3. data/RELEASE_NOTES.adoc +3 -3
  4. data/benchmark/quick_benchmark.rb +2 -2
  5. data/benchmark/serialization_benchmark.rb +4 -4
  6. data/docs/_guides/advanced-mapping.adoc +1 -1
  7. data/docs/_guides/character-encoding.adoc +3 -3
  8. data/docs/_guides/missing-values-handling.adoc +6 -6
  9. data/docs/_guides/ooxml-examples.adoc +7 -7
  10. data/docs/_guides/opal.adoc +1 -1
  11. data/docs/_guides/value-transformations.adoc +7 -7
  12. data/docs/_guides/xml/namespace-presentation.adoc +1 -1
  13. data/docs/_guides/xml/namespace-semantics.adoc +15 -15
  14. data/docs/_guides/xml/type-namespaces.adoc +9 -9
  15. data/docs/_guides/xml-mapping.adoc +32 -26
  16. data/docs/_guides/xml-namespace-qualification.adoc +4 -4
  17. data/docs/_guides/xml-namespaces.adoc +2 -2
  18. data/docs/_guides/xml_mappings/04_xml_namespace_class.adoc +18 -18
  19. data/docs/_guides/xml_mappings/05_common_patterns.adoc +16 -16
  20. data/docs/_guides/xml_mappings/06_migration_guide.adoc +5 -5
  21. data/docs/_guides/xml_mappings/07_best_practices.adoc +11 -11
  22. data/docs/_migrations/0-8-0-namespace-restructuring.adoc +2 -2
  23. data/docs/_pages/attributes.adoc +2 -2
  24. data/docs/_pages/collections.adoc +26 -20
  25. data/docs/_pages/consolidation-mapping.adoc +4 -4
  26. data/docs/_pages/importable_models.adoc +14 -13
  27. data/docs/_pages/quick-start.adoc +1 -1
  28. data/docs/_pages/value_types.adoc +10 -10
  29. data/docs/_references/custom_registers.adoc +7 -7
  30. data/docs/_references/format-independent-features.adoc +4 -4
  31. data/docs/_references/instance-serialization.adoc +1 -1
  32. data/docs/_references/parent-root-context.adoc +3 -3
  33. data/docs/_tutorials/basic-model-definition.adoc +1 -1
  34. data/docs/_tutorials/first-xml-serialization.adoc +4 -4
  35. data/docs/_tutorials/lutaml-xml-architecture.adoc +4 -4
  36. data/docs/_tutorials/validation-basics.adoc +1 -1
  37. data/docs/_tutorials/working-with-collections.adoc +2 -2
  38. data/docs/_tutorials/xml-namespaces-basics.adoc +1 -1
  39. data/docs/_tutorials/xml-schema-primer-style-guide.adoc +29 -29
  40. data/docs/cli_compare.adoc +1 -1
  41. data/docs/index.adoc +1 -1
  42. data/docs/namespace-management.adoc +14 -14
  43. data/lib/lutaml/key_value/mapping.rb +31 -6
  44. data/lib/lutaml/model/collection.rb +11 -11
  45. data/lib/lutaml/model/error/no_root_mapping_error.rb +6 -5
  46. data/lib/lutaml/model/error/no_root_namespace_error.rb +6 -5
  47. data/lib/lutaml/model/error/type_only_mapping_error.rb +13 -0
  48. data/lib/lutaml/model/error/type_only_namespace_error.rb +12 -0
  49. data/lib/lutaml/model/version.rb +1 -1
  50. data/lib/lutaml/model.rb +3 -0
  51. data/lib/lutaml/xml/adapter/base_adapter.rb +0 -9
  52. data/lib/lutaml/xml/adapter/nokogiri_adapter.rb +0 -1
  53. data/lib/lutaml/xml/adapter/oga_adapter.rb +0 -1
  54. data/lib/lutaml/xml/adapter/ox_adapter.rb +0 -1
  55. data/lib/lutaml/xml/adapter/rexml_adapter.rb +0 -1
  56. data/lib/lutaml/xml/adapter/xml_serializer.rb +42 -22
  57. data/lib/lutaml/xml/adapter.rb +4 -0
  58. data/lib/lutaml/xml/builder/base.rb +64 -25
  59. data/lib/lutaml/xml/builder/nokogiri.rb +0 -2
  60. data/lib/lutaml/xml/builder/oga.rb +0 -2
  61. data/lib/lutaml/xml/builder/ox.rb +0 -2
  62. data/lib/lutaml/xml/builder/rexml.rb +0 -2
  63. data/lib/lutaml/xml/builder.rb +1 -0
  64. data/lib/lutaml/xml/configurable.rb +2 -2
  65. data/lib/lutaml/xml/declaration_handler.rb +3 -105
  66. data/lib/lutaml/xml/mapping.rb +3 -3
  67. data/lib/lutaml/xml/schema/xsd/documentation.rb +1 -1
  68. data/lib/lutaml/xml/serialization/collection_ext.rb +7 -7
  69. data/lib/lutaml/xml/serialization/format_conversion.rb +1 -1
  70. data/lib/lutaml/xml/serialization/instance_methods.rb +1 -1
  71. data/lib/lutaml/xml.rb +1 -2
  72. data/lib/tasks/memory_profile.rb +2 -2
  73. data/lib/tasks/performance_benchmark.rb +5 -5
  74. data/spec/lutaml/key_value/transformation/rule_compiler_spec.rb +1 -1
  75. data/spec/lutaml/key_value/transformation/value_serializer_spec.rb +1 -1
  76. data/spec/lutaml/model/attribute_collection_spec.rb +1 -1
  77. data/spec/lutaml/model/cli_spec.rb +1 -1
  78. data/spec/lutaml/model/collection_spec.rb +1 -1
  79. data/spec/lutaml/model/collection_validation_spec.rb +6 -6
  80. data/spec/lutaml/model/consolidation_spec.rb +8 -8
  81. data/spec/lutaml/model/custom_collection_spec.rb +3 -3
  82. data/spec/lutaml/model/default_register_spec.rb +23 -23
  83. data/spec/lutaml/model/delegation_spec.rb +3 -10
  84. data/spec/lutaml/model/derived_attribute_serialization_spec.rb +1 -1
  85. data/spec/lutaml/model/dynamic_attribute_spec.rb +2 -2
  86. data/spec/lutaml/model/enum_spec.rb +1 -1
  87. data/spec/lutaml/model/group_spec.rb +12 -12
  88. data/spec/lutaml/model/lazy_collection_spec.rb +4 -4
  89. data/spec/lutaml/model/mixed_content_spec.rb +2 -2
  90. data/spec/lutaml/model/namespace_versioning_spec.rb +4 -4
  91. data/spec/lutaml/model/processing_instruction_spec.rb +11 -11
  92. data/spec/lutaml/model/register_methods_spec.rb +2 -2
  93. data/spec/lutaml/model/render_empty_spec.rb +1 -1
  94. data/spec/lutaml/model/serialize_perf_guard_spec.rb +1 -1
  95. data/spec/lutaml/model/transform_dynamic_attributes_spec.rb +1 -1
  96. data/spec/lutaml/model/transformation_builder_spec.rb +2 -2
  97. data/spec/lutaml/model/xml_decoupling_spec.rb +3 -3
  98. data/spec/lutaml/model/xsd_patterns_spec.rb +2 -3
  99. data/spec/lutaml/xml/adapter/order_spec.rb +1 -1
  100. data/spec/lutaml/xml/clear_parse_state_spec.rb +1 -1
  101. data/spec/lutaml/xml/content_model_validation_spec.rb +4 -2
  102. data/spec/lutaml/xml/doubly_defined_namespace_spec.rb +5 -5
  103. data/spec/lutaml/xml/enhanced_mapping_spec.rb +2 -1
  104. data/spec/lutaml/xml/entity_fragmentation_spec.rb +5 -5
  105. data/spec/lutaml/xml/indent_spec.rb +109 -0
  106. data/spec/lutaml/xml/line_ending_spec.rb +66 -0
  107. data/spec/lutaml/xml/mapping_finalization_guard_spec.rb +2 -2
  108. data/spec/lutaml/xml/model_transform_guard_spec.rb +4 -4
  109. data/spec/lutaml/xml/namespace_alias_spec.rb +4 -4
  110. data/spec/lutaml/xml/namespace_aware_parsing_spec.rb +3 -3
  111. data/spec/lutaml/xml/namespace_bound_element_roundtrip_spec.rb +2 -2
  112. data/spec/lutaml/xml/namespace_format_preservation_spec.rb +1 -1
  113. data/spec/lutaml/xml/namespace_inheritance_spec.rb +3 -3
  114. data/spec/lutaml/xml/namespace_preservation_spec.rb +5 -5
  115. data/spec/lutaml/xml/opal_xml_spec.rb +8 -8
  116. data/spec/lutaml/xml/pipeline_integration_spec.rb +145 -0
  117. data/spec/lutaml/xml/schema_primer_spec.rb +5 -5
  118. data/spec/lutaml/xml/transformation_spec.rb +20 -20
  119. data/spec/lutaml/xml/type_namespace/collector_spec.rb +1 -1
  120. data/spec/lutaml/xml/type_namespace/planner_spec.rb +3 -3
  121. metadata +7 -2
data/README.adoc CHANGED
@@ -336,7 +336,7 @@ class TermiumExtract < Lutaml::Model::Serializable
336
336
  attribute :extract_language, ExtractLanguage, collection: true
337
337
 
338
338
  xml do
339
- root "termium_extract"
339
+ element "termium_extract"
340
340
  map_attribute "language", to: :language
341
341
  map_element "extractLanguage", to: :extract_language
342
342
  end
@@ -496,7 +496,7 @@ model, the `import_model_mappings` method can be used (see
496
496
 
497
497
  === Serialization and transformation
498
498
 
499
- Models can be serialized to various formats (XML, JSON, YAML, TOML) or
499
+ Models can be serialized to various formats (XML, JSON, YAML, TOML) or
500
500
  transformed to other representations like Hash objects.
501
501
 
502
502
  ==== Basic serialization
@@ -853,7 +853,7 @@ class Event < Lutaml::Model::Serializable
853
853
  attribute :start_date, :date
854
854
 
855
855
  xml do
856
- root "event"
856
+ element "event"
857
857
  map_element "startDate", to: :start_date
858
858
  end
859
859
 
@@ -908,7 +908,7 @@ class ProcessingTask < Lutaml::Model::Serializable
908
908
  attribute :processing_time, :duration
909
909
 
910
910
  xml do
911
- root "task"
911
+ element "task"
912
912
  map_element "processingTime", to: :processing_time
913
913
  end
914
914
  end
@@ -938,7 +938,7 @@ class Resource < Lutaml::Model::Serializable
938
938
  attribute :schema_location, :uri
939
939
 
940
940
  xml do
941
- root "resource"
941
+ element "resource"
942
942
  map_element "homepage", to: :homepage
943
943
  map_attribute "schemaLocation", to: :schema_location
944
944
  end
@@ -973,7 +973,7 @@ class Reference < Lutaml::Model::Serializable
973
973
  attribute :target, :qname
974
974
 
975
975
  xml do
976
- root "reference"
976
+ element "reference"
977
977
  map_attribute "type", to: :ref_type
978
978
  map_element "target", to: :target
979
979
  end
@@ -1011,7 +1011,7 @@ class Attachment < Lutaml::Model::Serializable
1011
1011
  attribute :filename, :string
1012
1012
 
1013
1013
  xml do
1014
- root "attachment"
1014
+ element "attachment"
1015
1015
  map_element "content", to: :content
1016
1016
  map_attribute "filename", to: :filename
1017
1017
  end
@@ -1052,7 +1052,7 @@ class Checksum < Lutaml::Model::Serializable
1052
1052
  attribute :algorithm, :string
1053
1053
 
1054
1054
  xml do
1055
- root "checksum"
1055
+ element "checksum"
1056
1056
  map_element "value", to: :hash_value
1057
1057
  map_attribute "algorithm", to: :algorithm
1058
1058
  end
@@ -1114,7 +1114,7 @@ class Task < Lutaml::Model::Serializable
1114
1114
  attribute :priority, :symbol
1115
1115
 
1116
1116
  xml do
1117
- root "task"
1117
+ element "task"
1118
1118
  map_element "status", to: :status
1119
1119
  map_element "priority", to: :priority
1120
1120
  end
@@ -1359,7 +1359,7 @@ class Address < Lutaml::Model::Serializable
1359
1359
 
1360
1360
  # Define how this complex object maps to different formats
1361
1361
  xml do
1362
- root "Address"
1362
+ element "Address"
1363
1363
  map_element "Street", to: :street
1364
1364
  map_element "City", to: :city
1365
1365
  map_element "PostalCode", to: :postal_code
@@ -2603,7 +2603,7 @@ class ReferenceSet < Lutaml::Model::Serializable
2603
2603
  ]
2604
2604
 
2605
2605
  xml do
2606
- root "ReferenceSet"
2606
+ element "ReferenceSet"
2607
2607
 
2608
2608
  map_element "reference", to: :references, polymorphic: {
2609
2609
  # This refers to the attribute in the polymorphic model, you need
@@ -2740,7 +2740,7 @@ class SomeModel < Lutaml::Model::Serializable
2740
2740
  attribute :coll, :string, collection: true
2741
2741
 
2742
2742
  xml do
2743
- root "some-model"
2743
+ element "some-model"
2744
2744
  map_element 'collection', to: :coll
2745
2745
  end
2746
2746
 
@@ -2904,7 +2904,8 @@ class Person < Lutaml::Model::Serializable
2904
2904
  end
2905
2905
 
2906
2906
  xml do
2907
- root "Person", mixed: true
2907
+ element "Person"
2908
+ mixed_content
2908
2909
  sequence do
2909
2910
  map_element :FirstName, to: :first_name
2910
2911
  map_element :LastName, to: :last_name
@@ -2961,8 +2962,9 @@ This feature works both with XML and key-value formats.
2961
2962
 
2962
2963
  * The import order determines how elements and attributes are overwritten.
2963
2964
 
2964
- * An importable model with XML serialization mappings requires setting the model's
2965
- XML serialization configuration with the `no_root` directive.
2965
+ * An importable model with XML serialization mappings is a "type-only model" —
2966
+ it has no `element` declaration in its `xml` block, meaning it can only be
2967
+ used as an embedded type through a parent model.
2966
2968
 
2967
2969
  The model can be imported into another model using the following directives:
2968
2970
 
@@ -2972,11 +2974,11 @@ The model can be imported into another model using the following directives:
2972
2974
 
2973
2975
  `import_model_mappings`:: imports only mappings.
2974
2976
 
2975
- NOTE: Models with `no_root` can only be parsed through parent models.
2976
- Direct calling `NoRootModel.from_xml` will raise a `NoRootMappingError`.
2977
+ NOTE: Type-only models (no `element` declaration) can only be parsed through parent models.
2978
+ Directly calling `TypeOnlyModel.from_xml` will raise a `TypeOnlyMappingError`.
2977
2979
 
2978
2980
  NOTE: Namespaces are not currently supported in importable models.
2979
- If `namespace` is defined with `no_root`, `NoRootNamespaceError` will be raised.
2981
+ If `namespace` is defined with the deprecated `no_root`, `TypeOnlyNamespaceError` will be raised.
2980
2982
 
2981
2983
  .Importing model components using an importable model
2982
2984
  [example]
@@ -2998,7 +3000,7 @@ class GroupOfItems < Lutaml::Model::Serializable
2998
3000
  attribute :code, :string
2999
3001
 
3000
3002
  xml do
3001
- no_root
3003
+ # Type-only model - no element declaration needed
3002
3004
  sequence do
3003
3005
  map_element "name", to: :name
3004
3006
  map_element "type", to: :type
@@ -3014,7 +3016,7 @@ class ComplexType < Lutaml::Model::Serializable
3014
3016
  import_model_attributes GroupOfItems
3015
3017
 
3016
3018
  xml do
3017
- root "GroupOfItems"
3019
+ element "GroupOfItems"
3018
3020
 
3019
3021
  map_attribute "tag", to: :tag
3020
3022
  map_content to: :content
@@ -3043,7 +3045,7 @@ end
3043
3045
  [source,ruby]
3044
3046
  ----
3045
3047
  > parsed = GroupOfItems.from_xml(xml)
3046
- > # Lutaml::Model::NoRootMappingError: "GroupOfItems has `no_root`, it allowed only for reusable models"
3048
+ > # Lutaml::Model::TypeOnlyMappingError: "GroupOfItems is a type-only model (no element declared), ..."
3047
3049
  ----
3048
3050
  ====
3049
3051
 
@@ -3131,7 +3133,7 @@ class Address < Lutaml::Model::Serializable
3131
3133
  attribute :zip, :string
3132
3134
 
3133
3135
  xml do
3134
- no_root
3136
+ # Type-only model - no element declaration needed
3135
3137
 
3136
3138
  map_element :street, to: :street
3137
3139
  map_element :city, to: :city
@@ -3144,7 +3146,7 @@ class Person < Lutaml::Model::Serializable
3144
3146
  import_model_attributes Address
3145
3147
 
3146
3148
  xml do
3147
- root "Person"
3149
+ element "Person"
3148
3150
 
3149
3151
  map_element :name, to: :name
3150
3152
  sequence do
@@ -3200,7 +3202,7 @@ class ContactEmail < Lutaml::Model::Serializable
3200
3202
  attribute :email, :string
3201
3203
 
3202
3204
  xml do
3203
- no_root
3205
+ # Type-only model - no element declaration needed
3204
3206
 
3205
3207
  map_element :email, to: :email
3206
3208
  end
@@ -3210,7 +3212,7 @@ class ContactPhone < Lutaml::Model::Serializable
3210
3212
  attribute :phone, :string
3211
3213
 
3212
3214
  xml do
3213
- no_root
3215
+ # Type-only model - no element declaration needed
3214
3216
 
3215
3217
  map_element :phone, to: :phone
3216
3218
  end
@@ -3224,7 +3226,7 @@ class Person < Lutaml::Model::Serializable
3224
3226
  end
3225
3227
 
3226
3228
  xml do
3227
- root "Person"
3229
+ element "Person"
3228
3230
 
3229
3231
  map_element :email, to: :email
3230
3232
  map_element :phone, to: :phone
@@ -3735,7 +3737,7 @@ class TitleDelimiterCollection < Lutaml::Model::Collection
3735
3737
  instances :items, :string
3736
3738
 
3737
3739
  xml do
3738
- root "titles"
3740
+ element "titles"
3739
3741
  map_attribute "title", to: :items, delimiter: "; " <1>
3740
3742
  end
3741
3743
  end
@@ -3754,7 +3756,7 @@ class TitleCollection < Lutaml::Model::Collection
3754
3756
  instances :items, :string
3755
3757
 
3756
3758
  xml do
3757
- root "titles"
3759
+ element "titles"
3758
3760
  map_attribute "title", to: :items, as_list: {
3759
3761
  import: ->(str) { str.split("; ") }, <1>
3760
3762
  export: ->(arr) { arr.join("; ") }, <2>
@@ -3892,7 +3894,6 @@ class TitleCollection < Lutaml::Model::Collection
3892
3894
  instances :titles, Title
3893
3895
 
3894
3896
  key_value do
3895
- no_root # default
3896
3897
  map_instances to: :titles
3897
3898
  end
3898
3899
  end
@@ -3972,7 +3973,6 @@ class TitleCollection < Lutaml::Model::Collection
3972
3973
  instances :titles, Title
3973
3974
 
3974
3975
  key_value do
3975
- no_root # default
3976
3976
  map_instances to: :titles
3977
3977
  end
3978
3978
  end
@@ -4067,11 +4067,11 @@ class MyCollection < Lutaml::Model::Collection
4067
4067
  instances :items, ModelType
4068
4068
 
4069
4069
  xml do
4070
- root "name-of-xml-container-element"
4070
+ element "name-of-xml-container-element"
4071
4071
  end
4072
4072
 
4073
4073
  key_value do
4074
- root "name-of-key-value-container-element"
4074
+ root "name-of-key-value-container-key"
4075
4075
  end
4076
4076
  end
4077
4077
 
@@ -4080,6 +4080,15 @@ class ModelType < Lutaml::Model::Serializable
4080
4080
  end
4081
4081
  ----
4082
4082
 
4083
+ In the `key_value` block:
4084
+
4085
+ - `key "key-name"` sets the wrapper key for the collection in key-value formats (JSON, YAML, TOML).
4086
+ The serialized output wraps all instances under this key (e.g., `{"titles": [...]}`).
4087
+ - Without a `key` call (the default), instances are serialized directly at the top level
4088
+ (e.g., `["Item One", "Item Two"]`).
4089
+
4090
+ NOTE: Key-value formats use `key` to set the wrapper key name, and `element` for XML element names.
4091
+
4083
4092
  A named collection can alternatively be implemented as a non-collection model
4084
4093
  ("Model class with an attribute") that contains the collection of instances. In
4085
4094
  this case, the attribute will be an Array object, which does not contain
@@ -4094,7 +4103,7 @@ class Title < Lutaml::Model::Serializable
4094
4103
  attribute :title, :string
4095
4104
 
4096
4105
  xml do
4097
- root "title"
4106
+ element "title"
4098
4107
  map_content to: :title
4099
4108
  end
4100
4109
  end
@@ -4103,7 +4112,7 @@ class DirectTitleCollection < Lutaml::Model::Collection
4103
4112
  instances :items, Title
4104
4113
 
4105
4114
  xml do
4106
- root "titles"
4115
+ element "titles"
4107
4116
  map_element "title", to: :items
4108
4117
  end
4109
4118
 
@@ -4229,7 +4238,7 @@ class Title < Lutaml::Model::Serializable
4229
4238
  attribute :title, :string
4230
4239
 
4231
4240
  xml do
4232
- root "title"
4241
+ element "title"
4233
4242
  map_element "content", to: :title
4234
4243
  end
4235
4244
 
@@ -4242,12 +4251,12 @@ class TitleCollection < Lutaml::Model::Collection
4242
4251
  instances :items, Title
4243
4252
 
4244
4253
  xml do
4245
- root "titles"
4254
+ element "titles"
4246
4255
  map_element 'title', to: :items
4247
4256
  end
4248
4257
 
4249
4258
  key_value do
4250
- root "titles"
4259
+ element "titles"
4251
4260
  map_instances to: :items
4252
4261
  end
4253
4262
  end
@@ -4332,12 +4341,12 @@ class BibliographicItem < Lutaml::Model::Serializable
4332
4341
  attribute :title_parts, :string, collection: StringParts
4333
4342
 
4334
4343
  xml do
4335
- root "titles"
4344
+ element "titles"
4336
4345
  map_element "title", to: :title_parts
4337
4346
  end
4338
4347
 
4339
4348
  key_value do
4340
- root "titles"
4349
+ element "titles"
4341
4350
  map_instances to: :title_parts
4342
4351
  end
4343
4352
 
@@ -4413,7 +4422,7 @@ class TitleCollection < Lutaml::Model::Collection
4413
4422
  instances :items, Title
4414
4423
 
4415
4424
  xml do
4416
- root "title-group"
4425
+ element "title-group"
4417
4426
  map_element "artifact", to: :items
4418
4427
  end
4419
4428
  end
@@ -4422,7 +4431,7 @@ class BibItem < Lutaml::Model::Serializable
4422
4431
  attribute :titles, TitleCollection
4423
4432
 
4424
4433
  xml do
4425
- root "bibitem"
4434
+ element "bibitem"
4426
4435
  # This overrides the collection's root "title-group"
4427
4436
  map_element "titles", to: :titles
4428
4437
  end
@@ -4801,14 +4810,14 @@ Collection-level validations are applied to the entire collection as a unit. The
4801
4810
  ----
4802
4811
  class UniquePublicationCollection < Lutaml::Model::Collection
4803
4812
  instances :publications, Publication
4804
-
4813
+
4805
4814
  # Ensure uniqueness of IDs across all publications
4806
4815
  validates_uniqueness_of :id, message: "Publication IDs must be unique"
4807
-
4816
+
4808
4817
  # Ensure collection size constraints
4809
4818
  validates_min_count 2, message: "Must have at least 2 publications"
4810
4819
  validates_max_count 10, message: "Cannot have more than 10 publications"
4811
-
4820
+
4812
4821
  # Ensure all publications have required fields
4813
4822
  validates_all_present :author, message: "All publications must have an author"
4814
4823
  validates_all_present :year
@@ -4824,7 +4833,7 @@ end
4824
4833
  ----
4825
4834
  class BusinessRuleCollection < Lutaml::Model::Collection
4826
4835
  instances :publications, Publication
4827
-
4836
+
4828
4837
  # Custom validation: ensure publication years are sequential
4829
4838
  validate_collection do |publications, errors|
4830
4839
  years = publications.map(&:year).compact.sort
@@ -4835,7 +4844,7 @@ class BusinessRuleCollection < Lutaml::Model::Collection
4835
4844
  end
4836
4845
  end
4837
4846
  end
4838
-
4847
+
4839
4848
  # Another custom validation: ensure category diversity
4840
4849
  validate_collection do |publications, errors|
4841
4850
  categories = publications.map(&:category).compact.uniq
@@ -4859,7 +4868,7 @@ class ComprehensiveCollection < Lutaml::Model::Collection
4859
4868
  validates :year, numericality: { greater_than: 1900 }
4860
4869
  validates :title, presence: true
4861
4870
  end
4862
-
4871
+
4863
4872
  # Collection-level validations (for the collection as a whole)
4864
4873
  validates_uniqueness_of :id
4865
4874
  validates_min_count 1
@@ -5107,12 +5116,11 @@ class OrderedItemCollection < Lutaml::Model::Collection
5107
5116
  ordered by: :id, order: :desc
5108
5117
 
5109
5118
  xml do
5110
- root "items"
5119
+ element "items"
5111
5120
  map_element "item", to: :items
5112
5121
  end
5113
5122
 
5114
5123
  key_value do
5115
- no_root
5116
5124
  map_instances to: :items
5117
5125
  end
5118
5126
  end
@@ -5141,7 +5149,7 @@ class ProcOrderedItemCollection < Lutaml::Model::Collection
5141
5149
  ordered by: ->(item) { [item.name.length, item.name] }, order: :asc
5142
5150
 
5143
5151
  xml do
5144
- root "items"
5152
+ element "items"
5145
5153
  map_element "item", to: :items
5146
5154
  end
5147
5155
  end
@@ -5197,7 +5205,7 @@ class ReferenceSet < Lutaml::Model::Collection
5197
5205
  ]
5198
5206
 
5199
5207
  xml do
5200
- root "ReferenceSet"
5208
+ element "ReferenceSet"
5201
5209
  map_instances to: :references, polymorphic: {
5202
5210
  attribute: "_class",
5203
5211
  class_map: {
@@ -5294,7 +5302,7 @@ class ReferenceSet < Lutaml::Model::Collection
5294
5302
  ]
5295
5303
 
5296
5304
  xml do
5297
- root "ReferenceSet"
5305
+ element "ReferenceSet"
5298
5306
  map_instances to: :references, polymorphic: {
5299
5307
  attribute: "_class",
5300
5308
  class_map: {
@@ -6142,7 +6150,7 @@ class Document < Lutaml::Model::Serializable
6142
6150
  attribute :content, :string
6143
6151
 
6144
6152
  xml do
6145
- root "doc"
6153
+ element "doc"
6146
6154
  map_attribute "lang", to: :lang
6147
6155
  map_attribute "space", to: :space
6148
6156
  map_attribute "id", to: :id
@@ -6302,7 +6310,8 @@ also supports the `mixed:` and `ordered:` options.
6302
6310
  In v0.8.0 onwards, these options are deprecated in favor of:
6303
6311
 
6304
6312
  * the `mixed_content` method replaces `mixed: true`;
6305
- * the `sequence do` block replaces the `ordered: true` option
6313
+ * the `sequence do` block or `ordered method replaces the `ordered: true`
6314
+ option.
6306
6315
  ====
6307
6316
 
6308
6317
  Syntax:
@@ -6332,7 +6341,7 @@ class Paragraph < Lutaml::Model::Serializable
6332
6341
  attribute :italic, :string
6333
6342
 
6334
6343
  xml do
6335
- root 'p', mixed: true # Enable mixed content
6344
+ root 'p', mixed: true # Enable mixed content
6336
6345
  map_element 'bold', to: :bold
6337
6346
  map_element 'i', to: :italic
6338
6347
  end
@@ -6679,7 +6688,8 @@ To specify mixed content, the `mixed: true` option needs to be set at the
6679
6688
  [source,ruby]
6680
6689
  ----
6681
6690
  xml do
6682
- root 'xml_element_name', mixed: true
6691
+ element 'xml_element_name'
6692
+ mixed_content
6683
6693
  end
6684
6694
  ----
6685
6695
 
@@ -6693,7 +6703,8 @@ class Paragraph < Lutaml::Model::Serializable
6693
6703
  attribute :italic, :string
6694
6704
 
6695
6705
  xml do
6696
- root 'p', mixed: true
6706
+ element 'p'
6707
+ mixed_content
6697
6708
 
6698
6709
  map_element 'bold', to: :bold
6699
6710
  map_element 'i', to: :italic
@@ -6736,7 +6747,8 @@ Syntax:
6736
6747
  [source,ruby]
6737
6748
  ----
6738
6749
  xml do
6739
- root 'xml_element_name', ordered: true
6750
+ element 'xml_element_name'
6751
+ ordered
6740
6752
  end
6741
6753
  ----
6742
6754
 
@@ -6752,7 +6764,8 @@ class RootOrderedContent < Lutaml::Model::Serializable
6752
6764
  attribute :underline, :string
6753
6765
 
6754
6766
  xml do
6755
- root "RootOrderedContent", ordered: true
6767
+ element "RootOrderedContent"
6768
+ ordered
6756
6769
  map_element :bold, to: :bold
6757
6770
  map_element :italic, to: :italic
6758
6771
  map_element :underline, to: :underline
@@ -6791,7 +6804,7 @@ class RootOrderedContent < Lutaml::Model::Serializable
6791
6804
  attribute :underline, :string
6792
6805
 
6793
6806
  xml do
6794
- root "RootOrderedContent"
6807
+ element "RootOrderedContent"
6795
6808
  map_element :bold, to: :bold
6796
6809
  map_element :italic, to: :italic
6797
6810
  map_element :underline, to: :underline
@@ -6875,7 +6888,7 @@ class Ceramic < Lutaml::Model::Serializable
6875
6888
  attribute :glaze, :string
6876
6889
 
6877
6890
  xml do
6878
- root 'Ceramic'
6891
+ element "Ceramic"
6879
6892
  namespace CeramicXmlNamespace
6880
6893
  map_element 'Type', to: :type
6881
6894
  map_element 'Glaze', to: :glaze
@@ -6949,7 +6962,7 @@ class Properties < Lutaml::Model::Serializable
6949
6962
  attribute :template, :string
6950
6963
 
6951
6964
  xml do
6952
- root "Properties"
6965
+ element "Properties"
6953
6966
  namespace AppNamespace
6954
6967
 
6955
6968
  # Force vt namespace to be declared even if unused
@@ -7128,7 +7141,7 @@ class Vcard < Lutaml::Model::Serializable
7128
7141
  attribute :created, DctermsCreatedType
7129
7142
 
7130
7143
  xml do
7131
- root "vCard"
7144
+ element "vCard"
7132
7145
  namespace VcardNamespace
7133
7146
  namespace_scope [VcardNamespace, DcNamespace, DctermsNamespace] # <1>
7134
7147
 
@@ -7192,7 +7205,7 @@ class Properties < Lutaml::Model::Serializable
7192
7205
  attribute :template, :string
7193
7206
 
7194
7207
  xml do
7195
- root "Properties"
7208
+ element "Properties"
7196
7209
  namespace AppNamespace
7197
7210
 
7198
7211
  # Force vt namespace declaration even though unused
@@ -7250,7 +7263,7 @@ class CoreProperties < Lutaml::Model::Serializable
7250
7263
  attribute :title, :string
7251
7264
 
7252
7265
  xml do
7253
- root "coreProperties"
7266
+ element "coreProperties"
7254
7267
  namespace CorePropertiesNamespace
7255
7268
 
7256
7269
  # Per-namespace declaration control
@@ -7467,7 +7480,7 @@ class Example < Lutaml::Model::Serializable
7467
7480
  attribute :name, :string
7468
7481
 
7469
7482
  xml do
7470
- root 'example'
7483
+ element "example"
7471
7484
  map_element 'name', to: :name
7472
7485
  end
7473
7486
  end
@@ -7499,7 +7512,7 @@ class RecordDate < Lutaml::Model::Serializable
7499
7512
  attribute :content, :string
7500
7513
 
7501
7514
  xml do
7502
- root "recordDate"
7515
+ element "recordDate"
7503
7516
  map_content to: :content
7504
7517
  end
7505
7518
  end
@@ -7508,7 +7521,7 @@ class OriginInfo < Lutaml::Model::Serializable
7508
7521
  attribute :date_issued, RecordDate, collection: true
7509
7522
 
7510
7523
  xml do
7511
- root "originInfo"
7524
+ element "originInfo"
7512
7525
  map_element "dateIssued", to: :date_issued
7513
7526
  end
7514
7527
  end
@@ -7732,7 +7745,7 @@ class Example < Lutaml::Model::Serializable
7732
7745
  attribute :value, :integer
7733
7746
 
7734
7747
  xml do
7735
- root 'example'
7748
+ element "example"
7736
7749
  map_attribute 'value', to: :value
7737
7750
  end
7738
7751
  end
@@ -7775,7 +7788,7 @@ class Attribute < Lutaml::Model::Serializable
7775
7788
  attribute :value, TechXmiIntegerType
7776
7789
 
7777
7790
  xml do
7778
- root 'example'
7791
+ element "example"
7779
7792
  map_attribute 'value', to: :value
7780
7793
  end
7781
7794
  end
@@ -7935,7 +7948,7 @@ class Example < Lutaml::Model::Serializable
7935
7948
  attribute :description, :string
7936
7949
 
7937
7950
  xml do
7938
- root 'example'
7951
+ element "example"
7939
7952
  map_content to: :description
7940
7953
  end
7941
7954
  end
@@ -8078,7 +8091,7 @@ class Example < Lutaml::Model::Serializable
8078
8091
  attribute :note, :string
8079
8092
 
8080
8093
  xml do
8081
- root 'example'
8094
+ element "example"
8082
8095
  map_element :name, to: :name, cdata: true
8083
8096
  map_content to: :description, cdata: true
8084
8097
  map_element :title, to: :title, cdata: false
@@ -8140,7 +8153,7 @@ class RfcDoc < Lutaml::Model::Serializable
8140
8153
  attribute :pi_settings, :hash
8141
8154
 
8142
8155
  xml do
8143
- root "rfc"
8156
+ element "rfc"
8144
8157
  map_element "title", to: :title
8145
8158
  map_processing_instruction "rfc", to: :pi_settings
8146
8159
  end
@@ -8174,7 +8187,7 @@ class RfcDoc < Lutaml::Model::Serializable
8174
8187
  attribute :rfc_pis, :string, collection: true
8175
8188
 
8176
8189
  xml do
8177
- root "rfc"
8190
+ element "rfc"
8178
8191
  map_element "title", to: :title
8179
8192
  map_processing_instruction "rfc", to: :rfc_pis
8180
8193
  end
@@ -8265,7 +8278,7 @@ class KilnCollection < Lutaml::Model::Serializable
8265
8278
  attribute :kiln, Kiln, collection: 1..2
8266
8279
 
8267
8280
  xml do
8268
- root "collection"
8281
+ element "collection"
8269
8282
  map_element "kiln", to: :kiln
8270
8283
  end
8271
8284
  end
@@ -8378,7 +8391,7 @@ class Ceramic < Lutaml::Model::Serializable
8378
8391
  attribute :color, :string
8379
8392
 
8380
8393
  xml do
8381
- root 'Ceramic'
8394
+ element "Ceramic"
8382
8395
  namespace 'http://example.com/ceramic', 'cera'
8383
8396
  map_element 'Type', to: :type, namespace: :inherit
8384
8397
  map_element 'Glaze', to: :glaze
@@ -8456,7 +8469,7 @@ class Ceramic < Lutaml::Model::Serializable
8456
8469
  attribute :temperature, :integer
8457
8470
 
8458
8471
  xml do
8459
- root 'ceramic'
8472
+ element "ceramic"
8460
8473
  map_element 'name', to: :name
8461
8474
  map_attribute 'temperature', to: :temperature
8462
8475
  map_content to: :description
@@ -8582,7 +8595,7 @@ class Contact < Lutaml::Model::Serializable
8582
8595
  attribute :email, EmailType
8583
8596
 
8584
8597
  xml do
8585
- root 'contact'
8598
+ element "contact"
8586
8599
  map_element 'email', to: :email # Uses EmailNamespace automatically
8587
8600
  end
8588
8601
  end
@@ -8670,7 +8683,7 @@ class Properties < Lutaml::Model::Serializable
8670
8683
  attribute :template, :string
8671
8684
 
8672
8685
  xml do
8673
- root "Properties"
8686
+ element "Properties"
8674
8687
  namespace AppNamespace
8675
8688
  map_element "Template", to: :template
8676
8689
  end
@@ -9226,7 +9239,7 @@ class DctermsCreatedType < Lutaml::Model::Serializable
9226
9239
  attribute :type, XsiTypeType
9227
9240
 
9228
9241
  xml do
9229
- root 'created'
9242
+ element "created"
9230
9243
  # This becomes xsi:type from XsiTypeType
9231
9244
  map_attribute 'type', to: :type
9232
9245
  map_content to: :value
@@ -9240,7 +9253,7 @@ class DctermsModifiedType < Lutaml::Model::Serializable
9240
9253
  attribute :type, XsiTypeType
9241
9254
 
9242
9255
  xml do
9243
- root 'modified'
9256
+ element "modified"
9244
9257
  map_attribute 'type', to: :type
9245
9258
  map_content to: :value
9246
9259
  end
@@ -9258,7 +9271,7 @@ class CoreProperties < Lutaml::Model::Serializable
9258
9271
  attribute :modified, DctermsModifiedType
9259
9272
 
9260
9273
  xml do
9261
- root 'coreProperties'
9274
+ element "coreProperties"
9262
9275
 
9263
9276
  # Type namespaces automatically applied
9264
9277
  map_element 'title', to: :title # Becomes <dc:title>
@@ -9351,7 +9364,7 @@ class Model < Lutaml::Model::Serializable
9351
9364
  attribute :value, DefaultType
9352
9365
 
9353
9366
  xml do
9354
- root 'model'
9367
+ element "model"
9355
9368
 
9356
9369
  # Case 1: Type namespace used (no explicit namespace)
9357
9370
  map_element 'value1', to: :value
@@ -9392,7 +9405,7 @@ class Product < Lutaml::Model::Serializable
9392
9405
  attribute :schema_type, XsiTypeType
9393
9406
 
9394
9407
  xml do
9395
- root 'product'
9408
+ element "product"
9396
9409
  map_attribute 'id', to: :id # Unqualified: id="..."
9397
9410
  map_attribute 'type', to: :schema_type # Qualified: xsi:type="..."
9398
9411
  end
@@ -9592,7 +9605,7 @@ class JapaneseCeramic < Lutaml::Model::Serializable
9592
9605
  attribute :description, :string
9593
9606
 
9594
9607
  xml do
9595
- root 'JapaneseCeramic'
9608
+ element "JapaneseCeramic"
9596
9609
  map_attribute 'glazeType', to: :glaze_type
9597
9610
  map_element 'description', to: :description
9598
9611
  end
@@ -9653,7 +9666,7 @@ class Ceramic < Lutaml::Model::Serializable
9653
9666
  attribute :temperature, :integer
9654
9667
 
9655
9668
  xml do
9656
- root 'ceramic'
9669
+ element "ceramic"
9657
9670
  map_element 'potter', to: :potter
9658
9671
  map_content to: :description
9659
9672
  end
@@ -9704,7 +9717,7 @@ class JapaneseCeramic < Lutaml::Model::Serializable
9704
9717
  attribute :description, :string
9705
9718
 
9706
9719
  xml do
9707
- root 'JapaneseCeramic'
9720
+ element "JapaneseCeramic"
9708
9721
  map_attribute 'glazeType', to: :glaze_type
9709
9722
  map_element 'description', to: :description
9710
9723
  end
@@ -10032,7 +10045,7 @@ class Settings < Lutaml::Model::Serializable
10032
10045
  attribute :chart_tracking, :boolean
10033
10046
 
10034
10047
  xml do
10035
- root "settings"
10048
+ element "settings"
10036
10049
  namespace WNamespace
10037
10050
  namespace_scope [W14Namespace, W15Namespace]
10038
10051
 
@@ -11868,7 +11881,7 @@ class JapaneseCeramic < Lutaml::Model::Serializable
11868
11881
  attribute :description, :string
11869
11882
 
11870
11883
  xml do
11871
- root 'JapaneseCeramic'
11884
+ element "JapaneseCeramic"
11872
11885
  map_attribute 'glazeType', to: :glaze_type
11873
11886
  map_element 'description', to: :description
11874
11887
  end
@@ -12029,7 +12042,7 @@ class Ceramic < Lutaml::Model::Serializable
12029
12042
 
12030
12043
  # Mapping-level transformation in XML format
12031
12044
  xml do
12032
- root "Ceramic"
12045
+ element "Ceramic"
12033
12046
  map_attribute "glaze-type", to: :glaze_type, transform: {
12034
12047
  export: ->(value) { "Traditional #{value}" },
12035
12048
  import: ->(value) { value.gsub("Traditional ", "") }
@@ -12137,7 +12150,7 @@ class Ceramic < Lutaml::Model::Serializable
12137
12150
 
12138
12151
  # Mapping-level transformation in XML format
12139
12152
  xml do
12140
- root "Ceramic"
12153
+ element "Ceramic"
12141
12154
  map_attribute "glaze-type", to: :glaze_type, transform: {
12142
12155
  export: ->(value) { "Traditional #{value}" },
12143
12156
  import: ->(value) { value.gsub("Traditional ", "") }
@@ -12357,7 +12370,7 @@ class CombinedTransformModel < Lutaml::Model::Serializable
12357
12370
  end
12358
12371
 
12359
12372
  xml do
12360
- root "CombinedTransformModel"
12373
+ element "CombinedTransformModel"
12361
12374
  map_element "title", to: :title, transform: SuffixTransformer
12362
12375
  end
12363
12376
  end
@@ -12565,7 +12578,7 @@ class Glaze < Lutaml::Model::Serializable
12565
12578
  attribute :firing_time, :integer, default: -> { 60 }
12566
12579
 
12567
12580
  xml do
12568
- root "glaze"
12581
+ element "glaze"
12569
12582
  map_element 'color', to: :color
12570
12583
  map_element 'opacity', to: :opacity, render_default: true
12571
12584
  map_attribute 'temperature', to: :temperature
@@ -12655,7 +12668,7 @@ class CustomModel < Lutaml::Model::Serializable
12655
12668
  end
12656
12669
 
12657
12670
  xml do
12658
- root "CustomModel"
12671
+ element "CustomModel"
12659
12672
  map_element ["name", "custom-name"], with: { to: :name_to_xml, from: :name_from_xml }
12660
12673
  map_element ["color", "shade"], with: { to: :color_to_xml, from: :color_from_xml }
12661
12674
  map_attribute ["id", "identifier"], to: :id
@@ -14397,7 +14410,7 @@ class SomeModel < Lutaml::Model::Serializable
14397
14410
  attribute :coll, :string, collection: true
14398
14411
 
14399
14412
  xml do
14400
- root "some-model"
14413
+ element "some-model"
14401
14414
  map_element 'collection', to: :coll, render_nil: :omit
14402
14415
  end
14403
14416
 
@@ -14436,7 +14449,7 @@ class SomeModel < Lutaml::Model::Serializable
14436
14449
  attribute :coll, :string, collection: true
14437
14450
 
14438
14451
  xml do
14439
- root "some-model"
14452
+ element "some-model"
14440
14453
  map_element 'collection', to: :coll, render_nil: :as_nil
14441
14454
  end
14442
14455
 
@@ -14478,7 +14491,7 @@ class SomeModel < Lutaml::Model::Serializable
14478
14491
  attribute :coll, :string, collection: true
14479
14492
 
14480
14493
  xml do
14481
- root "some-model"
14494
+ element "some-model"
14482
14495
  map_element 'collection', to: :coll, render_nil: :as_blank # <1>
14483
14496
  end
14484
14497
 
@@ -14575,7 +14588,7 @@ class SomeModel < Lutaml::Model::Serializable
14575
14588
  attribute :coll, :string, collection: true
14576
14589
 
14577
14590
  xml do
14578
- root "some-model"
14591
+ element "some-model"
14579
14592
  map_element 'collection', to: :coll, render_empty: :omit
14580
14593
  end
14581
14594
 
@@ -14612,7 +14625,7 @@ class SomeModel < Lutaml::Model::Serializable
14612
14625
  attribute :coll, :string, collection: true
14613
14626
 
14614
14627
  xml do
14615
- root "some-model"
14628
+ element "some-model"
14616
14629
  map_element 'collection', to: :coll, render_empty: :as_nil
14617
14630
  end
14618
14631
 
@@ -14654,7 +14667,7 @@ class SomeModel < Lutaml::Model::Serializable
14654
14667
  attribute :coll, :string, collection: true
14655
14668
 
14656
14669
  xml do
14657
- root "some-model"
14670
+ element "some-model"
14658
14671
  map_element 'collection', to: :coll, render_empty: :as_blank # <1>
14659
14672
  end
14660
14673
 
@@ -14698,7 +14711,7 @@ class Tag < Lutaml::Model::Serializable
14698
14711
  attribute :text, :string
14699
14712
 
14700
14713
  xml do
14701
- root "Tag"
14714
+ element "Tag"
14702
14715
 
14703
14716
  map_content to: :text
14704
14717
  end
@@ -14712,7 +14725,7 @@ class Tags < Lutaml::Model::Serializable
14712
14725
  attribute :tag, Tag, collection: true
14713
14726
 
14714
14727
  xml do
14715
- root "Tags"
14728
+ element "Tags"
14716
14729
 
14717
14730
  map_element "Tag", to: :tag
14718
14731
  end
@@ -14726,7 +14739,7 @@ class Post < Lutaml::Model::Serializable
14726
14739
  attribute :tags, Tags, collection: true
14727
14740
 
14728
14741
  xml do
14729
- root "Post"
14742
+ element "Post"
14730
14743
  map_element "Tags", to: :tags
14731
14744
  end
14732
14745