Module: Lutaml::Xml::Serialization::InstanceMethods

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

Overview

XML-specific instance methods for Serialize.

Prepended into Lutaml::Model::Serialize when XML is loaded. Provides XML-specific instance-level behavior:

  • XML instance attributes (element_order, schema_location, encoding, doctype, ordered, mixed)

  • xml_declaration_plan writer / import_declaration_plan method

  • XML-specific format options preparation

  • XML root mapping validation

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#doctypeObject

Returns the value of attribute doctype.



19
20
21
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 19

def doctype
  @doctype
end

#element_orderObject

Returns the value of attribute element_order.



19
20
21
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 19

def element_order
  @element_order
end

#encodingObject

Returns the value of attribute encoding.



19
20
21
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 19

def encoding
  @encoding
end

#import_declaration_planDeclarationPlan?

Build or return the cached declaration plan.

When import_declaration_plan: :lazy (default), builds the plan from pre-collected namespace data on first call. No-op when no pending data exists (:eager already set, :skip, or programmatic creation).

Returns:



80
81
82
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 80

def import_declaration_plan
  @import_declaration_plan ||= build_pending_declaration_plan
end

#mixed=(value) ⇒ Object (writeonly)

Sets the attribute mixed

Parameters:

  • value

    the value to set the attribute mixed to.



83
84
85
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 83

def mixed=(value)
  @mixed = value
end

#ordered=(value) ⇒ Object (writeonly)

Sets the attribute ordered

Parameters:

  • value

    the value to set the attribute ordered to.



83
84
85
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 83

def ordered=(value)
  @ordered = value
end

#pending_namespace_dataObject

Store pre-collected namespace data for lazy plan building. This is a plain Hash (no adapter objects) collected during from_xml.



23
24
25
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 23

def pending_namespace_data
  @pending_namespace_data
end

#pending_plan_root_elementObject

Store root element reference for truly lazy plan building. Set in :lazy mode during deserialization; consumed on first to_xml. Released after plan is built to allow GC of the DOM tree.



28
29
30
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 28

def pending_plan_root_element
  @pending_plan_root_element
end

#schema_locationObject

Returns the value of attribute schema_location.



19
20
21
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 19

def schema_location
  @schema_location
end

Instance Method Details

#each_mixed_contentself, Enumerator

Iterate over content in document order.

Yields String (text nodes) and Lutaml::Model::Serializable (inline elements). Works for both:

- Mixed content: text + elements interleaved
- Ordered content: elements only, but in specific sequence

Returns self when called with a block, Enumerator when called without.

Examples:

para.each_mixed_content { |item| puts item.inspect }
# For mixed content => "Hello ", #<Emphasis>, "!"
# For ordered only => #<Item "first">, #<Item "second">

Returns:

  • (self, Enumerator)

    self if block given, Enumerator otherwise



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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 118

def each_mixed_content
  return to_enum(:each_mixed_content) unless block_given?
  # Only iterate for mixed or ordered content
  return unless element_order && (mixed? || ordered?)

  # Get the XML mapping for this class
  xml_mapping = self.class.mappings_for(:xml, lutaml_register)
  return unless xml_mapping

  # Build lookup: element name -> attribute name
  # @elements maps namespaced names to MappingRule or Array<MappingRule>
  # Note: rule.name is a Symbol but el.name from element_order is a String
  # We store both to handle the mismatch
  element_to_attr = {}
  xml_mapping.mapping_elements_hash.each_value do |rule_or_array|
    Array(rule_or_array).each do |rule|
      element_to_attr[rule.name] = rule.to
      if rule.name.is_a?(Symbol)
        element_to_attr[rule.name.to_s] =
          rule.to
      end
    end
  end

  # Track current index for each collection attribute
  # Using ::Hash to avoid conflict with Lutaml::Model::Hash
  collection_indices = ::Hash.new(0)

  element_order.each do |el|
    if el.text?
      # Text node - yield the text content (skip whitespace-only)
      text = el.text_content
      yield(text) if text && !text.strip.empty?
    elsif el.element?
      # Element node - look up mapped collection and get next item
      attr_name = element_to_attr[el.name]
      next unless attr_name

      collection = send(attr_name)
      next unless collection.is_a?(Array)

      index = collection_indices[attr_name]
      collection_indices[attr_name] += 1

      obj = collection[index]
      yield(obj) if obj
    end
  end

  self
end

#format_element_sequences(register) ⇒ Array?

XML-specific element sequences for validation

Parameters:

  • register (Symbol, nil)

    The register context

Returns:

  • (Array, nil)

    Element sequences from XML mapping



