lutaml-model 0.8.15 → 0.8.16
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/.rubocop_todo.yml +14 -73
- data/README.adoc +188 -25
- data/docs/_guides/xml-mapping.adoc +178 -24
- data/docs/_pages/importable_models.adoc +7 -1
- data/lib/lutaml/model/attribute.rb +4 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +2 -1
- data/lib/lutaml/turtle/transform.rb +2 -1
- data/lib/lutaml/xml/adapter/plan_based_builder.rb +3 -1
- data/lib/lutaml/xml/adapter/xml_serializer.rb +14 -4
- data/lib/lutaml/xml/adapter.rb +2 -1
- data/lib/lutaml/xml/builder/base.rb +2 -1
- data/lib/lutaml/xml/data_model.rb +19 -3
- data/lib/lutaml/xml/mapping.rb +3 -1
- data/lib/lutaml/xml/mapping_rule.rb +28 -2
- data/lib/lutaml/xml/model_transform.rb +9 -1
- data/lib/lutaml/xml/serialization/instance_methods.rb +16 -9
- data/lib/lutaml/xml/transformation/element_builder.rb +1 -3
- data/lib/lutaml/xml/transformation/rule_applier.rb +21 -0
- data/lib/lutaml/xml/transformation/rule_compiler.rb +12 -3
- data/spec/lutaml/jsonld/transform_spec.rb +3 -1
- data/spec/lutaml/model/mixed_content_spec.rb +48 -7
- data/spec/lutaml/model/raw_element_spec.rb +533 -0
- data/spec/lutaml/rdf/mapping_spec.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0b419ac1cce55a5e56ca59dd217042047801d2420751f89ce0b875558e517f44
|
|
4
|
+
data.tar.gz: ed7c6b7dcd749c35d7fa434d2adf4b9e036c7329afd80c2420ef75f57f65895f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c923ed6933f06ca678d4b76c19b46553f1196e0b30c0f202113a792619c91c0e6b3e3885963f4b910d101722d0cee22df8bf71c0c593fc7de4f0832d9062d87d
|
|
7
|
+
data.tar.gz: cfc1cc06ebeb1affa7875ecc522d8625147f70ed81aa6ae2feb2b4debd92f652ce2cf565f9984e52170e65559a75f23139c85762df5018545b60187cb5974744
|
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
|
|
3
|
+
# on 2026-06-05 08:01:07 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,60 +11,13 @@ Gemspec/RequiredRubyVersion:
|
|
|
11
11
|
Exclude:
|
|
12
12
|
- 'lutaml-model.gemspec'
|
|
13
13
|
|
|
14
|
-
# Offense count:
|
|
15
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
16
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
17
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
18
|
-
Layout/ArgumentAlignment:
|
|
19
|
-
Exclude:
|
|
20
|
-
- 'spec/lutaml/model/opal_smoke_spec.rb'
|
|
21
|
-
|
|
22
|
-
# Offense count: 1
|
|
23
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
24
|
-
Layout/ClosingParenthesisIndentation:
|
|
25
|
-
Exclude:
|
|
26
|
-
- 'spec/lutaml/model/opal_smoke_spec.rb'
|
|
27
|
-
|
|
28
|
-
# Offense count: 1
|
|
29
|
-
# 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:
|
|
33
|
-
Exclude:
|
|
34
|
-
- 'spec/lutaml/model/opal_smoke_spec.rb'
|
|
35
|
-
|
|
36
|
-
# Offense count: 2
|
|
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:
|
|
43
|
-
Exclude:
|
|
44
|
-
- 'spec/lutaml/model/opal_smoke_spec.rb'
|
|
45
|
-
|
|
46
|
-
# Offense count: 3022
|
|
14
|
+
# Offense count: 3052
|
|
47
15
|
# This cop supports safe autocorrection (--autocorrect).
|
|
48
16
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
49
17
|
# URISchemes: http, https
|
|
50
18
|
Layout/LineLength:
|
|
51
19
|
Enabled: false
|
|
52
20
|
|
|
53
|
-
# Offense count: 1
|
|
54
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
55
|
-
# Configuration parameters: EnforcedStyle.
|
|
56
|
-
# SupportedStyles: symmetrical, new_line, same_line
|
|
57
|
-
Layout/MultilineMethodCallBraceLayout:
|
|
58
|
-
Exclude:
|
|
59
|
-
- 'spec/lutaml/model/opal_smoke_spec.rb'
|
|
60
|
-
|
|
61
|
-
# Offense count: 1
|
|
62
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
63
|
-
# Configuration parameters: AllowInHeredoc.
|
|
64
|
-
Layout/TrailingWhitespace:
|
|
65
|
-
Exclude:
|
|
66
|
-
- 'spec/lutaml/model/opal_smoke_spec.rb'
|
|
67
|
-
|
|
68
21
|
# Offense count: 21
|
|
69
22
|
# Configuration parameters: AllowedMethods.
|
|
70
23
|
# AllowedMethods: enums
|
|
@@ -76,21 +29,15 @@ Lint/ConstantDefinitionInBlock:
|
|
|
76
29
|
- 'spec/lutaml/xml/type_namespace_prefix_spec.rb'
|
|
77
30
|
- 'spec/lutaml/xml/xml_space_type_spec.rb'
|
|
78
31
|
|
|
79
|
-
# Offense count:
|
|
32
|
+
# Offense count: 35
|
|
80
33
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
81
34
|
Lint/DuplicateBranch:
|
|
82
35
|
Enabled: false
|
|
83
36
|
|
|
84
|
-
# Offense count:
|
|
37
|
+
# Offense count: 3
|
|
85
38
|
Lint/DuplicateMethods:
|
|
86
39
|
Exclude:
|
|
87
40
|
- '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
41
|
|
|
95
42
|
# Offense count: 1
|
|
96
43
|
# This cop supports safe autocorrection (--autocorrect).
|
|
@@ -156,18 +103,12 @@ Lint/UnusedMethodArgument:
|
|
|
156
103
|
- 'lib/lutaml/xml/unqualified_inheritance_strategy.rb'
|
|
157
104
|
- 'spec/support/xml/xsd/code_example_validator.rb'
|
|
158
105
|
|
|
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
106
|
# Offense count: 1
|
|
166
107
|
Lint/UselessConstantScoping:
|
|
167
108
|
Exclude:
|
|
168
109
|
- 'lib/lutaml/xml/mapping_rule.rb'
|
|
169
110
|
|
|
170
|
-
# Offense count:
|
|
111
|
+
# Offense count: 346
|
|
171
112
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
172
113
|
Metrics/AbcSize:
|
|
173
114
|
Enabled: false
|
|
@@ -183,12 +124,12 @@ Metrics/BlockLength:
|
|
|
183
124
|
Metrics/BlockNesting:
|
|
184
125
|
Max: 6
|
|
185
126
|
|
|
186
|
-
# Offense count:
|
|
127
|
+
# Offense count: 307
|
|
187
128
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
188
129
|
Metrics/CyclomaticComplexity:
|
|
189
130
|
Enabled: false
|
|
190
131
|
|
|
191
|
-
# Offense count:
|
|
132
|
+
# Offense count: 554
|
|
192
133
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
193
134
|
Metrics/MethodLength:
|
|
194
135
|
Max: 514
|
|
@@ -196,10 +137,10 @@ Metrics/MethodLength:
|
|
|
196
137
|
# Offense count: 81
|
|
197
138
|
# Configuration parameters: CountKeywordArgs.
|
|
198
139
|
Metrics/ParameterLists:
|
|
199
|
-
Max: 24
|
|
200
140
|
MaxOptionalParameters: 5
|
|
141
|
+
Max: 25
|
|
201
142
|
|
|
202
|
-
# Offense count:
|
|
143
|
+
# Offense count: 261
|
|
203
144
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
204
145
|
Metrics/PerceivedComplexity:
|
|
205
146
|
Enabled: false
|
|
@@ -291,7 +232,7 @@ RSpec/BeforeAfterAll:
|
|
|
291
232
|
RSpec/ContextWording:
|
|
292
233
|
Enabled: false
|
|
293
234
|
|
|
294
|
-
# Offense count:
|
|
235
|
+
# Offense count: 101
|
|
295
236
|
# Configuration parameters: IgnoredMetadata.
|
|
296
237
|
RSpec/DescribeClass:
|
|
297
238
|
Enabled: false
|
|
@@ -302,7 +243,7 @@ RSpec/DescribeMethod:
|
|
|
302
243
|
- 'spec/lutaml/xml/schema/xsd/schema_helper_methods_spec.rb'
|
|
303
244
|
- 'spec/lutaml/xml/serializable_namespace_spec.rb'
|
|
304
245
|
|
|
305
|
-
# Offense count:
|
|
246
|
+
# Offense count: 1328
|
|
306
247
|
# Configuration parameters: CountAsOne.
|
|
307
248
|
RSpec/ExampleLength:
|
|
308
249
|
Max: 68
|
|
@@ -377,7 +318,7 @@ RSpec/MultipleDescribes:
|
|
|
377
318
|
- 'spec/lutaml/xml/namespace_resolution_strategy_spec.rb'
|
|
378
319
|
- 'spec/lutaml/xml/xml_space_type_spec.rb'
|
|
379
320
|
|
|
380
|
-
# Offense count:
|
|
321
|
+
# Offense count: 1560
|
|
381
322
|
RSpec/MultipleExpectations:
|
|
382
323
|
Max: 21
|
|
383
324
|
|
|
@@ -544,10 +485,10 @@ Style/StringConcatenation:
|
|
|
544
485
|
- 'lib/lutaml/model/schema/xml_compiler/simple_type.rb'
|
|
545
486
|
- 'lib/lutaml/model/schema/xml_compiler/xml_namespace_class.rb'
|
|
546
487
|
|
|
547
|
-
# Offense count:
|
|
488
|
+
# Offense count: 3
|
|
548
489
|
# This cop supports safe autocorrection (--autocorrect).
|
|
549
490
|
# Configuration parameters: EnforcedStyleForMultiline.
|
|
550
491
|
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
551
492
|
Style/TrailingCommaInArguments:
|
|
552
493
|
Exclude:
|
|
553
|
-
- 'spec/lutaml/model/
|
|
494
|
+
- 'spec/lutaml/model/raw_element_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
|
-
|
|
7976
|
-
|
|
7980
|
+
[[xml-raw-element]]
|
|
7981
|
+
==== Capturing raw XML content
|
|
7977
7982
|
|
|
7978
|
-
|
|
7979
|
-
|
|
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
|
-
|
|
7987
|
+
===== `raw: :element` on `map_element` — full element capture (recommended)
|
|
7982
7988
|
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
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
|
-
|
|
7988
|
-
|
|
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
|
-
|
|
7991
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7996
|
-
* attributes
|
|
7997
|
-
* text nodes
|
|
8041
|
+
`raw: :element` also works with collection attributes:
|
|
7998
8042
|
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8043
|
+
[source,ruby]
|
|
8044
|
+
----
|
|
8045
|
+
class MultiFragment < Lutaml::Model::Serializable
|
|
8046
|
+
attribute :fragments, :string, collection: true
|
|
8002
8047
|
|
|
8003
|
-
|
|
8004
|
-
|
|
8048
|
+
xml do
|
|
8049
|
+
element "container"
|
|
8050
|
+
map_element "fragment", to: :fragments, raw: :element
|
|
8051
|
+
end
|
|
8052
|
+
end
|
|
8053
|
+
----
|
|
8054
|
+
====
|
|
8005
8055
|
|
|
8006
|
-
|
|
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
|
|
|
@@ -1097,42 +1097,184 @@ end
|
|
|
1097
1097
|
====
|
|
1098
1098
|
|
|
1099
1099
|
|
|
1100
|
-
[[xml-map-all]]
|
|
1101
|
-
==== Mapping entire XML element into an attribute
|
|
1102
1100
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1101
|
+
[[xml-raw-element]]
|
|
1102
|
+
==== Capturing raw XML content
|
|
1105
1103
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1104
|
+
Lutaml::Model provides several mechanisms for capturing XML content as raw strings.
|
|
1105
|
+
Use these when you need to embed foreign XML vocabularies (SVG, MathML, XSL-FO) or
|
|
1106
|
+
preserve markup that your model doesn't need to parse.
|
|
1108
1107
|
|
|
1109
|
-
|
|
1108
|
+
===== `raw: :element` on `map_element` -- full element capture (recommended)
|
|
1110
1109
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1110
|
+
The `raw: :element` option captures a specific mapped element as a complete XML
|
|
1111
|
+
string, including its opening tag, attributes, children, and closing tag.
|
|
1112
|
+
This provides **lossless round-trip** fidelity -- the captured string is
|
|
1113
|
+
self-contained and serialized verbatim.
|
|
1114
1114
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1115
|
+
.Syntax
|
|
1116
|
+
[source,ruby]
|
|
1117
|
+
----
|
|
1118
|
+
xml do
|
|
1119
|
+
map_element "svg", to: :svg_data, raw: :element
|
|
1120
|
+
end
|
|
1121
|
+
----
|
|
1117
1122
|
|
|
1118
|
-
|
|
1119
|
-
|
|
1123
|
+
.Capturing an SVG element as raw XML
|
|
1124
|
+
[example]
|
|
1125
|
+
====
|
|
1126
|
+
[source,ruby]
|
|
1127
|
+
----
|
|
1128
|
+
class SvgContainer < Lutaml::Model::Serializable
|
|
1129
|
+
attribute :name, :string
|
|
1130
|
+
attribute :svg_data, :string
|
|
1120
1131
|
|
|
1121
|
-
|
|
1132
|
+
xml do
|
|
1133
|
+
element "container"
|
|
1134
|
+
map_element "name", to: :name
|
|
1135
|
+
map_element "svg", to: :svg_data, raw: :element
|
|
1136
|
+
end
|
|
1137
|
+
end
|
|
1138
|
+
----
|
|
1122
1139
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1140
|
+
[source,xml]
|
|
1141
|
+
----
|
|
1142
|
+
<container>
|
|
1143
|
+
<name>diagram</name>
|
|
1144
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
1145
|
+
<rect x="0" y="0" width="100" height="100" fill="red"/>
|
|
1146
|
+
</svg>
|
|
1147
|
+
</container>
|
|
1148
|
+
----
|
|
1126
1149
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1150
|
+
[source,ruby]
|
|
1151
|
+
----
|
|
1152
|
+
> doc = SvgContainer.from_xml(xml)
|
|
1153
|
+
> doc.name
|
|
1154
|
+
# => "diagram"
|
|
1155
|
+
> doc.svg_data
|
|
1156
|
+
# => "<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>"
|
|
1157
|
+
----
|
|
1130
1158
|
|
|
1131
|
-
|
|
1132
|
-
the
|
|
1159
|
+
The captured string round-trips correctly -- serializing the model back to XML
|
|
1160
|
+
outputs the raw element verbatim without escaping or wrapping.
|
|
1133
1161
|
|
|
1134
|
-
|
|
1162
|
+
`raw: :element` also works with collection attributes:
|
|
1135
1163
|
|
|
1164
|
+
[source,ruby]
|
|
1165
|
+
----
|
|
1166
|
+
class MultiFragment < Lutaml::Model::Serializable
|
|
1167
|
+
attribute :fragments, :string, collection: true
|
|
1168
|
+
|
|
1169
|
+
xml do
|
|
1170
|
+
element "container"
|
|
1171
|
+
map_element "fragment", to: :fragments, raw: :element
|
|
1172
|
+
end
|
|
1173
|
+
end
|
|
1174
|
+
----
|
|
1175
|
+
====
|
|
1176
|
+
|
|
1177
|
+
===== `raw: :content` on `map_element` -- inner content capture
|
|
1178
|
+
|
|
1179
|
+
The `raw: :content` option captures only the *inner XML* of the matched element,
|
|
1180
|
+
without the wrapper tags. The wrapper element is reconstructed from the mapping rule
|
|
1181
|
+
during serialization.
|
|
1182
|
+
|
|
1183
|
+
.Syntax
|
|
1184
|
+
[source,ruby]
|
|
1185
|
+
----
|
|
1186
|
+
xml do
|
|
1187
|
+
map_element "street", to: :street, raw: :content
|
|
1188
|
+
end
|
|
1189
|
+
----
|
|
1190
|
+
|
|
1191
|
+
.Capturing inner XML content
|
|
1192
|
+
[example]
|
|
1193
|
+
====
|
|
1194
|
+
[source,ruby]
|
|
1195
|
+
----
|
|
1196
|
+
class Address < Lutaml::Model::Serializable
|
|
1197
|
+
attribute :street, :string
|
|
1198
|
+
|
|
1199
|
+
xml do
|
|
1200
|
+
element "address"
|
|
1201
|
+
map_element "street", to: :street, raw: :content
|
|
1202
|
+
end
|
|
1203
|
+
end
|
|
1204
|
+
----
|
|
1205
|
+
|
|
1206
|
+
[source,xml]
|
|
1207
|
+
----
|
|
1208
|
+
<address><street><b>123</b> Main St</street></address>
|
|
1209
|
+
----
|
|
1210
|
+
|
|
1211
|
+
[source,ruby]
|
|
1212
|
+
----
|
|
1213
|
+
> doc = Address.from_xml(xml)
|
|
1214
|
+
> doc.street
|
|
1215
|
+
# => "<b>123</b> Main St"
|
|
1216
|
+
----
|
|
1217
|
+
====
|
|
1218
|
+
|
|
1219
|
+
NOTE: `raw: :content` is **lossy** -- namespace prefixes declared on the wrapper
|
|
1220
|
+
element are not captured. For lossless capture, use `raw: :element` instead.
|
|
1221
|
+
|
|
1222
|
+
===== Namespace behavior
|
|
1223
|
+
|
|
1224
|
+
Both `raw: :element` and `raw: :content` match elements by local name regardless
|
|
1225
|
+
of namespace or prefix:
|
|
1226
|
+
|
|
1227
|
+
* Elements with no namespace (`<svg>`)
|
|
1228
|
+
* Elements with an `xmlns` declaration on themselves (`<svg xmlns="...">`)
|
|
1229
|
+
* Elements inheriting a default namespace from a parent
|
|
1230
|
+
* Elements with an explicit namespace prefix (`<ns:svg>`)
|
|
1231
|
+
|
|
1232
|
+
This is intentional -- raw capture is designed to handle foreign XML vocabularies
|
|
1233
|
+
without needing model classes for them.
|
|
1234
|
+
|
|
1235
|
+
===== Round-trip fidelity comparison
|
|
1236
|
+
|
|
1237
|
+
| Aspect | `raw: :element` | `raw: :content` |
|
|
1238
|
+
|--------|----------------|-----------------|
|
|
1239
|
+
| Element name | Preserved (in string) | Reconstructed from rule |
|
|
1240
|
+
| Element attributes | Preserved (in string) | Lost unless separately mapped |
|
|
1241
|
+
| Inner content | Preserved (in string) | Preserved (in string) |
|
|
1242
|
+
| Namespace prefixes | Safe (declared in string) | May break if declared on wrapper |
|
|
1243
|
+
| Fidelity | **Lossless** | **Lossy** |
|
|
1244
|
+
|
|
1245
|
+
===== Wrapper model pattern for attribute extraction
|
|
1246
|
+
|
|
1247
|
+
Raw capture stores the element as a string. If you need to inspect or modify
|
|
1248
|
+
attributes on the captured element, use a wrapper model with `map_all`:
|
|
1249
|
+
|
|
1250
|
+
[source,ruby]
|
|
1251
|
+
----
|
|
1252
|
+
class SvgInner < Lutaml::Model::Serializable
|
|
1253
|
+
attribute :raw, :string
|
|
1254
|
+
|
|
1255
|
+
xml do
|
|
1256
|
+
element "svg"
|
|
1257
|
+
map_all to: :raw
|
|
1258
|
+
end
|
|
1259
|
+
end
|
|
1260
|
+
|
|
1261
|
+
class Container < Lutaml::Model::Serializable
|
|
1262
|
+
attribute :svg_data, SvgInner
|
|
1263
|
+
|
|
1264
|
+
xml do
|
|
1265
|
+
element "container"
|
|
1266
|
+
map_element "svg", to: :svg_data
|
|
1267
|
+
end
|
|
1268
|
+
end
|
|
1269
|
+
----
|
|
1270
|
+
|
|
1271
|
+
===== `map_all` -- root inner XML capture
|
|
1272
|
+
|
|
1273
|
+
The `map_all` directive captures the entire inner XML of the root element into
|
|
1274
|
+
a single attribute. It is **exclusive** -- it cannot be combined with other
|
|
1275
|
+
`map_element` or `map_content` mappings (only `map_attribute` is allowed).
|
|
1276
|
+
|
|
1277
|
+
.Syntax
|
|
1136
1278
|
[source,ruby]
|
|
1137
1279
|
----
|
|
1138
1280
|
xml do
|
|
@@ -1167,6 +1309,18 @@ end
|
|
|
1167
1309
|
----
|
|
1168
1310
|
====
|
|
1169
1311
|
|
|
1312
|
+
===== Deprecated: `attribute :x, :string, raw: true`
|
|
1313
|
+
|
|
1314
|
+
[WARNING]
|
|
1315
|
+
====
|
|
1316
|
+
`attribute :name, :string, raw: true` is deprecated. Use
|
|
1317
|
+
`map_element "name", to: :name, raw: :content` instead.
|
|
1318
|
+
====
|
|
1319
|
+
|
|
1320
|
+
This legacy syntax captures the inner XML of the matched element.
|
|
1321
|
+
It is equivalent to `raw: :content` on the mapping. Existing code continues
|
|
1322
|
+
to work but emits a deprecation warning.
|
|
1323
|
+
|
|
1170
1324
|
|
|
1171
1325
|
==== Mapping CDATA nodes
|
|
1172
1326
|
|
|
@@ -546,7 +546,13 @@ the current value is the same as the default value.
|
|
|
546
546
|
|
|
547
547
|
|
|
548
548
|
|
|
549
|
-
=== Attribute as raw string
|
|
549
|
+
=== Attribute as raw string (deprecated)
|
|
550
|
+
|
|
551
|
+
[WARNING]
|
|
552
|
+
====
|
|
553
|
+
`attribute :name, :string, raw: true` is deprecated.
|
|
554
|
+
Use `map_element "name", to: :name, raw: :content` instead.
|
|
555
|
+
====
|
|
550
556
|
|
|
551
557
|
An attribute can be set to read the value as raw string for XML, by using the `raw: true` option.
|
|
552
558
|
|