Class: Lutaml::Xml::Adapter::BaseAdapter Abstract
- Extended by:
- AdapterHelpers, XmlParser, DocTypeExtractor
- Includes:
- NamespaceUriCollector, PlanBasedBuilder, XmlSerializer, DeclarationHandler, PolymorphicValueHandler
- Defined in:
- lib/lutaml/xml/adapter/base_adapter.rb
Overview
Subclass and implement required methods
Base class for XML adapters providing shared functionality.
This class extracts common code from NokogiriAdapter, OxAdapter, OgaAdapter, and RexmlAdapter to reduce duplication and ensure consistent behavior across adapters.
Subclasses must implement:
-
MOXML_ADAPTER - Moxml adapter implementation for parsing
-
BUILDER_CLASS - Builder implementation for serialization
-
PARSED_ELEMENT_CLASS - Adapter element class returned by parsing
Direct Known Subclasses
Constant Summary collapse
- EMPTY_DOCUMENT_ERROR_MESSAGE =
"Document has no root element. " \ "The XML may be empty, contain only whitespace, " \ "or consist only of an XML declaration."
- EMPTY_DOCUMENT_ERROR_TYPE =
:invalid_format- PARSE_ERROR_CLASS =
nil
Constants included from AdapterHelpers
Instance Attribute Summary
Attributes inherited from Document
#doctype, #encoding, #parsed_doc, #register, #root, #xml_declaration
Class Method Summary collapse
- .extract_document_processing_instructions(moxml_doc) ⇒ Object
-
.fpi?(uri) ⇒ Boolean
Detect if a string is an FPI (Formal Public Identifier), not a valid namespace URI.
-
.fpi_to_urn(fpi) ⇒ Object
Convert a Formal Public Identifier (FPI) to a URN per RFC 3151.
-
.namespaced_name(namespace_uri, prefix, name) ⇒ String
Build a namespaced element name.
Instance Method Summary collapse
-
#attribute_definition_for(element, rule, mapper_class: nil) ⇒ Attribute?
Get attribute definition for an element and rule.
-
#attribute_value_for(element, rule) ⇒ Object?
Get attribute value for an element and rule.
-
#attributes_hash(element) ⇒ Hash
Build attributes hash from element attributes.
-
#determine_encoding(options) ⇒ String?
Determine encoding for XML output Returns nil when encoding is explicitly set to nil (to not set encoding at all).
- #order ⇒ Object
-
#ordered?(element, options = {}) ⇒ Boolean
Check if element has ordered content.
-
#process_content_mapping(element, content_rule, xml, mapper_class) ⇒ Object
Process content mapping for an element.
-
#render_element?(rule, element, value) ⇒ Boolean
Check if an element should be rendered.
Methods included from DocTypeExtractor
Methods included from AdapterHelpers
name_of, namespaced_attr_name, namespaced_name_of, node_type_of, prefixed_name_of, text_node?
Methods included from XmlParser
Methods included from PlanBasedBuilder
#build_element_with_plan, #build_ordered_element_with_plan, #build_unordered_children_with_plan, #build_xml_element
Methods included from XmlSerializer
#add_value, #build_serializable_xml, #build_xml_element_with_plan, #to_xml
Methods included from NamespaceUriCollector
#collect_original_namespace_uris
Methods included from PolymorphicValueHandler
Methods included from DeclarationHandler
extract_attribute, extract_xml_declaration, #generate_declaration, #generate_doctype_declaration, #should_include_declaration?
Methods inherited from Document
#add_value, #attributes, #cdata, #children, #declaration, #doctype_declaration, #element_children, #element_children_index, encoding, #initialize, name_of, namespaced_name_of, order_of, parse, #parse_element, #text, text_of, #to_h, type
Constructor Details
This class inherits a constructor from Lutaml::Xml::Document
Class Method Details
.extract_document_processing_instructions(moxml_doc) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 64 def self.extract_document_processing_instructions(moxml_doc) pis = [] root = moxml_doc.root moxml_doc.children.each do |child| break if child == root next unless child.is_a?(Moxml::ProcessingInstruction) pis << Lutaml::Xml::DataModel::XmlProcessingInstruction.new( child.target, child.content.to_s.strip ) end pis end |
.fpi?(uri) ⇒ Boolean
Detect if a string is an FPI (Formal Public Identifier), not a valid namespace URI. FPIs start with -// or +// (SGML-style, not a URI scheme).
60 61 62 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 60 def self.fpi?(uri) uri.is_a?(String) && uri.start_with?("-//", "+//") end |
.fpi_to_urn(fpi) ⇒ Object
Convert a Formal Public Identifier (FPI) to a URN per RFC 3151. FPI examples: “-//OASIS//DTD XML Exchange Table Model 19990315//EN” Returns nil if the string is not an FPI.
RFC 3151 format: urn:publicid:prefix:+/-//registrant//description//language// Conversion: replace spaces with +, prepend “urn:publicid:”
49 50 51 52 53 54 55 56 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 49 def self.fpi_to_urn(fpi) return nil unless fpi.is_a?(String) && fpi.start_with?("-//", "+//") # Replace spaces with + per RFC 3151 normalized = fpi.gsub(" ", "+") "urn:publicid:#{normalized}" end |
.namespaced_name(namespace_uri, prefix, name) ⇒ String
Build a namespaced element name
84 85 86 87 88 89 90 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 84 def self.namespaced_name(namespace_uri, prefix, name) if namespace_uri prefix ? "#{prefix}:#{name}" : name else name end end |
Instance Method Details
#attribute_definition_for(element, rule, mapper_class: nil) ⇒ Attribute?
Get attribute definition for an element and rule
155 156 157 158 159 160 161 162 163 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 155 def attribute_definition_for(element, rule, mapper_class: nil) klass = mapper_class || element.class return klass.attributes[rule.to] unless rule.delegate delegated_obj = element.send(rule.delegate) return nil if delegated_obj.nil? delegated_obj.class.attributes[rule.to] end |
#attribute_value_for(element, rule) ⇒ Object?
Get attribute value for an element and rule
170 171 172 173 174 175 176 177 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 170 def attribute_value_for(element, rule) return element.send(rule.to) unless rule.delegate delegate_obj = element.send(rule.delegate) return nil if delegate_obj.nil? delegate_obj.send(rule.to) end |
#attributes_hash(element) ⇒ Hash
Build attributes hash from element attributes
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 207 def attributes_hash(element) result = Lutaml::Model::MappingHash.new attribute_values(element) do |attr| if schema_location_attribute?(attr) result["__schema_location"] = { namespace: attr.namespace, prefix: attribute_namespace_prefix(attr), schema_location: attr.value, } else result[attribute_hash_name(attr)] = attr.value end end result end |
#determine_encoding(options) ⇒ String?
Determine encoding for XML output Returns nil when encoding is explicitly set to nil (to not set encoding at all)
99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 99 def determine_encoding() if .key?(:encoding) # Return nil if encoding is explicitly nil (don't set encoding) # Return the value otherwise [:encoding] elsif .key?(:parse_encoding) [:parse_encoding] elsif @encoding && @encoding.to_s.upcase != "ASCII-8BIT" @encoding else "UTF-8" end end |
#order ⇒ Object
145 146 147 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 145 def order root.order end |
#ordered?(element, options = {}) ⇒ Boolean
Check if element has ordered content
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 128 def ordered?(element, = {}) return false unless element.respond_to?(:element_order) mapper_class = [:mapper_class] xml_mapping = mapper_class&.mappings_for(:xml) # Class mapping is the authoritative source for ordered/mixed. # Instance @ordered/@mixed are stale after class definition changes. if xml_mapping&.mixed_content? || xml_mapping&.ordered? return !element.element_order.nil? && !element.element_order.empty? end return [:mixed_content] if .key?(:mixed_content) false end |
#process_content_mapping(element, content_rule, xml, mapper_class) ⇒ Object
Process content mapping for an element
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 185 def process_content_mapping(element, content_rule, xml, mapper_class) return unless content_rule if content_rule.custom_methods[:to] mapper_class.new.send( content_rule.custom_methods[:to], element, xml.parent, xml, ) else text = content_rule.serialize(element) text = text.join if text.is_a?(Array) xml.add_text(xml, text, cdata: content_rule.cdata) end end |
#render_element?(rule, element, value) ⇒ Boolean
Check if an element should be rendered
119 120 121 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 119 def render_element?(rule, element, value) rule.render?(value, element) end |