lutaml-model 0.8.15 → 0.8.17

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +0 -3
  3. data/.rubocop_todo.yml +49 -52
  4. data/README.adoc +188 -25
  5. data/docs/_guides/xml/namespace-semantics.adoc +2 -0
  6. data/docs/_guides/xml-mapping.adoc +178 -24
  7. data/docs/_guides/xml-namespace-qualification.adoc +142 -0
  8. data/docs/_pages/importable_models.adoc +7 -1
  9. data/docs/_tutorials/xml-element-attribute-namespace-guide.adoc +2 -0
  10. data/docs/_tutorials/xml-schema-primer-style-guide.adoc +2 -0
  11. data/docs/namespace-management.adoc +2 -0
  12. data/docs/xml-schema-qualification.md +6 -0
  13. data/lib/lutaml/jsonld.rb +1 -4
  14. data/lib/lutaml/model/attribute.rb +4 -0
  15. data/lib/lutaml/model/choice.rb +34 -0
  16. data/lib/lutaml/model/compiled_rule.rb +7 -0
  17. data/lib/lutaml/model/version.rb +1 -1
  18. data/lib/lutaml/model.rb +3 -1
  19. data/lib/lutaml/{jsonld → rdf}/context.rb +1 -1
  20. data/lib/lutaml/{jsonld/transform.rb → rdf/linked_data_transform.rb} +33 -35
  21. data/lib/lutaml/{jsonld → rdf}/term_definition.rb +1 -1
  22. data/lib/lutaml/rdf.rb +3 -0
  23. data/lib/lutaml/turtle/transform.rb +2 -1
  24. data/lib/lutaml/xml/adapter/plan_based_builder.rb +3 -1
  25. data/lib/lutaml/xml/adapter/xml_serializer.rb +14 -4
  26. data/lib/lutaml/xml/adapter.rb +2 -1
  27. data/lib/lutaml/xml/adapter_element.rb +2 -2
  28. data/lib/lutaml/xml/builder/base.rb +2 -1
  29. data/lib/lutaml/xml/data_model.rb +19 -3
  30. data/lib/lutaml/xml/mapping.rb +3 -1
  31. data/lib/lutaml/xml/mapping_rule.rb +28 -2
  32. data/lib/lutaml/xml/model_transform.rb +9 -1
  33. data/lib/lutaml/xml/serialization/instance_methods.rb +16 -9
  34. data/lib/lutaml/xml/transformation/element_builder.rb +39 -26
  35. data/lib/lutaml/xml/transformation/rule_applier.rb +21 -0
  36. data/lib/lutaml/xml/transformation/rule_compiler.rb +12 -3
  37. data/lib/lutaml/yamlld/adapter.rb +25 -0
  38. data/lib/lutaml/yamlld.rb +25 -0
  39. data/spec/lutaml/integration/multi_format_spec.rb +23 -0
  40. data/spec/lutaml/model/attribute_spec.rb +8 -1
  41. data/spec/lutaml/model/choice_restrict_spec.rb +225 -0
  42. data/spec/lutaml/model/custom_model_spec.rb +4 -4
  43. data/spec/lutaml/model/mixed_content_spec.rb +50 -9
  44. data/spec/lutaml/model/multiple_mapping_spec.rb +4 -4
  45. data/spec/lutaml/model/ordered_content_spec.rb +3 -3
  46. data/spec/lutaml/model/raw_element_spec.rb +533 -0
  47. data/spec/lutaml/model/uninitialized_class_spec.rb +1 -1
  48. data/spec/lutaml/model/xsd_form_default_patterns_spec.rb +2 -2
  49. data/spec/lutaml/model/xsd_patterns_spec.rb +4 -4
  50. data/spec/lutaml/{jsonld → rdf}/context_spec.rb +2 -2
  51. data/spec/lutaml/{jsonld/transform_spec.rb → rdf/linked_data_transform_spec.rb} +18 -2
  52. data/spec/lutaml/rdf/mapping_spec.rb +2 -1
  53. data/spec/lutaml/{jsonld → rdf}/term_definition_spec.rb +2 -2
  54. data/spec/lutaml/turtle/transform_spec.rb +2 -2
  55. data/spec/lutaml/xml/enhanced_mapping_spec.rb +230 -1
  56. data/spec/lutaml/xml/mapping_spec.rb +4 -4
  57. data/spec/lutaml/xml/namespace_placement_spec.rb +11 -8
  58. data/spec/lutaml/xml/namespace_three_phase_spec.rb +1 -1
  59. data/spec/lutaml/xml/prefix_control_spec.rb +4 -4
  60. data/spec/lutaml/xml/serializable_namespace_spec.rb +6 -6
  61. data/spec/lutaml/xml/type_namespace_examples_spec.rb +1 -1
  62. data/spec/lutaml/xml/type_namespace_integration_spec.rb +3 -3
  63. data/spec/lutaml/yamlld/adapter_spec.rb +56 -0
  64. data/spec/lutaml/yamlld/registration_spec.rb +33 -0
  65. metadata +14 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d6ce7467101e1a845bcd0bfb98b0e878d55d440065a12481576a8aa5c050c98
