Class: Moxml::Adapter::HeadedOx
- Defined in:
- lib/moxml/adapter/headed_ox.rb
Overview
HeadedOx adapter - combines Ox’s fast parsing with Moxml’s XPath engine.
This adapter uses:
-
Ox for XML parsing (fast C-based parser)
-
Moxml::XPath engine for comprehensive XPath 1.0 support
Unlike the standard Ox adapter which has limited XPath support through Ox’s locate() method, HeadedOx provides full XPath 1.0 functionality including all axes, predicates, and 27 standard functions.
Class Method Summary collapse
-
.at_xpath(node, expression, namespaces = {}) ⇒ Moxml::Node, ...
Execute XPath query and return first result.
-
.capabilities ⇒ Hash
Report adapter capabilities.
-
.parse(xml, _options = {}) ⇒ Object
Override parse to use HeadedOx context instead of Ox context.
-
.xpath(node, expression, namespaces = {}) ⇒ Moxml::NodeSet, Object
Execute XPath query using Moxml’s XPath engine.
-
.xpath_supported? ⇒ Boolean
Check if XPath is supported.
Methods inherited from Ox
add_child, add_next_sibling, add_previous_sibling, ancestors, attribute_element, attributes, cdata_content, children, comment_content, create_document, create_native_cdata, create_native_comment, create_native_declaration, create_native_doctype, create_native_element, create_native_namespace, create_native_processing_instruction, create_native_text, declaration_attribute, doctype_external_id, doctype_name, doctype_system_id, document, duplicate_node, get_attribute, get_attribute_value, inner_text, namespace, namespace_definitions, namespace_prefix, namespace_uri, next_sibling, node_name, node_type, parent, patch_node, previous_sibling, processing_instruction_content, processing_instruction_target, remove, remove_attribute, replace, replace_children, root, sax_parse, serialize, set_attribute, set_attribute_name, set_attribute_value, set_cdata_content, set_comment_content, set_declaration_attribute, set_namespace, set_node_name, set_processing_instruction_content, set_root, set_text_content, text_content, unpatch_node
Methods inherited from Base
create_cdata, create_comment, create_declaration, create_doctype, create_document, create_element, create_namespace, create_processing_instruction, create_text, duplicate_node, patch_node, prepare_for_new_document, sax_parse, sax_supported?, set_attribute_name, set_attribute_value, set_root
Methods included from XmlUtils
#encode_entities, #normalize_xml_value, #validate_comment_content, #validate_declaration_encoding, #validate_declaration_standalone, #validate_declaration_version, #validate_element_name, #validate_pi_target, #validate_prefix, #validate_uri
Class Method Details
.at_xpath(node, expression, namespaces = {}) ⇒ Moxml::Node, ...
Execute XPath query and return first result
110 111 112 113 |
# File 'lib/moxml/adapter/headed_ox.rb', line 110 def at_xpath(node, expression, namespaces = {}) result = xpath(node, expression, namespaces) result.is_a?(NodeSet) ? result.first : result end |
.capabilities ⇒ Hash
Report adapter capabilities
HeadedOx extends Ox’s capabilities with full XPath support through Moxml’s XPath engine
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 |
# File 'lib/moxml/adapter/headed_ox.rb', line 128 def capabilities { # Core adapter capabilities parse: true, # Parsing capabilities (inherited from Ox) sax_parsing: true, namespace_aware: true, namespace_support: :partial, dtd_support: true, parsing_speed: :fast, # XPath capabilities (provided by Moxml's XPath engine) xpath_support: :full, xpath_full: true, xpath_axes: :partial, # 6 of 13 axes: child, descendant, descendant-or-self, self, attribute, parent xpath_functions: :complete, # All 27 XPath 1.0 functions xpath_predicates: true, xpath_namespaces: true, xpath_variables: true, # Serialization capabilities (inherited from Ox) namespace_serialization: true, pretty_print: true, # Known limitations schema_validation: false, xslt_support: false, } end |
.parse(xml, _options = {}) ⇒ Object
Override parse to use HeadedOx context instead of Ox context
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/moxml/adapter/headed_ox.rb', line 29 def parse(xml, = {}) native_doc = begin result = ::Ox.parse(xml) # result can be either Document or Element if result.is_a?(::Ox::Document) result else doc = ::Ox::Document.new doc << result doc end rescue ::Ox::ParseError => e raise Moxml::ParseError.new( e., source: xml.is_a?(String) ? xml[0..100] : nil, ) end # Use :headed_ox context instead of :ox DocumentBuilder.new(Context.new(:headed_ox)).build(native_doc) end |
.xpath(node, expression, namespaces = {}) ⇒ Moxml::NodeSet, Object
Execute XPath query using Moxml’s XPath engine
This overrides the Ox adapter’s xpath method which uses locate().
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/moxml/adapter/headed_ox.rb', line 60 def xpath(node, expression, namespaces = {}) # If we receive a native node, wrap it first # Document#xpath passes @native, but our compiled XPath needs Moxml nodes unless node.is_a?(Moxml::Node) # Determine the context from the node if possible # For now, create a basic context for wrapped nodes ctx = Context.new(:headed_ox) # Wrap the native node - don't rebuild the whole document node = Node.wrap(node, ctx) end # Parse XPath expression to AST ast = XPath::Parser.parse(expression) # Compile AST to executable Proc using class method proc = XPath::Compiler.compile_with_cache(ast, namespaces: namespaces) # Execute on the node (now guaranteed to be wrapped Moxml node) result = proc.call(node) # Wrap Array results in NodeSet, return other types directly case result when Array # Deduplicate by native object identity to handle descendant-or-self # which may yield the same native node multiple times nodeset = NodeSet.new(result, node.context) nodeset.uniq_by_native when NodeSet # Deduplicate NodeSet results as well result.uniq_by_native else # Scalar values (string, number, boolean) - return as-is result end rescue StandardError => e raise Moxml::XPathError.new( "XPath execution failed: #{e.}", expression: expression, adapter: "HeadedOx", node: node, ) end |
.xpath_supported? ⇒ Boolean
Check if XPath is supported
118 119 120 |
# File 'lib/moxml/adapter/headed_ox.rb', line 118 def xpath_supported? true end |