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

#attribute_orderObject

Returns the value of attribute attribute_order.



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

def attribute_order
  @attribute_order
end

#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:



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

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.



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

def mixed=(value)
  @mixed = value
end

#ordered=(value) ⇒ Object (writeonly)

Sets the attribute ordered

Parameters:

  • value

    the value to set the attribute ordered to.



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

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.



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

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.



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

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



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
169
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 119

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



250
251
252
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 250

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



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

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

#mixed?Boolean

Returns:

  • (Boolean)


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

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)


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

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



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

def original_namespace_uri
  @__xml_original_namespace_uri
end

#original_namespace_uri=(value) ⇒ Object



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

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)



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
238
239
240
241
242
243
244
# File 'lib/lutaml/xml/serialization/instance_methods.rb', line 204

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

  # Force eager plan building when adapter is being overridden,
  # to dereference adapter-specific native nodes before the switch.
  if @pending_plan_root_element && options[:_adapter_override]
    import_declaration_plan
  end

  # 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



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

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



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

def raw_schema_location
  @raw_schema_location
end

#raw_schema_location=(value) ⇒ Object



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

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:



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

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



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

def xml_declaration
  @xml_declaration
end

#xml_declaration=(value) ⇒ Object



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

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.



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

def xml_namespace_prefix
  @__xml_namespace_prefix
end

#xml_namespace_prefix=(value) ⇒ Object



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

def xml_namespace_prefix=(value)
  @__xml_namespace_prefix = value
end

#xml_ns_prefixesObject



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

def xml_ns_prefixes
  @__xml_ns_prefixes
end

#xml_ns_prefixes=(value) ⇒ Object



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

def xml_ns_prefixes=(value)
  @__xml_ns_prefixes = value
end