4
- data.tar.gz: e534138d7ca3848eaa33681e286584ea385386734617f37c5fa89a7c3f752f79
3
+ metadata.gz: 8296b9832eb080f64ba1344b7fa929b179fedc1c4265d9743d6636cd408720f6
4
+ data.tar.gz: 533255e9702cd82fc93cacc78bf88fb90dba17b8543b5ecf22bb223eaacfa9a1
5
5
  SHA512:
6
- metadata.gz: 8e872c659c1e147598fffe00ea015ed07dbd16b795c254f4aed6df30d2c6f2c91ab51740f5112b93e67d113d5b7d7f4edef755a2d6fa848053ab885533ac1336
7
- data.tar.gz: 22a484ca450a64ff4b3b0d426f1982e0e17d90eb422534158cf02ca65b96cc5293f401fec9cbbaa39a0ccaa06c0ef987b9a7f0f02312bc6fd55233b1666191ad
6
+ metadata.gz: 936d9c1ff8eefb9f2b861d3c29c4d032462f9f6f5624bb2d669ebfc77d49ade62ce2859f171052f3b473a00d0a83a88955ee1c4cbd47f5bbddfe2a625e62d1f8
7
+ data.tar.gz: 79f9f3b4cea4bff89c06df360e6a316507f62af37f2a277cd10dc54b38f72c374cadba6b4b995234e4c67f82dbaa71ecf751d3ec8ed280bf5fe0e64dca42534f
@@ -23,9 +23,6 @@ jobs:
23
23
  uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
24
24
  with:
25
25
  next_version: ${{ github.event.inputs.next_version }}
26
- post_install: |
27
- git status
28
- cat .bundle/config
29
26
  secrets:
30
27
  rubygems-api-key: ${{ secrets.LUTAML_CI_RUBYGEMS_API_KEY }}
31
28
  pat_token: ${{ secrets.LUTAML_CI_PAT_TOKEN }}
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-27 05:02:01 UTC using RuboCop version 1.86.0.
3
+ # on 2026-06-08 11:45:37 UTC using RuboCop version 1.87.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
@@ -11,39 +11,45 @@ Gemspec/RequiredRubyVersion:
11
11
  Exclude:
12
12
  - 'lutaml-model.gemspec'
13
13
 
14
- # Offense count: 2
14
+ # Offense count: 1
15
15
  # This cop supports safe autocorrection (--autocorrect).
16
16
  # Configuration parameters: EnforcedStyle, IndentationWidth.
17
17
  # SupportedStyles: with_first_argument, with_fixed_indentation
18
18
  Layout/ArgumentAlignment:
19
19
  Exclude:
20
- - 'spec/lutaml/model/opal_smoke_spec.rb'
20
+ - 'lib/lutaml/rdf/linked_data_transform.rb'
21
21
 
