Module: Lutaml::Xml::Serialization::FormatConversion

Defined in:
lib/lutaml/xml/serialization/format_conversion.rb

Overview

XML-specific format conversion hooks for Serialize module

This module provides XML-specific serialization logic that extends the format-agnostic Lutaml::Model::Serialize::FormatConversion.

It is prepended into Serialize::ClassMethods when XML format is loaded, overriding the hook methods defined in FormatConversion.

Instance Method Summary collapse

Instance Method Details

#add_format_specific_model_methods(klass) ⇒ Object

Add XML-specific model methods (ordered, mixed, element_order, etc.) when ‘model CustomClass` is used with a plain Ruby class.

Parameters:

  • klass (Class)

    The model class



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 161

def add_format_specific_model_methods(klass)
  super
  Lutaml::Model::Utils.add_boolean_accessor_if_not_defined(klass,
                                                           :ordered)
  Lutaml::Model::Utils.add_boolean_accessor_if_not_defined(klass,
                                                           :mixed)
  Lutaml::Model::Utils.add_accessor_if_not_defined(klass,
                                                   :element_order)
  Lutaml::Model::Utils.add_accessor_if_not_defined(klass, :encoding)
  Lutaml::Model::Utils.add_accessor_if_not_defined(klass, :doctype)
  # XML namespace metadata accessors for custom model classes
  %i[xml_namespace_prefix xml_ns_prefixes original_namespace_uri
     xml_declaration raw_schema_location].each do |attr|
    Lutaml::Model::Utils.add_accessor_if_not_defined(klass, attr)
  end
end

#apply_namespace_overrides(options) ⇒ Hash

Apply namespace prefix overrides for XML serialization

Parameters:

  • options (Hash)

    The options hash

Returns:

  • (Hash)

    The modified options hash



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 182

def apply_namespace_overrides(options)
  namespaces = options[:namespaces]
  return options unless namespaces.is_a?(Array)

  # Build a namespace URI to prefix mapping
  ns_prefix_map = {}
  namespaces.each do |ns_config|
    if ns_config.is_a?(Hash)
      ns_class = ns_config[:namespace]
      prefix = ns_config[:prefix]

      if ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace && prefix
        ns_prefix_map[ns_class.uri] = prefix.to_s
      end
    end
  end

  unless ns_prefix_map.empty?
    options[:namespace_prefix_map] = ns_prefix_map
  end
  options
end

#choice(min: 1, max: 1, format: :xml) ⇒ Object

Override choice to set format: :xml so Choice knows which format it belongs to.



48
49
50
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 48

def choice(min: 1, max: 1, format: :xml, &)
  super
end

#namespace(ns_class = nil) ⇒ Class?

Deprecated.

Use namespace inside ‘xml do … end` blocks instead.

Class-level namespace directive for XML.

Parameters:

  • ns_class (Class, nil) (defaults to: nil)

    XmlNamespace class to associate with this model

Returns:

  • (Class, nil)

    the XmlNamespace class



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 20

def namespace(ns_class = nil)
  if ns_class
    unless ns_class.is_a?(Class) && ns_class < Lutaml::Xml::Namespace
      raise ArgumentError,
            "namespace must be an XmlNamespace class, got #{ns_class.class}"
    end

    warn_class_level_namespace_usage(ns_class)
    @namespace_class = ns_class
  end
  @namespace_class
end

#namespace_prefixString?

Get the default namespace prefix for this Model

Returns:

  • (String, nil)

    the namespace prefix



43
44
45
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 43

def namespace_prefix
  @namespace_class&.prefix_default
end

#namespace_uriString?

Get the namespace URI for this Model

Returns:

  • (String, nil)

    the namespace URI



36
37
38
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 36

def namespace_uri
  @namespace_class&.uri
end

#post_process_mapping(format) ⇒ Object

XML-specific post-processing after mapping DSL evaluation

Parameters:

  • format (Symbol)

    The format



71
72
73
74
75
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 71

def post_process_mapping(format)
  return super unless format == :xml

  check_sort_configs!
end

#pre_deserialize_hook(format, register) ⇒ Object

XML-specific pre-deserialization: resolve XML mapping imports

Parameters:

  • format (Symbol)

    The format

  • register (Symbol)

    The register



81
82
83
84
85
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 81

def pre_deserialize_hook(format, register)
  return super unless format == :xml

  mappings[:xml]&.ensure_mappings_imported!(register)
end

#pre_serialize_hook(format, register) ⇒ Object

XML-specific pre-serialization: resolve XML mapping imports

Parameters:

  • format (Symbol)

    The format

  • register (Symbol)

    The register



151
152
153
154
155
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 151

def pre_serialize_hook(format, register)
  return super unless format == :xml

  mappings[:xml]&.ensure_mappings_imported!(register)
end

#prepare_to_options(format, instance, options) ⇒ Hash

XML-specific options preparation for serialization

Parameters:

  • format (Symbol)

    The format

  • instance (Object)

    The model instance

  • options (Hash)

    The options hash

Returns:

  • (Hash)

    The modified options hash



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 111

def prepare_to_options(format, instance, options)
  return super unless format == :xml

  options[:mapper_class] = self

  # Handle prefix option for XML
  if options.key?(:prefix)
    prefix_option = options[:prefix]
    mappings_for(:xml)

    case prefix_option
    when true
      options[:use_prefix] = true
    when String
      options[:use_prefix] = prefix_option
    when false, :default, nil
      options[:use_prefix] = false
    end
    options.delete(:prefix)
  end

  # Apply namespace prefix overrides for XML format
  if options[:namespaces]
    options = apply_namespace_overrides(options)
  end

  # Retrieve stored declaration plan from model instance for namespace preservation
  if instance.is_a?(Lutaml::Model::Serialize) &&
      !options.key?(:stored_xml_declaration_plan)
    stored_plan = instance.import_declaration_plan
    options[:stored_xml_declaration_plan] = stored_plan if stored_plan
  end

  options
end

#process_mapping(format, *args) ⇒ Object

Override process_mapping for XML format to handle mapping class inheritance.

When ‘xml SomeMapping` is called with a mapping class argument, inherits mappings from the class instead of using a DSL block.

Parameters:

  • format (Symbol)

    The format

  • args (Array)

    Additional arguments (mapping class for XML)

  • block (Proc)

    The DSL block



60
61
62
63
64
65
66
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 60

def process_mapping(format, *args, &)
  if format == :xml && args.any? && args.first.is_a?(Class) && args.first < Lutaml::Xml::Mapping
    process_xml_mapping_class_inheritance(args.first, &)
  else
    super
  end
end

#validate_document(format, doc, options, register) ⇒ Object

XML-specific document validation: root mapping, encoding, doctype

Parameters:

  • format (Symbol)

    The format

  • doc (Object)

    The parsed document

  • options (Hash)

    Options hash (modified in place)

  • register (Symbol)

    The register

Raises:



93
94
95
96
97
98
99
100
101
102
103
# File 'lib/lutaml/xml/serialization/format_conversion.rb', line 93

def validate_document(format, doc, options, register)
  return super unless format == :xml

  valid = root?(register) || options[:from_collection]
  raise Lutaml::Model::NoRootMappingError.new(self) unless valid

  options[:encoding] = doc.encoding
  if doc.respond_to?(:doctype) && doc.doctype
    options[:doctype] = doc.doctype
  end
end