File: active_support/xml_mini/libxmlsax.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: ActiveSupport#4
  module: XmlMini_LibXMLSAX#5
extends
  XmlMini_LibXMLSAX ( ActiveSupport )
has properties
attribute: document_class [RW] #60
method: parse / 1 #63
  class: HashBuilder#10
includes
  Callbacks ( Unknown-Module::LibXML::XML::SaxParser )
inherits from
  Object ( Builtin-Module )
has properties
constant: CONTENT_KEY #14
constant: HASH_SIZE_KEY #15
attribute: hash [R] #17
method: current_hash #19
method: on_start_document #23
method: on_end_document #28
method: on_start_element / 2 #33
method: on_end_element / 1 #46
method: on_characters / 1 #53

Class Hierarchy

Code

   1  require 'libxml'
   2 
   3  # = XmlMini LibXML implementation using a SAX-based parser
   4  module ActiveSupport
   5    module XmlMini_LibXMLSAX
   6      extend self
   7 
   8      # Class that will build the hash while the XML document
   9      # is being parsed using SAX events.
  10      class HashBuilder
  11 
  12        include LibXML::XML::SaxParser::Callbacks
  13 
  14        CONTENT_KEY   = '__content__'.freeze
  15        HASH_SIZE_KEY = '__hash_size__'.freeze
  16 
  17        attr_reader :hash
  18 
  19        def current_hash
  20          @hash_stack.last
  21        end
  22 
  23        def on_start_document
  24          @hash = { CONTENT_KEY => '' }
  25          @hash_stack = [@hash]
  26        end
  27 
  28        def on_end_document
  29          @hash = @hash_stack.pop
  30          @hash.delete(CONTENT_KEY)
  31        end
  32 
  33        def on_start_element(name, attrs = {})
  34          new_hash = { CONTENT_KEY => '' }.merge(attrs)
  35          new_hash[HASH_SIZE_KEY] = new_hash.size + 1
  36 
  37          case current_hash[name]
  38            when Array then current_hash[name] << new_hash
  39            when Hash  then current_hash[name] = [current_hash[name], new_hash]
  40            when nil   then current_hash[name] = new_hash
  41          end
  42 
  43          @hash_stack.push(new_hash)
  44        end
  45 
  46        def on_end_element(name)
  47          if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ''
  48            current_hash.delete(CONTENT_KEY)
  49          end
  50          @hash_stack.pop
  51        end
  52 
  53        def on_characters(string)
  54          current_hash[CONTENT_KEY] << string
  55        end
  56 
  57        alias_method :on_cdata_block, :on_characters
  58      end
  59 
  60      attr_accessor :document_class
  61      self.document_class = HashBuilder
  62 
  63      def parse(string)
  64        return {} if string.blank?
  65        LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
  66        parser = LibXML::XML::SaxParser.string(string)
  67        document = self.document_class.new
  68 
  69        parser.callbacks = document
  70        parser.parse
  71        document.hash
  72      end
  73    end
  74  en