Module: Lutaml::Xml::Adapter::XmlParser

Included in:
BaseAdapter
Defined in:
lib/lutaml/xml/adapter/xml_parser.rb

Overview

Class methods for parsing XML input.

Extracted from BaseAdapter — parsing is a distinct lifecycle phase with no instance state dependency.

Subclasses must define:

  • MOXML_ADAPTER — Moxml adapter class for parsing
  • PARSED_ELEMENT_CLASS — element wrapper class
  • PARSE_ERROR_CLASS — error class to rescue (nil to skip)
  • EMPTY_DOCUMENT_ERROR_MESSAGE — error message for empty docs
  • EMPTY_DOCUMENT_ERROR_TYPE — :invalid_format or :parse_exception

Constant Summary collapse

TRUNCATION_FATAL_MARKER =

Recover-mode parsing must never masquerade input truncation as success.

moxml releases before 0.5.84 parsed Nokogiri documents without XML_PARSE_HUGE, so libxml2 capped its input buffer at 10 MB; longer documents tripped a fatal "Resource limit exceeded: Buffer size limit exceeded, try XML_PARSE_HUGE" error mid-input. In recover mode Nokogiri records that error on the document and returns the partial tree, so every node past the limit silently vanishes (lutaml-model#871). A resource-limit fatal means the engine stopped early with input left — refuse to deserialize the partial document instead of dropping trailing content without a trace.

moxml 0.5.84 and later always pass XML_PARSE_HUGE, so the Nokogiri path no longer truncates and this guard stays silent; it remains for older moxml releases and for any other adapter that reports the resource-limit family.

Other recover-mode fatals (e.g. an XML declaration after leading whitespace) do not drop content and keep the long-standing recover behavior; only the resource-limit family is truncating.

/Resource limit exceeded|Buffer size limit exceeded/

Instance Method Summary collapse

Instance Method Details

#parse(xml, options = {}) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/lutaml/xml/adapter/xml_parser.rb', line 18

def parse(xml, options = {})
  parse_encoding = encoding(xml, options)
  raw_xml = xml
  xml = normalize_xml_for_parse(xml)
  parsed = parse_with_moxml(xml, parse_encoding)
  assert_no_truncated_recovered_parse!(parsed)
  root_element = parsed.root

  raise_empty_document_error if root_element.nil?

  root = self::PARSED_ELEMENT_CLASS.new(root_element)
  doc_pis = extract_document_processing_instructions(parsed)
  root.processing_instructions = doc_pis unless doc_pis.empty?
  new(root, parse_encoding, **parse_document_options(raw_xml))
end