22
- # Offense count: 1
22
+ # Offense count: 2
23
23
  # This cop supports safe autocorrection (--autocorrect).
24
- Layout/ClosingParenthesisIndentation:
24
+ # Configuration parameters: EnforcedStyleAlignWith.
25
+ # SupportedStylesAlignWith: either, start_of_block, start_of_line
26
+ Layout/BlockAlignment:
25
27
  Exclude:
26
- - 'spec/lutaml/model/opal_smoke_spec.rb'
28
+ - 'spec/lutaml/model/choice_restrict_spec.rb'
27
29
 
28
- # Offense count: 1
30
+ # Offense count: 2
29
31
  # This cop supports safe autocorrection (--autocorrect).
30
- # Configuration parameters: EnforcedStyle, IndentationWidth.
31
- # SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses
32
- Layout/FirstArgumentIndentation:
32
+ Layout/BlockEndNewline:
33
33
  Exclude:
34
- - 'spec/lutaml/model/opal_smoke_spec.rb'
34
+ - 'spec/lutaml/model/choice_restrict_spec.rb'
35
35
 
36
36
  # Offense count: 2
37
37
  # This cop supports safe autocorrection (--autocorrect).
38
- # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
39
- # SupportedHashRocketStyles: key, separator, table
40
- # SupportedColonStyles: key, separator, table
41
- # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
42
- Layout/HashAlignment:
38
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
39
+ # SupportedStyles: special_inside_parentheses, consistent, align_brackets
40
+ Layout/FirstArrayElementIndentation:
41
+ Exclude:
42
+ - 'spec/lutaml/model/choice_restrict_spec.rb'
43
+
44
+ # Offense count: 4
45
+ # This cop supports safe autocorrection (--autocorrect).
46
+ # Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
47
+ # SupportedStylesAlignWith: start_of_line, relative_to_receiver
48
+ Layout/IndentationWidth:
43
49
  Exclude:
44
- - 'spec/lutaml/model/opal_smoke_spec.rb'
50
+ - 'spec/lutaml/model/choice_restrict_spec.rb'
45
51
 
46
- # Offense count: 3022
52
+ # Offense count: 3071
47
53
  # This cop supports safe autocorrection (--autocorrect).
48
54
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
49
55
  # URISchemes: http, https
@@ -54,16 +60,16 @@ Layout/LineLength:
54
60
  # This cop supports safe autocorrection (--autocorrect).
55
61
  # Configuration parameters: EnforcedStyle.
56
62
  # SupportedStyles: symmetrical, new_line, same_line
57
- Layout/MultilineMethodCallBraceLayout:
63
+ Layout/MultilineArrayBraceLayout:
58
64
  Exclude:
59
- - 'spec/lutaml/model/opal_smoke_spec.rb'
65
+ - 'spec/lutaml/model/choice_restrict_spec.rb'
60
66
 
61
67
  # Offense count: 1
62
68
  # This cop supports safe autocorrection (--autocorrect).
63
69
  # Configuration parameters: AllowInHeredoc.
64
70
  Layout/TrailingWhitespace:
65
71
  Exclude:
66
- - 'spec/lutaml/model/opal_smoke_spec.rb'
72
+ - 'lib/lutaml/rdf/linked_data_transform.rb'
67
73
 
68
74
  # Offense count: 21
69
75
  # Configuration parameters: AllowedMethods.
@@ -76,21 +82,15 @@ Lint/ConstantDefinitionInBlock:
76
82
  - 'spec/lutaml/xml/type_namespace_prefix_spec.rb'
77
83
  - 'spec/lutaml/xml/xml_space_type_spec.rb'
78
84
 
79
- # Offense count: 36
85
+ # Offense count: 35
80
86
  # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
81
87
  Lint/DuplicateBranch:
82
88
  Enabled: false
83
89
 
84
- # Offense count: 22
90
+ # Offense count: 3
85
91
  Lint/DuplicateMethods:
86
92
  Exclude:
87
93
  - 'lib/lutaml/xml/mapping.rb'