243
244
245
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 243

def format_element_sequences(register)
  self.class.mappings_for(:xml, register)&.element_sequence
end

#initialize(attrs = {}, options = {}) ⇒ Object

Override initialize to extract XML-specific attrs



171
172
173
174
175
176
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 171

def initialize(attrs = {}, options = {})
  super
  set_ordering(attrs)
  set_schema_location(attrs)
  set_doctype(attrs)
end

#mixed?Boolean

Returns:

  • (Boolean)


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

def mixed?
  klass = self.class
  if klass.is_a?(Class) && klass.include?(Lutaml::Model::Serialize)
    klass.mappings_for(:xml, lutaml_register)&.mixed_content? || false
  else
    !!@mixed
  end
end

#ordered?Boolean

Returns:

  • (Boolean)


85
86
87
88
89
90
91
92
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 85

def ordered?
  klass = self.class
  if klass.is_a?(Class) && klass.include?(Lutaml::Model::Serialize)
    klass.mappings_for(:xml, lutaml_register)&.ordered? || false
  else
    !!@ordered
  end
end

#original_namespace_uriObject



49
50
51
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 49

def original_namespace_uri
  @__xml_original_namespace_uri
end

#original_namespace_uri=(value) ⇒ Object



53
54
55
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 53

def original_namespace_uri=(value)
  @__xml_original_namespace_uri = value
end

#prepare_instance_format_options(format, options) ⇒ Object

XML-specific instance options preparation

Parameters:

  • format (Symbol)

    The format

  • options (Hash)

    Options hash (modified in place)



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 203

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

  # Handle prefix option (converts to use_prefix for transformation phase)
  if options.key?(:prefix)
    prefix_option = options[:prefix]
    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

  options[:parse_encoding] = encoding if encoding
  options[:doctype] = doctype if doctype

  # Pass XML declaration info for XML Declaration Preservation
  if instance_variable_defined?(:@xml_declaration) && @xml_declaration
    options[:xml_declaration] = @xml_declaration
  end

  # Pass input namespaces for Namespace Preservation
  if instance_variable_defined?(:@xml_input_namespaces) && @xml_input_namespaces&.any?
    options[:input_namespaces] = @xml_input_namespaces
  end

  # Pass stored DeclarationPlan for format preservation.
  if import_declaration_plan
    options[:stored_xml_declaration_plan] = import_declaration_plan
  end
end

#pretty_print_instance_variablesObject

Extend INTERNAL_ATTRIBUTES with XML-specific ones



179
180
181
182
183
184
185
186
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 179

def pretty_print_instance_variables
  xml_internals = %i[@import_declaration_plan @xml_input_namespaces
                     @pending_namespace_data @pending_plan_root_element
                     @__xml_namespace_prefix
                     @__xml_ns_prefixes @__xml_original_namespace_uri
                     @xml_declaration @raw_schema_location]
  super - xml_internals
end

#raw_schema_locationObject



65
66
67
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 65

def raw_schema_location
  @raw_schema_location
end

#raw_schema_location=(value) ⇒ Object



69
70
71
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 69

def raw_schema_location=(value)
  @raw_schema_location = value
end

#validate_root_mapping!(format, options) ⇒ Object

XML-specific root mapping validation

Parameters:

  • format (Symbol)

    The format

  • options (Hash)

    Options hash

Raises:



192
193
194
195
196
197
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 192

def validate_root_mapping!(format, options)
  return super unless format == :xml
  return if options[:collection] || self.class.root?(lutaml_register)

  raise Lutaml::Model::NoRootMappingError.new(self.class)
end

#xml_declarationObject



57
58
59
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 57

def xml_declaration
  @xml_declaration
end

#xml_declaration=(value) ⇒ Object



61
62
63
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 61

def xml_declaration=(value)
  @xml_declaration = value
end

#xml_namespace_prefixObject

XML namespace metadata for doubly-defined and alias support. These carry information from deserialization to serialization. Accessor methods use the @__ prefixed ivars for backward compatibility.



33
34
35
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 33

def xml_namespace_prefix
  @__xml_namespace_prefix
end

#xml_namespace_prefix=(value) ⇒ Object



37
38
39
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 37

def xml_namespace_prefix=(value)
  @__xml_namespace_prefix = value
end

#xml_ns_prefixesObject



41
42
43
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 41

def xml_ns_prefixes
  @__xml_ns_prefixes
end

#xml_ns_prefixes=(value) ⇒ Object



45
46
47
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 45

def xml_ns_prefixes=(value)
  @__xml_ns_prefixes = value
end