lutaml-model 0.7.1 → 0.7.7
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.
- checksums.yaml +4 -4
- data/.envrc +1 -0
- data/.github/workflows/dependent-tests.yml +4 -0
- data/.github/workflows/rake.yml +12 -0
- data/.github/workflows/release.yml +3 -0
- data/.gitignore +6 -1
- data/.irbrc +1 -0
- data/.pryrc +1 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +58 -84
- data/Gemfile +4 -1
- data/README.adoc +3115 -365
- data/RELEASE_NOTES.adoc +346 -0
- data/docs/custom_adapters.adoc +144 -0
- data/docs/custom_registers.adoc +228 -0
- data/docs/schema_generation.adoc +898 -0
- data/docs/schema_import.adoc +364 -0
- data/flake.lock +114 -0
- data/flake.nix +103 -0
- data/lib/lutaml/model/attribute.rb +242 -100
- data/lib/lutaml/model/choice.rb +30 -0
- data/lib/lutaml/model/collection.rb +212 -0
- data/lib/lutaml/model/comparable_model.rb +3 -3
- data/lib/lutaml/model/config.rb +71 -42
- data/lib/lutaml/model/constants.rb +2 -0
- data/lib/lutaml/model/error/element_count_out_of_range_error.rb +29 -0
- data/lib/lutaml/model/error/invalid_attribute_name_error.rb +15 -0
- data/lib/lutaml/model/error/invalid_attribute_options_error.rb +16 -0
- data/lib/lutaml/model/error/invalid_choice_range_error.rb +3 -5
- data/lib/lutaml/model/error/polymorphic_error.rb +7 -2
- data/lib/lutaml/model/error/register/not_registrable_class_error.rb +11 -0
- data/lib/lutaml/model/error/type/invalid_value_error.rb +5 -3
- data/lib/lutaml/model/error/type/max_bound_error.rb +20 -0
- data/lib/lutaml/model/error/type/max_length_error.rb +20 -0
- data/lib/lutaml/model/error/type/min_bound_error.rb +20 -0
- data/lib/lutaml/model/error/type/min_length_error.rb +20 -0
- data/lib/lutaml/model/error/type/pattern_not_matched_error.rb +18 -0
- data/lib/lutaml/model/error/validation_failed_error.rb +9 -0
- data/lib/lutaml/model/error.rb +10 -0
- data/lib/lutaml/model/errors.rb +36 -0
- data/lib/lutaml/model/format_registry.rb +44 -0
- data/lib/lutaml/model/global_register.rb +41 -0
- data/lib/lutaml/model/hash_adapter/document.rb +11 -0
- data/lib/lutaml/model/hash_adapter/mapping.rb +19 -0
- data/lib/lutaml/model/hash_adapter/mapping_rule.rb +9 -0
- data/lib/lutaml/model/hash_adapter/standard_adapter.rb +17 -0
- data/lib/lutaml/model/hash_adapter/transform.rb +8 -0
- data/lib/lutaml/model/hash_adapter.rb +21 -0
- data/lib/lutaml/model/json/document.rb +11 -0
- data/lib/lutaml/model/json/mapping.rb +19 -0
- data/lib/lutaml/model/json/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
- data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
- data/lib/lutaml/model/json/transform.rb +8 -0
- data/lib/lutaml/model/json.rb +21 -0
- data/lib/lutaml/model/jsonl/document.rb +14 -0
- data/lib/lutaml/model/jsonl/mapping.rb +19 -0
- data/lib/lutaml/model/jsonl/mapping_rule.rb +9 -0
- data/lib/lutaml/model/jsonl/standard_adapter.rb +33 -0
- data/lib/lutaml/model/jsonl/transform.rb +19 -0
- data/lib/lutaml/model/jsonl.rb +21 -0
- data/lib/lutaml/model/key_value_document.rb +28 -0
- data/lib/lutaml/model/mapping/key_value_mapping.rb +85 -13
- data/lib/lutaml/model/mapping/key_value_mapping_rule.rb +5 -0
- data/lib/lutaml/model/mapping/mapping.rb +13 -0
- data/lib/lutaml/model/mapping/mapping_rule.rb +15 -9
- data/lib/lutaml/model/register.rb +105 -0
- data/lib/lutaml/model/{toml_adapter.rb → registrable.rb} +1 -1
- data/lib/lutaml/model/schema/base_schema.rb +64 -0
- data/lib/lutaml/model/schema/decorators/attribute.rb +114 -0
- data/lib/lutaml/model/schema/decorators/choices.rb +31 -0
- data/lib/lutaml/model/schema/decorators/class_definition.rb +85 -0
- data/lib/lutaml/model/schema/decorators/definition_collection.rb +97 -0
- data/lib/lutaml/model/schema/generator/definition.rb +53 -0
- data/lib/lutaml/model/schema/generator/definitions_collection.rb +81 -0
- data/lib/lutaml/model/schema/generator/properties_collection.rb +63 -0
- data/lib/lutaml/model/schema/generator/property.rb +110 -0
- data/lib/lutaml/model/schema/generator/ref.rb +24 -0
- data/lib/lutaml/model/schema/helpers/template_helper.rb +49 -0
- data/lib/lutaml/model/schema/json_schema.rb +42 -49
- data/lib/lutaml/model/schema/relaxng_schema.rb +14 -10
- data/lib/lutaml/model/schema/renderer.rb +36 -0
- data/lib/lutaml/model/schema/shared_methods.rb +24 -0
- data/lib/lutaml/model/schema/templates/model.erb +9 -0
- data/lib/lutaml/model/schema/xml_compiler/attribute.rb +85 -0
- data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +45 -0
- data/lib/lutaml/model/schema/xml_compiler/choice.rb +65 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +27 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +34 -0
- data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +136 -0
- data/lib/lutaml/model/schema/xml_compiler/element.rb +104 -0
- data/lib/lutaml/model/schema/xml_compiler/group.rb +97 -0
- data/lib/lutaml/model/schema/xml_compiler/restriction.rb +101 -0
- data/lib/lutaml/model/schema/xml_compiler/sequence.rb +50 -0
- data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +36 -0
- data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +189 -0
- data/lib/lutaml/model/schema/xml_compiler.rb +231 -587
- data/lib/lutaml/model/schema/xsd_schema.rb +12 -8
- data/lib/lutaml/model/schema/yaml_schema.rb +41 -35
- data/lib/lutaml/model/schema.rb +1 -0
- data/lib/lutaml/model/sequence.rb +60 -30
- data/lib/lutaml/model/serialization_adapter.rb +22 -0
- data/lib/lutaml/model/serialize.rb +296 -548
- data/lib/lutaml/model/services/base.rb +11 -0
- data/lib/lutaml/model/services/logger.rb +54 -0
- data/lib/lutaml/model/services/rule_value_extractor.rb +92 -0
- data/lib/lutaml/model/services/transformer.rb +48 -0
- data/lib/lutaml/model/services/type/validator/number.rb +25 -0
- data/lib/lutaml/model/services/type/validator/string.rb +52 -0
- data/lib/lutaml/model/services/type/validator.rb +43 -0
- data/lib/lutaml/model/services/validator.rb +145 -0
- data/lib/lutaml/model/services.rb +5 -0
- data/lib/lutaml/model/toml/document.rb +11 -0
- data/lib/lutaml/model/toml/mapping.rb +27 -0
- data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
- data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
- data/lib/lutaml/model/toml/transform.rb +8 -0
- data/lib/lutaml/model/toml.rb +30 -0
- data/lib/lutaml/model/transform/key_value_transform.rb +297 -0
- data/lib/lutaml/model/transform/xml_transform.rb +228 -0
- data/lib/lutaml/model/transform.rb +93 -0
- data/lib/lutaml/model/type/boolean.rb +1 -1
- data/lib/lutaml/model/type/date.rb +1 -1
- data/lib/lutaml/model/type/date_time.rb +1 -1
- data/lib/lutaml/model/type/decimal.rb +11 -9
- data/lib/lutaml/model/type/float.rb +2 -1
- data/lib/lutaml/model/type/integer.rb +24 -21
- data/lib/lutaml/model/type/string.rb +4 -2
- data/lib/lutaml/model/type/time.rb +1 -1
- data/lib/lutaml/model/type/time_without_date.rb +1 -1
- data/lib/lutaml/model/type/value.rb +11 -10
- data/lib/lutaml/model/type.rb +5 -2
- data/lib/lutaml/model/uninitialized_class.rb +1 -1
- data/lib/lutaml/model/utils.rb +56 -4
- data/lib/lutaml/model/validation.rb +6 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
- data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
- data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
- data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +42 -25
- data/lib/lutaml/model/xml/element.rb +32 -0
- data/lib/lutaml/model/xml/mapping.rb +471 -0
- data/lib/lutaml/model/xml/mapping_rule.rb +149 -0
- data/lib/lutaml/model/xml/nokogiri_adapter.rb +234 -0
- data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +7 -2
- data/lib/lutaml/model/xml/oga_adapter.rb +172 -0
- data/lib/lutaml/model/xml/ox_adapter.rb +229 -0
- data/lib/lutaml/model/xml/transform.rb +8 -0
- data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
- data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +9 -31
- data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
- data/lib/lutaml/model/xml.rb +31 -0
- data/lib/lutaml/model/xml_adapter/element.rb +11 -25
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
- data/lib/lutaml/model/yaml/document.rb +10 -0
- data/lib/lutaml/model/yaml/mapping.rb +19 -0
- data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
- data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
- data/lib/lutaml/model/yaml/transform.rb +8 -0
- data/lib/lutaml/model/yaml.rb +21 -0
- data/lib/lutaml/model/yamls/document.rb +14 -0
- data/lib/lutaml/model/yamls/mapping.rb +19 -0
- data/lib/lutaml/model/yamls/mapping_rule.rb +9 -0
- data/lib/lutaml/model/yamls/standard_adapter.rb +34 -0
- data/lib/lutaml/model/yamls/transform.rb +19 -0
- data/lib/lutaml/model/yamls.rb +21 -0
- data/lib/lutaml/model.rb +15 -4
- data/lutaml-model.gemspec +0 -4
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +5 -6
- data/spec/fixtures/xml/advanced_test_schema.xsd +134 -0
- data/spec/fixtures/xml/examples/nested_categories.xml +55 -0
- data/spec/fixtures/xml/examples/valid_catalog.xml +43 -0
- data/spec/fixtures/xml/product_catalog.xsd +151 -0
- data/spec/fixtures/xml/specifications_schema.xsd +38 -0
- data/spec/lutaml/model/attribute_collection_spec.rb +101 -0
- data/spec/lutaml/model/attribute_spec.rb +41 -44
- data/spec/lutaml/model/cdata_spec.rb +7 -7
- data/spec/lutaml/model/choice_spec.rb +44 -0
- data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
- data/spec/lutaml/model/custom_collection_spec.rb +830 -0
- data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
- data/spec/lutaml/model/global_register_spec.rb +108 -0
- data/spec/lutaml/model/group_spec.rb +27 -10
- data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
- data/spec/lutaml/model/json_adapter_spec.rb +6 -6
- data/spec/lutaml/model/jsonl/standard_adapter_spec.rb +91 -0
- data/spec/lutaml/model/jsonl_spec.rb +229 -0
- data/spec/lutaml/model/key_value_mapping_spec.rb +25 -1
- data/spec/lutaml/model/mixed_content_spec.rb +24 -24
- data/spec/lutaml/model/multiple_mapping_spec.rb +6 -6
- data/spec/lutaml/model/ordered_content_spec.rb +6 -6
- data/spec/lutaml/model/polymorphic_spec.rb +178 -0
- data/spec/lutaml/model/register/key_value_spec.rb +275 -0
- data/spec/lutaml/model/register/xml_spec.rb +185 -0
- data/spec/lutaml/model/register_spec.rb +147 -0
- data/spec/lutaml/model/root_mappings_spec.rb +3 -3
- data/spec/lutaml/model/rule_value_extractor_spec.rb +162 -0
- data/spec/lutaml/model/schema/generator/definitions_collection_spec.rb +120 -0
- data/spec/lutaml/model/schema/json_schema_spec.rb +412 -51
- data/spec/lutaml/model/schema/json_schema_to_models_spec.rb +383 -0
- data/spec/lutaml/model/schema/xml_compiler/attribute_group_spec.rb +65 -0
- data/spec/lutaml/model/schema/xml_compiler/attribute_spec.rb +63 -0
- data/spec/lutaml/model/schema/xml_compiler/choice_spec.rb +71 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_content_restriction_spec.rb +55 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_content_spec.rb +37 -0
- data/spec/lutaml/model/schema/xml_compiler/complex_type_spec.rb +173 -0
- data/spec/lutaml/model/schema/xml_compiler/element_spec.rb +63 -0
- data/spec/lutaml/model/schema/xml_compiler/group_spec.rb +86 -0
- data/spec/lutaml/model/schema/xml_compiler/restriction_spec.rb +76 -0
- data/spec/lutaml/model/schema/xml_compiler/sequence_spec.rb +59 -0
- data/spec/lutaml/model/schema/xml_compiler/simple_content_spec.rb +55 -0
- data/spec/lutaml/model/schema/xml_compiler/simple_type_spec.rb +181 -0
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +503 -1804
- data/spec/lutaml/model/schema/yaml_schema_spec.rb +249 -26
- data/spec/lutaml/model/sequence_spec.rb +36 -0
- data/spec/lutaml/model/serializable_spec.rb +201 -94
- data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
- data/spec/lutaml/model/toml_spec.rb +51 -0
- data/spec/lutaml/model/transformation_spec.rb +72 -15
- data/spec/lutaml/model/type_spec.rb +8 -4
- data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
- data/spec/lutaml/model/utils_spec.rb +3 -3
- data/spec/lutaml/model/xml/derived_attributes_spec.rb +1 -1
- data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
- data/spec/lutaml/model/xml/root_mappings/nested_child_mappings_spec.rb +217 -0
- data/spec/lutaml/model/xml/xml_element_spec.rb +7 -1
- data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
- data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +12 -12
- data/spec/lutaml/model/xml_adapter_spec.rb +30 -6
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +14 -7
- data/spec/lutaml/model/xml_mapping_spec.rb +27 -15
- data/spec/lutaml/model/xml_spec.rb +63 -0
- data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
- data/spec/lutaml/model/yamls/standard_adapter_spec.rb +183 -0
- data/spec/lutaml/model/yamls_spec.rb +294 -0
- data/spec/spec_helper.rb +4 -3
- metadata +162 -60
- data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
- data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
- data/lib/lutaml/model/loggable.rb +0 -15
- data/lib/lutaml/model/mapping/json_mapping.rb +0 -17
- data/lib/lutaml/model/mapping/toml_mapping.rb +0 -25
- data/lib/lutaml/model/mapping/xml_mapping.rb +0 -389
- data/lib/lutaml/model/mapping/xml_mapping_rule.rb +0 -139
- data/lib/lutaml/model/mapping/yaml_mapping.rb +0 -17
- data/lib/lutaml/model/mapping.rb +0 -14
- data/lib/lutaml/model/schema/templates/simple_type.rb +0 -247
- data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
- data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
- data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
- data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
- data/lib/lutaml/model/yaml_adapter.rb +0 -8
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<ProductCatalog version="1.0" lastUpdated="2024-03-20T10:00:00+00:00">
|
|
3
|
+
<categories>
|
|
4
|
+
<category>
|
|
5
|
+
<id>1</id>
|
|
6
|
+
<name>Electronics</name>
|
|
7
|
+
<parentCategory>0</parentCategory>
|
|
8
|
+
<description>Electronic devices and accessories</description>
|
|
9
|
+
</category>
|
|
10
|
+
<category>
|
|
11
|
+
<id>2</id>
|
|
12
|
+
<name>Smartphones</name>
|
|
13
|
+
<parentCategory>1</parentCategory>
|
|
14
|
+
<description>Mobile phones and accessories</description>
|
|
15
|
+
</category>
|
|
16
|
+
<category>
|
|
17
|
+
<id>3</id>
|
|
18
|
+
<name>Laptops</name>
|
|
19
|
+
<parentCategory>1</parentCategory>
|
|
20
|
+
<description>Portable computers and accessories</description>
|
|
21
|
+
</category>
|
|
22
|
+
</categories>
|
|
23
|
+
<products>
|
|
24
|
+
<product id="1" status="active">
|
|
25
|
+
<sku>PHN12345678</sku>
|
|
26
|
+
<name>Smartphone Pro</name>
|
|
27
|
+
<description>Latest smartphone model</description>
|
|
28
|
+
<category>
|
|
29
|
+
<id>2</id>
|
|
30
|
+
<name>Smartphones</name>
|
|
31
|
+
<parentCategory>1</parentCategory>
|
|
32
|
+
<description>Mobile phones and accessories</description>
|
|
33
|
+
</category>
|
|
34
|
+
<price>99.99</price>
|
|
35
|
+
<salePrice>89.99</salePrice>
|
|
36
|
+
<inventory>50</inventory>
|
|
37
|
+
<dimensions>
|
|
38
|
+
<length>14.5</length>
|
|
39
|
+
<width>7.0</width>
|
|
40
|
+
<height>0.7</height>
|
|
41
|
+
<weight>0.18</weight>
|
|
42
|
+
</dimensions>
|
|
43
|
+
<rating>4.5</rating>
|
|
44
|
+
<features>
|
|
45
|
+
<feature>5G Connectivity</feature>
|
|
46
|
+
<feature>128GB Storage</feature>
|
|
47
|
+
<feature>Triple Camera System</feature>
|
|
48
|
+
</features>
|
|
49
|
+
<images>
|
|
50
|
+
<image url="https://example.com/images/smartphone-pro-1.jpg" alt="Smartphone Pro Front View" isPrimary="true"/>
|
|
51
|
+
<image url="https://example.com/images/smartphone-pro-2.jpg" alt="Smartphone Pro Back View"/>
|
|
52
|
+
</images>
|
|
53
|
+
</product>
|
|
54
|
+
</products>
|
|
55
|
+
</ProductCatalog>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<ProductCatalog version="1.0" lastUpdated="2024-03-20T10:00:00+00:00">
|
|
3
|
+
<categories>
|
|
4
|
+
<category>
|
|
5
|
+
<id>1</id>
|
|
6
|
+
<name>Electronics</name>
|
|
7
|
+
<parentCategory>0</parentCategory>
|
|
8
|
+
<description>Electronic devices and accessories</description>
|
|
9
|
+
</category>
|
|
10
|
+
</categories>
|
|
11
|
+
<products>
|
|
12
|
+
<product id="1" status="active">
|
|
13
|
+
<sku>ABC12345678</sku>
|
|
14
|
+
<name>Smartphone X</name>
|
|
15
|
+
<description>A high-end smartphone with advanced features</description>
|
|
16
|
+
<category>
|
|
17
|
+
<id>1</id>
|
|
18
|
+
<name>Electronics</name>
|
|
19
|
+
<parentCategory>0</parentCategory>
|
|
20
|
+
<description>Electronic devices and accessories</description>
|
|
21
|
+
</category>
|
|
22
|
+
<price>99.99</price>
|
|
23
|
+
<salePrice>89.99</salePrice>
|
|
24
|
+
<inventory>100</inventory>
|
|
25
|
+
<dimensions>
|
|
26
|
+
<length>15.0</length>
|
|
27
|
+
<width>7.5</width>
|
|
28
|
+
<height>0.8</height>
|
|
29
|
+
<weight>0.2</weight>
|
|
30
|
+
</dimensions>
|
|
31
|
+
<rating>4.5</rating>
|
|
32
|
+
<features>
|
|
33
|
+
<feature>5G Connectivity</feature>
|
|
34
|
+
<feature>128GB Storage</feature>
|
|
35
|
+
<feature>Triple Camera System</feature>
|
|
36
|
+
</features>
|
|
37
|
+
<images>
|
|
38
|
+
<image url="https://example.com/images/smartphone-x-1.jpg" alt="Smartphone X Front View" isPrimary="true"/>
|
|
39
|
+
<image url="https://example.com/images/smartphone-x-2.jpg" alt="Smartphone X Back View"/>
|
|
40
|
+
</images>
|
|
41
|
+
</product>
|
|
42
|
+
</products>
|
|
43
|
+
</ProductCatalog>
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
3
|
+
xmlns:cat="http://www.example.com/catalog" targetNamespace="http://www.example.com/catalog" elementFormDefault="qualified">
|
|
4
|
+
|
|
5
|
+
<!-- Attributes -->
|
|
6
|
+
<xs:attribute name="id" type="xs:integer" use="required"/>
|
|
7
|
+
|
|
8
|
+
<!-- Simple Types -->
|
|
9
|
+
<xs:simpleType name="SKUType">
|
|
10
|
+
<xs:annotation>
|
|
11
|
+
<xs:documentation>Stock Keeping Unit - must be 8-12 alphanumeric characters</xs:documentation>
|
|
12
|
+
</xs:annotation>
|
|
13
|
+
<xs:restriction base="xs:string">
|
|
14
|
+
<xs:pattern value="[A-Z0-9]{8,12}"/>
|
|
15
|
+
</xs:restriction>
|
|
16
|
+
</xs:simpleType>
|
|
17
|
+
|
|
18
|
+
<xs:simpleType name="PriceType">
|
|
19
|
+
<xs:annotation>
|
|
20
|
+
<xs:documentation>Price with 2 decimal places, must be positive</xs:documentation>
|
|
21
|
+
</xs:annotation>
|
|
22
|
+
<xs:restriction base="xs:decimal">
|
|
23
|
+
<xs:maxExclusive value="101.00"/>
|
|
24
|
+
<xs:minInclusive value="0.01"/>
|
|
25
|
+
</xs:restriction>
|
|
26
|
+
</xs:simpleType>
|
|
27
|
+
|
|
28
|
+
<xs:simpleType name="QuantityTypes">
|
|
29
|
+
<xs:annotation>
|
|
30
|
+
<xs:documentation>Quantity must be non-negative</xs:documentation>
|
|
31
|
+
</xs:annotation>
|
|
32
|
+
<xs:restriction base="xs:integer">
|
|
33
|
+
<xs:minInclusive value="0"/>
|
|
34
|
+
</xs:restriction>
|
|
35
|
+
</xs:simpleType>
|
|
36
|
+
|
|
37
|
+
<xs:simpleType name="RatingType">
|
|
38
|
+
<xs:annotation>
|
|
39
|
+
<xs:documentation>Product rating from 1 to 5</xs:documentation>
|
|
40
|
+
</xs:annotation>
|
|
41
|
+
<xs:restriction base="xs:decimal">
|
|
42
|
+
<xs:minInclusive value="1"/>
|
|
43
|
+
<xs:maxInclusive value="5"/>
|
|
44
|
+
</xs:restriction>
|
|
45
|
+
</xs:simpleType>
|
|
46
|
+
|
|
47
|
+
<!-- Complex Types -->
|
|
48
|
+
<xs:complexType name="DimensionsType">
|
|
49
|
+
<xs:sequence>
|
|
50
|
+
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
|
51
|
+
<xs:choice maxOccurs="unbounded">
|
|
52
|
+
<xs:element name="length" type="xs:decimal">
|
|
53
|
+
<xs:annotation>
|
|
54
|
+
<xs:documentation>Length in centimeters</xs:documentation>
|
|
55
|
+
</xs:annotation>
|
|
56
|
+
</xs:element>
|
|
57
|
+
</xs:choice>
|
|
58
|
+
<xs:element name="width" type="xs:decimal">
|
|
59
|
+
<xs:annotation>
|
|
60
|
+
<xs:documentation>Width in centimeters</xs:documentation>
|
|
61
|
+
</xs:annotation>
|
|
62
|
+
</xs:element>
|
|
63
|
+
</xs:choice>
|
|
64
|
+
<xs:element name="height" type="xs:decimal">
|
|
65
|
+
<xs:annotation>
|
|
66
|
+
<xs:documentation>Height in centimeters</xs:documentation>
|
|
67
|
+
</xs:annotation>
|
|
68
|
+
</xs:element>
|
|
69
|
+
<xs:element name="weight" type="xs:decimal">
|
|
70
|
+
<xs:annotation>
|
|
71
|
+
<xs:documentation>Weight in kilograms</xs:documentation>
|
|
72
|
+
</xs:annotation>
|
|
73
|
+
</xs:element>
|
|
74
|
+
</xs:sequence>
|
|
75
|
+
</xs:complexType>
|
|
76
|
+
|
|
77
|
+
<xs:complexType name="CategoryType">
|
|
78
|
+
<xs:sequence>
|
|
79
|
+
<xs:element name="id" type="xs:integer"/>
|
|
80
|
+
<xs:element name="name" type="xs:string"/>
|
|
81
|
+
<xs:element name="parentCategory" type="xs:integer" minOccurs="0"/>
|
|
82
|
+
<xs:element name="description" type="xs:string" minOccurs="0"/>
|
|
83
|
+
</xs:sequence>
|
|
84
|
+
</xs:complexType>
|
|
85
|
+
|
|
86
|
+
<xs:complexType name="ProductType">
|
|
87
|
+
<xs:sequence>
|
|
88
|
+
<xs:element name="sku" type="cat:SKUType"/>
|
|
89
|
+
<xs:element name="name" type="xs:string"/>
|
|
90
|
+
<xs:element name="description" type="xs:string"/>
|
|
91
|
+
<xs:element name="category" type="cat:CategoryType"/>
|
|
92
|
+
<xs:element name="price" type="cat:PriceType"/>
|
|
93
|
+
<xs:element name="salePrice" type="cat:PriceType" minOccurs="0"/>
|
|
94
|
+
<xs:element name="inventory" type="cat:QuantityTypes"/>
|
|
95
|
+
<xs:element name="dimensions" type="cat:DimensionsType"/>
|
|
96
|
+
<xs:element name="rating" type="cat:RatingType" minOccurs="0"/>
|
|
97
|
+
<xs:element name="features" minOccurs="0">
|
|
98
|
+
<xs:complexType>
|
|
99
|
+
<xs:sequence>
|
|
100
|
+
<xs:element name="feature" type="xs:string" maxOccurs="unbounded"/>
|
|
101
|
+
</xs:sequence>
|
|
102
|
+
</xs:complexType>
|
|
103
|
+
</xs:element>
|
|
104
|
+
<xs:element name="images" minOccurs="0">
|
|
105
|
+
<xs:complexType>
|
|
106
|
+
<xs:sequence>
|
|
107
|
+
<xs:element name="image" maxOccurs="unbounded">
|
|
108
|
+
<xs:complexType>
|
|
109
|
+
<xs:attribute name="url" type="xs:anyURI" use="required"/>
|
|
110
|
+
<xs:attribute name="alt" type="xs:string" use="required"/>
|
|
111
|
+
<xs:attribute name="isPrimary" type="xs:boolean" default="false"/>
|
|
112
|
+
</xs:complexType>
|
|
113
|
+
</xs:element>
|
|
114
|
+
</xs:sequence>
|
|
115
|
+
</xs:complexType>
|
|
116
|
+
</xs:element>
|
|
117
|
+
</xs:sequence>
|
|
118
|
+
<!-- using 'ref' for development purposes only -->
|
|
119
|
+
<xs:attribute ref="id"/>
|
|
120
|
+
<xs:attribute name="status" use="required">
|
|
121
|
+
<xs:simpleType>
|
|
122
|
+
<xs:restriction base="xs:string">
|
|
123
|
+
<xs:enumeration value="active"/>
|
|
124
|
+
<xs:enumeration value="inactive"/>
|
|
125
|
+
<xs:enumeration value="discontinued"/>
|
|
126
|
+
</xs:restriction>
|
|
127
|
+
</xs:simpleType>
|
|
128
|
+
</xs:attribute>
|
|
129
|
+
</xs:complexType>
|
|
130
|
+
|
|
131
|
+
<xs:complexType name="ProductCatalog" mixed="true">
|
|
132
|
+
<xs:sequence>
|
|
133
|
+
<xs:element name="categories">
|
|
134
|
+
<xs:complexType>
|
|
135
|
+
<xs:sequence>
|
|
136
|
+
<xs:element name="category" type="cat:CategoryType" maxOccurs="unbounded"/>
|
|
137
|
+
</xs:sequence>
|
|
138
|
+
</xs:complexType>
|
|
139
|
+
</xs:element>
|
|
140
|
+
<xs:element name="products">
|
|
141
|
+
<xs:complexType>
|
|
142
|
+
<xs:sequence>
|
|
143
|
+
<xs:element name="product" type="cat:ProductType" maxOccurs="unbounded"/>
|
|
144
|
+
</xs:sequence>
|
|
145
|
+
</xs:complexType>
|
|
146
|
+
</xs:element>
|
|
147
|
+
</xs:sequence>
|
|
148
|
+
<xs:attribute name="version" type="xs:string" use="required"/>
|
|
149
|
+
<xs:attribute name="lastUpdated" type="xs:dateTime" use="required"/>
|
|
150
|
+
</xs:complexType>
|
|
151
|
+
</xs:schema>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example.com/specs"
|
|
3
|
+
xmlns="http://example.com/specs" elementFormDefault="qualified">
|
|
4
|
+
<!-- ComplexType SpecBase and ShortSpec are root elements -->
|
|
5
|
+
|
|
6
|
+
<!-- Base type for a specification -->
|
|
7
|
+
<xs:complexType name="spec">
|
|
8
|
+
<xs:sequence>
|
|
9
|
+
<xs:element name="title" type="xs:string"/>
|
|
10
|
+
<xs:element name="version" type="xs:string"/>
|
|
11
|
+
<xs:element name="status" type="status" minOccurs="0" default="draft"/>
|
|
12
|
+
</xs:sequence>
|
|
13
|
+
<xs:attribute name="id" type="xs:ID" use="required"/>
|
|
14
|
+
</xs:complexType>
|
|
15
|
+
|
|
16
|
+
<!-- Restriction: A "ShortSpec" only allows title and version, not status -->
|
|
17
|
+
<xs:complexType name="shortSpec">
|
|
18
|
+
<xs:complexContent>
|
|
19
|
+
<xs:restriction base="spec">
|
|
20
|
+
<xs:sequence>
|
|
21
|
+
<xs:element name="title" type="xs:string"/>
|
|
22
|
+
<xs:element name="version" type="xs:string"/>
|
|
23
|
+
<xs:element name="status" type="status" minOccurs="0" maxOccurs="2"/>
|
|
24
|
+
</xs:sequence>
|
|
25
|
+
<xs:attribute name="id" type="xs:ID" use="required"/>
|
|
26
|
+
</xs:restriction>
|
|
27
|
+
</xs:complexContent>
|
|
28
|
+
</xs:complexType>
|
|
29
|
+
|
|
30
|
+
<!-- Enumeration for status -->
|
|
31
|
+
<xs:simpleType name="status">
|
|
32
|
+
<xs:restriction base="xs:string">
|
|
33
|
+
<xs:enumeration value="draft"/>
|
|
34
|
+
<xs:enumeration value="final"/>
|
|
35
|
+
<xs:enumeration value="archived"/>
|
|
36
|
+
</xs:restriction>
|
|
37
|
+
</xs:simpleType>
|
|
38
|
+
</xs:schema>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "lutaml/model"
|
|
3
|
+
|
|
4
|
+
module AttributeCollection
|
|
5
|
+
class StringParts < Lutaml::Model::Collection
|
|
6
|
+
instances :parts, :string
|
|
7
|
+
|
|
8
|
+
def to_s
|
|
9
|
+
parts.join(" -- ")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class BibliographicItem < Lutaml::Model::Serializable
|
|
14
|
+
attribute :title_parts, :string, collection: StringParts
|
|
15
|
+
|
|
16
|
+
xml do
|
|
17
|
+
root "titles"
|
|
18
|
+
map_element "title", to: :title_parts
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
key_value do
|
|
22
|
+
root "titles"
|
|
23
|
+
map_instances to: :title_parts
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def render_title
|
|
27
|
+
title_parts.to_s
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
RSpec.describe AttributeCollection do
|
|
33
|
+
let(:xml_data) do
|
|
34
|
+
<<~XML
|
|
35
|
+
<titles>
|
|
36
|
+
<title>Title One</title>
|
|
37
|
+
<title>Title Two</title>
|
|
38
|
+
<title>Title Three</title>
|
|
39
|
+
</titles>
|
|
40
|
+
XML
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
let(:yaml_data) do
|
|
44
|
+
<<~YAML
|
|
45
|
+
---
|
|
46
|
+
titles:
|
|
47
|
+
- Title One
|
|
48
|
+
- Title Two
|
|
49
|
+
- Title Three
|
|
50
|
+
YAML
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "BibliographicItem with custom collection" do
|
|
54
|
+
let(:bib_item) { AttributeCollection::BibliographicItem.from_xml(xml_data) }
|
|
55
|
+
|
|
56
|
+
it "initializes with custom collection class" do
|
|
57
|
+
expect(bib_item.title_parts).to be_a(AttributeCollection::StringParts)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "contains the correct number of title parts" do
|
|
61
|
+
expect(bib_item.title_parts.count).to eq(3)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "contains the correct title parts" do
|
|
65
|
+
expect(bib_item.title_parts.parts).to eq(["Title One", "Title Two", "Title Three"])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "renders title with custom separator" do
|
|
69
|
+
expect(bib_item.render_title).to eq("Title One -- Title Two -- Title Three")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "serializes to XML correctly" do
|
|
73
|
+
expect(bib_item.to_xml.strip).to eq(xml_data.strip)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "deserializes from YAML correctly" do
|
|
77
|
+
yaml_bib_item = AttributeCollection::BibliographicItem.from_yaml(yaml_data)
|
|
78
|
+
expect(yaml_bib_item.title_parts.parts).to eq(["Title One", "Title Two", "Title Three"])
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "serializes to YAML correctly" do
|
|
82
|
+
expect(bib_item.to_yaml.strip).to eq(yaml_data.strip)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "can be initialized with an array of strings" do
|
|
86
|
+
bib_item = AttributeCollection::BibliographicItem.new(
|
|
87
|
+
title_parts: AttributeCollection::StringParts.new(
|
|
88
|
+
["Part One", "Part Two"],
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
expect(bib_item.title_parts.parts).to eq(["Part One", "Part Two"])
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "can be initialized with a custom collection instance" do
|
|
96
|
+
collection = AttributeCollection::StringParts.new(["Custom One", "Custom Two"])
|
|
97
|
+
bib_item = AttributeCollection::BibliographicItem.new(title_parts: collection)
|
|
98
|
+
expect(bib_item.title_parts.parts).to eq(["Custom One", "Custom Two"])
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -15,6 +15,7 @@ RSpec.describe Lutaml::Model::Attribute do
|
|
|
15
15
|
Class.new(Lutaml::Model::Serializable) do
|
|
16
16
|
attribute :age, :integer
|
|
17
17
|
attribute :image, :string
|
|
18
|
+
restrict :image, collection: 1..., pattern: /.*\.\w+$/
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -44,6 +45,45 @@ RSpec.describe Lutaml::Model::Attribute do
|
|
|
44
45
|
)
|
|
45
46
|
end
|
|
46
47
|
|
|
48
|
+
describe "#validate_name!" do
|
|
49
|
+
Lutaml::Model::Serializable.instance_methods.each do |method|
|
|
50
|
+
if Lutaml::Model::Attribute::ALLOW_OVERRIDING.include?(method)
|
|
51
|
+
before do
|
|
52
|
+
allow(Lutaml::Model::Logger).to receive(:warn)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "does not raise an error when method is `#{method}`" do
|
|
56
|
+
expect do
|
|
57
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
58
|
+
attribute method, :string
|
|
59
|
+
end
|
|
60
|
+
end.not_to raise_error
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "logs a warning, when method is `#{method}`" do
|
|
64
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
65
|
+
attribute method, :string
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
expect(Lutaml::Model::Logger)
|
|
69
|
+
.to have_received(:warn)
|
|
70
|
+
.with("Attribute name `#{method}` conflicts with a built-in method")
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
it "raise exception, when method is `#{method}`" do
|
|
74
|
+
expect do
|
|
75
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
76
|
+
attribute method, :string
|
|
77
|
+
end
|
|
78
|
+
end.to raise_error(
|
|
79
|
+
Lutaml::Model::InvalidAttributeNameError,
|
|
80
|
+
"Attribute name '#{method}' is not allowed",
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
47
87
|
describe "#validate_options!" do
|
|
48
88
|
let(:validate_options) { name_attr.method(:validate_options!) }
|
|
49
89
|
|
|
@@ -56,7 +96,7 @@ RSpec.describe Lutaml::Model::Attribute do
|
|
|
56
96
|
it "raise exception if option is not allowed" do
|
|
57
97
|
expect do
|
|
58
98
|
validate_options.call({ foo: "bar" })
|
|
59
|
-
end.to raise_error(
|
|
99
|
+
end.to raise_error(Lutaml::Model::InvalidAttributeOptionsError, "Invalid options given for `name` [:foo]")
|
|
60
100
|
end
|
|
61
101
|
|
|
62
102
|
it "raise exception if pattern is given with non string type" do
|
|
@@ -71,49 +111,6 @@ RSpec.describe Lutaml::Model::Attribute do
|
|
|
71
111
|
end
|
|
72
112
|
end
|
|
73
113
|
|
|
74
|
-
describe "#validate_type!" do
|
|
75
|
-
let(:validate_type) { name_attr.method(:validate_type!) }
|
|
76
|
-
|
|
77
|
-
it "return true if type is a class" do
|
|
78
|
-
expect(validate_type.call(TestRecord)).to be(true)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it "return true if type is a valid symbol" do
|
|
82
|
-
expect(validate_type.call(:string)).to be(true)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "return true if type is a valid string" do
|
|
86
|
-
expect(validate_type.call("String")).to be(true)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "raise exception if type is invalid symbol" do
|
|
90
|
-
expect do
|
|
91
|
-
validate_type.call(:foo)
|
|
92
|
-
end.to raise_error(StandardError, "Unknown Lutaml::Model::Type: foo")
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it "raise exception if type is invalid string" do
|
|
96
|
-
expect do
|
|
97
|
-
validate_type.call("foo")
|
|
98
|
-
end.to raise_error(StandardError, "Unknown Lutaml::Model::Type: foo")
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
describe "#cast_type!" do
|
|
103
|
-
it "cast :string to Lutaml::Model::Type::String" do
|
|
104
|
-
expect(name_attr.cast_type!(:string)).to eq(Lutaml::Model::Type::String)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
it "cast :integer to Lutaml::Model::Type::Integer" do
|
|
108
|
-
expect(name_attr.cast_type!(:integer)).to eq(Lutaml::Model::Type::Integer)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
it "raises ArgumentError on unknown type" do
|
|
112
|
-
expect { name_attr.cast_type!(:foobar) }
|
|
113
|
-
.to raise_error(ArgumentError, "Unknown Lutaml::Model::Type: foobar")
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
114
|
describe "#derived?" do
|
|
118
115
|
context "when type is set" do
|
|
119
116
|
let(:attribute) { described_class.new("name", :string) }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
require "lutaml/model"
|
|
3
|
-
require "lutaml/model/
|
|
4
|
-
require "lutaml/model/
|
|
3
|
+
require "lutaml/model/xml/nokogiri_adapter"
|
|
4
|
+
require "lutaml/model/xml/ox_adapter"
|
|
5
5
|
|
|
6
6
|
module CDATA
|
|
7
7
|
class Beta < Lutaml::Model::Serializable
|
|
@@ -350,7 +350,7 @@ RSpec.describe "CDATA" do
|
|
|
350
350
|
instance = parent_mapper.from_xml(input_xml)
|
|
351
351
|
result_xml = parent_mapper.to_xml(instance)
|
|
352
352
|
|
|
353
|
-
expected_output = adapter_class == Lutaml::Model::
|
|
353
|
+
expected_output = adapter_class == Lutaml::Model::Xml::OxAdapter ? expected_ox_xml : expected_nokogiri_xml
|
|
354
354
|
|
|
355
355
|
expect(result_xml.strip).to eq(expected_output.strip)
|
|
356
356
|
end
|
|
@@ -439,7 +439,7 @@ RSpec.describe "CDATA" do
|
|
|
439
439
|
|
|
440
440
|
# due to the difference in capturing
|
|
441
441
|
# newlines in ox and nokogiri adapters
|
|
442
|
-
if adapter_class == Lutaml::Model::
|
|
442
|
+
if adapter_class == Lutaml::Model::Xml::OxAdapter
|
|
443
443
|
expected_xml = expected_ox_xml
|
|
444
444
|
end
|
|
445
445
|
|
|
@@ -496,7 +496,7 @@ RSpec.describe "CDATA" do
|
|
|
496
496
|
|
|
497
497
|
# due to the difference in capturing
|
|
498
498
|
# newlines in ox and nokogiri adapters
|
|
499
|
-
if adapter_class == Lutaml::Model::
|
|
499
|
+
if adapter_class == Lutaml::Model::Xml::OxAdapter
|
|
500
500
|
expected_xml = expected_ox_xml
|
|
501
501
|
end
|
|
502
502
|
|
|
@@ -509,11 +509,11 @@ RSpec.describe "CDATA" do
|
|
|
509
509
|
end
|
|
510
510
|
end
|
|
511
511
|
|
|
512
|
-
describe Lutaml::Model::
|
|
512
|
+
describe Lutaml::Model::Xml::NokogiriAdapter do
|
|
513
513
|
it_behaves_like "cdata behavior", described_class
|
|
514
514
|
end
|
|
515
515
|
|
|
516
|
-
describe Lutaml::Model::
|
|
516
|
+
describe Lutaml::Model::Xml::OxAdapter do
|
|
517
517
|
it_behaves_like "cdata behavior", described_class
|
|
518
518
|
end
|
|
519
519
|
end
|
|
@@ -59,6 +59,29 @@ module ChoiceSpec
|
|
|
59
59
|
map :last_name, to: :last_name
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
|
+
|
|
63
|
+
class ContactEmail < Lutaml::Model::Serializable
|
|
64
|
+
attribute :email, :string
|
|
65
|
+
xml { no_root }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class ContactPhone < Lutaml::Model::Serializable
|
|
69
|
+
attribute :phone, :string
|
|
70
|
+
xml { no_root }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Person < Lutaml::Model::Serializable
|
|
74
|
+
choice(min: 1, max: 2) do
|
|
75
|
+
import_model_attributes ContactEmail
|
|
76
|
+
import_model_attributes ContactPhone
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
xml do
|
|
80
|
+
root "Person"
|
|
81
|
+
map_element :email, to: :email
|
|
82
|
+
map_element :phone, to: :phone
|
|
83
|
+
end
|
|
84
|
+
end
|
|
62
85
|
end
|
|
63
86
|
|
|
64
87
|
RSpec.describe "Choice" do
|
|
@@ -165,4 +188,25 @@ RSpec.describe "Choice" do
|
|
|
165
188
|
end.to raise_error(Lutaml::Model::InvalidChoiceRangeError, "Choice lower bound `-1` must be positive")
|
|
166
189
|
end
|
|
167
190
|
end
|
|
191
|
+
|
|
192
|
+
context "with choice using import_model_attributes" do
|
|
193
|
+
it "parses XML with both email and phone using choice and import_model_attributes" do
|
|
194
|
+
xml = <<~XML
|
|
195
|
+
<Person>
|
|
196
|
+
<email>john.doe@example.com</email>
|
|
197
|
+
<phone>1234567890</phone>
|
|
198
|
+
</Person>
|
|
199
|
+
XML
|
|
200
|
+
person = ChoiceSpec::Person.from_xml(xml)
|
|
201
|
+
expect(person.email).to eq("john.doe@example.com")
|
|
202
|
+
expect(person.phone).to eq("1234567890")
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "raises error if no contact info is provided" do
|
|
206
|
+
xml = <<~XML
|
|
207
|
+
<Person></Person>
|
|
208
|
+
XML
|
|
209
|
+
expect { ChoiceSpec::Person.from_xml(xml).validate! }.to raise_error(Lutaml::Model::ValidationError)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
168
212
|
end
|