88
- - 'spec/lutaml/model/liquid_compatibility_spec.rb'
89
- - 'spec/lutaml/xml/namespace_no_hoisting_spec.rb'
90
- - 'spec/lutaml/xml/namespace_scope_declare_spec.rb'
91
- - 'spec/lutaml/xml/namespace_scope_vcard_spec.rb'
92
- - 'spec/lutaml/xml/prefix_control_spec.rb'
93
- - 'spec/lutaml/xml/type_namespace_examples_spec.rb'
94
94
 
95
95
  # Offense count: 1
96
96
  # This cop supports safe autocorrection (--autocorrect).
@@ -156,18 +156,12 @@ Lint/UnusedMethodArgument:
156
156
  - 'lib/lutaml/xml/unqualified_inheritance_strategy.rb'
157
157
  - 'spec/support/xml/xsd/code_example_validator.rb'
158
158
 
159
- # Offense count: 1
160
- # This cop supports safe autocorrection (--autocorrect).
161
- Lint/UselessAssignment:
162
- Exclude:
163
- - 'spec/lutaml/xml/opal_xml_spec.rb'
164
-
165
159
  # Offense count: 1
166
160
  Lint/UselessConstantScoping:
167
161
  Exclude:
168
162
  - 'lib/lutaml/xml/mapping_rule.rb'
169
163
 
170
- # Offense count: 345
164
+ # Offense count: 346
171
165
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
172
166
  Metrics/AbcSize:
173
167
  Enabled: false
@@ -183,12 +177,12 @@ Metrics/BlockLength:
183
177
  Metrics/BlockNesting:
184
178
  Max: 6
185
179
 
186
- # Offense count: 308
180
+ # Offense count: 307
187
181
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
188
182
  Metrics/CyclomaticComplexity:
189
183
  Enabled: false
190
184
 
191
- # Offense count: 553
185
+ # Offense count: 554
192
186
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
193
187
  Metrics/MethodLength:
194
188
  Max: 514
@@ -196,10 +190,10 @@ Metrics/MethodLength:
196
190
  # Offense count: 81
197
191
  # Configuration parameters: CountKeywordArgs.
198
192
  Metrics/ParameterLists:
199
- Max: 24
200
193
  MaxOptionalParameters: 5
194
+ Max: 25
201
195
 
202
- # Offense count: 262
196
+ # Offense count: 261
203
197
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
204
198
  Metrics/PerceivedComplexity:
205
199
  Enabled: false
@@ -291,7 +285,7 @@ RSpec/BeforeAfterAll:
291
285
  RSpec/ContextWording:
292
286
  Enabled: false
293
287
 
294
- # Offense count: 98
288
+ # Offense count: 102
295
289
  # Configuration parameters: IgnoredMetadata.
296
290
  RSpec/DescribeClass:
297
291
  Enabled: false
@@ -302,7 +296,7 @@ RSpec/DescribeMethod:
302
296
  - 'spec/lutaml/xml/schema/xsd/schema_helper_methods_spec.rb'
303
297
  - 'spec/lutaml/xml/serializable_namespace_spec.rb'
304
298
 
305
- # Offense count: 1301
299
+ # Offense count: 1343
306
300
  # Configuration parameters: CountAsOne.
307
301
  RSpec/ExampleLength:
308
302
  Max: 68
@@ -377,7 +371,7 @@ RSpec/MultipleDescribes:
377
371
  - 'spec/lutaml/xml/namespace_resolution_strategy_spec.rb'
378
372
  - 'spec/lutaml/xml/xml_space_type_spec.rb'
379
373
 
380
- # Offense count: 1515
374
+ # Offense count: 1576
381
375
  RSpec/MultipleExpectations:
382
376
  Max: 21
383
377
 
@@ -425,7 +419,7 @@ RSpec/RepeatedExampleGroupDescription:
425
419
  Exclude:
426
420
  - 'spec/lutaml/model/mixed_content_spec.rb'
427
421
 
428
- # Offense count: 40
422
+ # Offense count: 39
429
423
  # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
