Sha256: da22ab5aee88ba637582faf9e5d043306b32b83688d315d51fb514307745662f

Contents?: true

Size: 1.95 KB

Versions: 1

Compression:

Stored size: 1.95 KB

Contents

require "nokogiri"

module SAXMachine
  class SAXHandler < Nokogiri::XML::SAX::Document
    attr_reader :stack

    def initialize(object)
      @stack = [[object, nil, ""]]
      @parsed_configs = {}
    end

    def characters(string)
      object, config, value = stack.last
      value << string
    end
    alias :cdata_block :characters

    def start_element(name, attrs = [])
      object, config, value = stack.last
      return unless object.class.respond_to?(:sax_config)
      
      sax_config = object.class.sax_config
      attrs.flatten!

      if collection_config = sax_config.collection_config(name, attrs)
        stack.push [object = collection_config.data_class.new, collection_config, ""]
        object, sax_config = object, object.class.sax_config
      end
      sax_config.element_configs_for_attribute(name, attrs).each do |ec|
        unless parsed_config?(object, ec)
          object.send(ec.setter, ec.value_from_attrs(attrs))
          mark_as_parsed(object, ec)
        end
      end
      if !collection_config && ec = sax_config.element_config_for_tag(name, attrs)
        stack.push [ec.data_class ? ec.data_class.new : object, ec, ""]
      end
    end

    def end_element(name)
      (object, _, _), (element, config, value) = stack[-2..-1]
      return unless config && config.name.to_s == name.to_s

      unless parsed_config?(object, config)
        if config.respond_to?(:accessor)
          object.send(config.accessor) << element
        else
          value = config.data_class ? element : value
          object.send(config.setter, value) unless value == ""
          mark_as_parsed(object, config)
        end
      end
      stack.pop
    end

    def mark_as_parsed(object, element_config)
      @parsed_configs[[object.object_id, element_config.object_id]] = true unless element_config.collection?
    end

    def parsed_config?(object, element_config)
      @parsed_configs[[object.object_id, element_config.object_id]]
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
orend-sax-machine-0.0.15 lib/sax-machine/sax_handler.rb