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, #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
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 55 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).
51 52 53 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 51 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:”
40 41 42 43 44 45 46 47 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 40 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
75 76 77 78 79 80 81 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 75 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
146 147 148 149 150 151 152 153 154 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 146 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.public_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
161 162 163 164 165 166 167 168 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 161 def attribute_value_for(element, rule) return element.public_send(rule.to) unless rule.delegate delegate_obj = element.public_send(rule.delegate) return nil if delegate_obj.nil? delegate_obj.public_send(rule.to) end |
#attributes_hash(element) ⇒ Hash
Build attributes hash from element attributes
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 198 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)
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 90 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
136 137 138 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 136 def order root.order end |
#ordered?(element, options = {}) ⇒ Boolean
Check if element has ordered content
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 119 def ordered?(element, = {}) return false unless element.is_a?(Lutaml::Model::Serialize) 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
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 176 def process_content_mapping(element, content_rule, xml, mapper_class) return unless content_rule if content_rule.custom_methods[:to] mapper_class.new.public_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
110 111 112 |
# File 'lib/lutaml/xml/adapter/base_adapter.rb', line 110 def render_element?(rule, element, value) rule.render?(value, element) end |