430
424
  # SupportedInflectors: default, active_support
431
425
  RSpec/SpecFilePathFormat:
@@ -451,6 +445,17 @@ Security/MarshalLoad:
451
445
  Exclude:
452
446
  - 'scripts-xmi-profile/profile_xmi.rb'
453
447
 
448
+ # Offense count: 3
449
+ # This cop supports safe autocorrection (--autocorrect).
450
+ # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
451
+ # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
452
+ # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
453
+ # FunctionalMethods: let, let!, subject, watch
454
+ # AllowedMethods: lambda, proc, it
455
+ Style/BlockDelimiters:
456
+ Exclude:
457
+ - 'spec/lutaml/model/choice_restrict_spec.rb'
458
+
454
459
  # Offense count: 2
455
460
  # This cop supports unsafe autocorrection (--autocorrect-all).
456
461
  # Configuration parameters: AllowedMethods, AllowedPatterns.
@@ -543,11 +548,3 @@ Style/StringConcatenation:
543
548
  - 'lib/lutaml/model/schema/xml_compiler/complex_type.rb'
544
549
  - 'lib/lutaml/model/schema/xml_compiler/simple_type.rb'
545
550
  - 'lib/lutaml/model/schema/xml_compiler/xml_namespace_class.rb'
546
-
547
- # Offense count: 1
548
- # This cop supports safe autocorrection (--autocorrect).
549
- # Configuration parameters: EnforcedStyleForMultiline.
550
- # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
551
- Style/TrailingCommaInArguments:
552
- Exclude:
553
- - 'spec/lutaml/model/opal_smoke_spec.rb'
data/README.adoc CHANGED
@@ -3554,7 +3554,14 @@ the current value is the same as the default value.
3554
3554
 
3555
3555
 
3556
3556
 
3557
- === Attribute as raw string
3557
+ === Attribute as raw string (deprecated)
3558
+
3559
+ [WARNING]
3560
+ ====
3561
+ `attribute :name, :string, raw: true` is deprecated.
3562
+ Use `map_element "name", to: :name, raw: :content` instead.
3563
+ See <<xml-raw-element>> for the full raw XML capture documentation.
3564
+ ====
3558
3565
 
3559
3566
  An attribute can be set to read the value as raw string for XML, by using the `raw: true` option.
3560
3567
 
@@ -7969,42 +7976,186 @@ end
7969
7976
  ====
7970
7977
 
7971
7978
 
7972
- [[xml-map-all]]
7973
- ==== Mapping entire XML element into an attribute
7974
7979
 
7975
- The `map_all` tag in XML mapping captures and maps all content within an XML
7976
- element into a single attribute in the target Ruby object.
7980
+ [[xml-raw-element]]
7981
+ ==== Capturing raw XML content
7977
7982
 
7978
- The use case for `map_all` is to tell Lutaml::Model to not parse the content of
7979
- the XML element at all, and instead handle it as an XML string.
7983
+ Lutaml::Model provides several mechanisms for capturing XML content as raw strings.
7984
+ Use these when you need to embed foreign XML vocabularies (SVG, MathML, XSL-FO) or
7985
+ preserve markup that your model doesn't need to parse.
7980
7986
 
7981
- NOTE: The corresponding method for key-value formats is at <<key-value-map-all>>.
7987
+ ===== `raw: :element` on `map_element` full element capture (recommended)
7982
7988
 
7983
- WARNING: Notice that usage of mapping all will lead to incompatibility between
7984
- serialization formats, i.e. the raw string content will not be portable as
7985
- objects are across different formats.
7989
+ The `raw: :element` option captures a specific mapped element as a complete XML
7990
+ string, including its opening tag, attributes, children, and closing tag.
7991
+ This provides **lossless round-trip** fidelity — the captured string is
7992
+ self-contained and serialized verbatim.
7993
+
7994
+ .Syntax
7995
+ [source,ruby]
7996
+ ----
7997
+ xml do
7998
+ map_element "svg", to: :svg_data, raw: :element
7999
+ end
8000
+ ----
8001
+
8002
+ .Capturing an SVG element as raw XML
8003
+ [example]
8004
+ ====
8005
+ [source,ruby]
8006
+ ----
8007
+ class SvgContainer < Lutaml::Model::Serializable
8008
+ attribute :name, :string
8009
+ attribute :svg_data, :string
8010
+
8011
+ xml do
8012
+ element "container"
8013
+ map_element "name", to: :name
8014
+ map_element "svg", to: :svg_data, raw: :element
8015
+ end
8016
+ end
8017
+ ----
7986
8018
 
