class SXRB::Callbacks
This class provides callbacks for SAX API which are configured with sxrb DSL. It's behavior is configured by DSL via Proxy
class objects, and should not be used outside of this scope. Currently it has only been tested with LibXML implementation of SAX, but set of method that object needs to provide is defined by standard, so using it with different backend should be automatic.
Public Class Methods
new()
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 18 def initialize @stack = [] @rules_map = Hash.new {|h,k| h[k] = Rules.new} end
Public Instance Methods
add_callback(type, rule_path, &block)
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 62 def add_callback(type, rule_path, &block) @rules_map[Regexp.new "^#{rule_path}$"].tap do |rules| rules.rules[type] = block rules.recursive = (type == :element) # true / false end end
add_rule(rule, rule_path, options)
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 70 def add_rule(rule, rule_path, options) operator = options[:recursive] ? '.*' : ' ' new_rule = rule_path + operator + rule new_rule.strip end
on_characters(chars)
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 34 def on_characters(chars) if @stack.last.is_a? TextNode @stack.last.append_text chars else TextNode.new(chars).tap do |node| invoke_callback(:characters, node) @stack.push node @current_element.append node if @current_element end end end
on_end_element_ns(name, prefix, uri)
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 47 def on_end_element_ns(name, prefix, uri) @stack.pop if @stack.last.is_a? TextNode if @current_element invoke_callback(:element, @current_element) if current_matching_rules.any?(&:recursive) @current_element = @current_element.parent end invoke_callback(:end, @stack.last) @stack.pop.tap do |node| raise SXRB::TagMismatchError if node.name != name end end
on_start_element_ns(name, attributes, prefix, uri, namespaces)
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 24 def on_start_element_ns(name, attributes, prefix, uri, namespaces) Node.new(name, attributes, prefix, uri, namespaces).tap do |node| @stack.push(node) invoke_callback(:start, node) @current_element.append node if @current_element @current_element = node if current_matching_rules.any?(&:recursive) || @current_element end end
Private Instance Methods
current_matching_rules()
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 86 def current_matching_rules @rules_map.each_pair. select {|rule, value| current_rule_path =~ rule}. map {|rule, value| value} end
current_rule_path()
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 93 def current_rule_path @stack.map(&:name).join(' ') end
invoke_callback(type, *args)
click to toggle source
@api private
# File lib/sxrb/callbacks.rb, line 79 def invoke_callback(type, *args) current_matching_rules. map {|value| value.rules[type]}. compact.each {|callback| callback.call(*args)} end