7987
- This is useful in the case where the content of an XML element is not to be
7988
- handled by a Lutaml::Model::Serializable object.
8019
+ [source,xml]
8020
+ ----
8021
+ <container>
8022
+ <name>diagram</name>
8023
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
8024
+ <rect x="0" y="0" width="100" height="100" fill="red"/>
8025
+ </svg>
8026
+ </container>
8027
+ ----
7989
8028
 
7990
- This feature is commonly used with custom methods or a custom model object to
7991
- handle the content.
8029
+ [source,ruby]
8030
+ ----
8031
+ > doc = SvgContainer.from_xml(xml)
8032
+ > doc.name
8033
+ # => "diagram"
8034
+ > doc.svg_data
8035
+ # => "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\">\n <rect x=\"0\" y=\"0\" width=\"100\" height=\"100\" fill=\"red\"/>\n</svg>"
8036
+ ----
7992
8037
 
7993
- This includes:
8038
+ The captured string round-trips correctly -- serializing the model back to XML
8039
+ outputs the raw element verbatim without escaping or wrapping.
7994
8040
 
7995
- * nested tags
7996
- * attributes
7997
- * text nodes
8041
+ `raw: :element` also works with collection attributes:
7998
8042
 
7999
- The `map_all` tag is **exclusive** and cannot be combined with other mappings
8000
- (`map_element`, `map_content`) except for `map_attribute` for the same element,
8001
- ensuring it captures the entire inner XML content.
8043
+ [source,ruby]
8044
+ ----
8045
+ class MultiFragment < Lutaml::Model::Serializable
8046
+ attribute :fragments, :string, collection: true
8002
8047
 
8003
- NOTE: An error is raised if `map_all` is defined alongside any other mapping in
8004
- the same XML mapping context.
8048
+ xml do
8049
+ element "container"
8050
+ map_element "fragment", to: :fragments, raw: :element
8051
+ end
8052
+ end
8053
+ ----
8054
+ ====
8005
8055
 
8006
- Syntax:
8056
+ ===== `raw: :content` on `map_element` — inner content capture
8057
+
8058
+ The `raw: :content` option captures only the *inner XML* of the matched element,
8059
+ without the wrapper tags. The wrapper element is reconstructed from the mapping rule
8060
+ during serialization.
8061
+
8062
+ .Syntax
8063
+ [source,ruby]
8064
+ ----
8065
+ xml do
8066
+ map_element "street", to: :street, raw: :content
8067
+ end
8068
+ ----
8069
+
8070
+ .Capturing inner XML content
8071
+ [example]
8072
+ ====
8073
+ [source,ruby]
8074
+ ----
8075
+ class Address < Lutaml::Model::Serializable
8076
+ attribute :street, :string
8077
+
8078
+ xml do
8079
+ element "address"
8080
+ map_element "street", to: :street, raw: :content
8081
+ end
8082
+ end
8083
+ ----
8084
+
8085
+ [source,xml]
8086
+ ----
8087
+ <address><street><b>123</b> Main St</street></address>
8088
+ ----
8089
+
8090
+ [source,ruby]
8091
+ ----
8092
+ > doc = Address.from_xml(xml)
8093
+ > doc.street
8094
+ # => "<b>123</b> Main St"
8095
+ ----
8096
+ ====
8097
+
8098
+ NOTE: `raw: :content` is **lossy** — namespace prefixes declared on the wrapper
8099
+ element are not captured. For lossless capture, use `raw: :element` instead.
8100
+
8101
+ ===== Namespace behavior
8102
+
8103
+ Both `raw: :element` and `raw: :content` match elements by local name regardless
8104
+ of namespace or prefix:
8105
+
8106
+ * Elements with no namespace (`<svg>`)
8107
+ * Elements with an `xmlns` declaration on themselves (`<svg xmlns="...">`)
8108
+ * Elements inheriting a default namespace from a parent
8109
+ * Elements with an explicit namespace prefix (`<ns:svg>`)
8110
+
8111
+ This is intentional — raw capture is designed to handle foreign XML vocabularies
8112
+ without needing model classes for them.
8113
+
8114
+ ===== Round-trip fidelity comparison
8115
+
8116
+ | Aspect | `raw: :element` | `raw: :content` |
8117
+ |--------|----------------|-----------------|
8118
+ | Element name | Preserved (in string) | Reconstructed from rule |
8119
+ | Element attributes | Preserved (in string) | Lost unless separately mapped |
8120
+ | Inner content | Preserved (in string) | Preserved (in string) |
8121
+ | Namespace prefixes | Safe (declared in string) | May break if declared on wrapper |
8122
+ | Fidelity | **Lossless** | **Lossy** |
8123
+
8124
+ ===== Wrapper model pattern for attribute extraction
8125
+
8126
+ Raw capture stores the element as a string. If you need to inspect or modify
8127
+ attributes on the captured element, use a wrapper model with `map_all`:
8007
8128
 
8129
+ [source,ruby]
8130
+ ----
8131
+ class SvgInner < Lutaml::Model::Serializable
8132
+ attribute :raw, :string
8133
+
8134
+ xml do
8135
+ element "svg"
8136
+ map_all to: :raw
8137
+ end
8138
+ end
8139
+
8140
+ class Container < Lutaml::Model::Serializable
8141
+ attribute :svg_data, SvgInner
8142
+
8143
+ xml do
8144
+ element "container"
8145
+ map_element "svg", to: :svg_data
8146
+ end
8147
+ end
8148
+ ----
8149
+
8150
+ ===== `map_all` — root inner XML capture
8151
+
8152
+ The `map_all` directive captures the entire inner XML of the root element into
8153
+ a single attribute. It is **exclusive** — it cannot be combined with other
8154
+ `map_element` or `map_content` mappings (only `map_attribute` is allowed).
8155
+
8156
+ NOTE: The corresponding method for key-value formats is at <<key-value-map-all>>.
8157
+
8158
+ .Syntax
8008
8159
  [source,ruby]
8009
8160
  ----
8010
8161
  xml do
@@ -8039,6 +8190,18 @@ end
8039
8190
  ----
8040
8191
  ====
8041
8192
 
8193
+ ===== Deprecated: `attribute :x, :string, raw: true`
8194
+
8195
+ [WARNING]
8196
+ ====
8197
+ `attribute :name, :string, raw: true` is deprecated. Use
8198
+ `map_element "name", to: :name, raw: :content` instead.
8199
+ ====
8200
+
8201
+ This legacy syntax captures the inner XML of the matched element.
8202
+ It is equivalent to `raw: :content` on the mapping. Existing code continues
8203
+ to work but emits a deprecation warning.
8204
+
8042
8205
 
8043
8206
  ==== Mapping CDATA nodes
8044
8207
 
@@ -13,6 +13,8 @@ parent: XML namespaces
13
13
  Lutaml::Model implements W3C XML Namespace specification with a focus on
14
14
  **attribute-based namespace resolution**. Each XML element's namespace is
15
15
  determined by its attribute's type and parent context, following clear and
16
+
17
+ NOTE: This document covers the *core namespace resolution principles*. For the `form:` override option, the full qualification precedence ladder, and `form:` behavior on nested `Serializable` children, see the companion guide: link:../xml-namespace-qualification[XML Namespace Qualification and Prefix Control].
16
18
  consistent rules.
17
19
 
18
20
  This document explains the core namespace principles that govern how namespaces