class REXML::Parsers::SAX2Parser

SAX2Parser

Public Class Methods

new(source) click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 11
def initialize source
  @parser = BaseParser.new(source)
  @listeners = []
  @procs = []
  @namespace_stack = []
  @has_listeners = false
  @tag_stack = []
  @entities = {}
end

Public Instance Methods

add_listener( listener ) click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 37
def add_listener( listener )
  @parser.add_listener( listener )
end
deafen( listener=nil, &blok ) click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 89
def deafen( listener=nil, &blok )
  if listener
    @listeners.delete_if {|item| item[-1] == listener }
    @has_listeners = false if @listeners.size == 0
  else
    @procs.delete_if {|item| item[-1] == blok }
  end
end
entity_expansion_count() click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 25
def entity_expansion_count
  @parser.entity_expansion_count
end
entity_expansion_limit=( limit ) click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 29
def entity_expansion_limit=( limit )
  @parser.entity_expansion_limit = limit
end
entity_expansion_text_limit=( limit ) click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 33
def entity_expansion_text_limit=( limit )
  @parser.entity_expansion_text_limit = limit
end
listen( *args, &blok ) click to toggle source

Listen arguments:

Symbol, Array, Block

Listen to Symbol events on Array elements

Symbol, Block

Listen to Symbol events

Array, Listener

Listen to all events on Array elements

Array, Block

Listen to :start_element events on Array elements

Listener

Listen to All events

Symbol can be one of: :start_element, :end_element, :start_prefix_mapping, :end_prefix_mapping, :characters, :processing_instruction, :doctype, :attlistdecl, :elementdecl, :entitydecl, :notationdecl, :cdata, :xmldecl, :comment

There is an additional symbol that can be listened for: :progress. This will be called for every event generated, passing in the current stream position.

Array contains regular expressions or strings which will be matched against fully qualified element names.

Listener must implement the methods in SAX2Listener

Block will be passed the same arguments as a SAX2Listener method would be, where the method name is the same as the matched Symbol. See the SAX2Listener for more information.

# File lib/rexml/parsers/sax2parser.rb, line 71
def listen( *args, &blok )
  if args[0].kind_of? Symbol
    if args.size == 2
      args[1].each { |match| @procs << [args[0], match, blok] }
    else
      add( [args[0], nil, blok] )
    end
  elsif args[0].kind_of? Array
    if args.size == 2
      args[0].each { |match| add( [nil, match, args[1]] ) }
    else
      args[0].each { |match| add( [ :start_element, match, blok ] ) }
    end
  else
    add([nil, nil, args[0]])
  end
end
parse() click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 98
def parse
  @procs.each { |sym,match,block| block.call if sym == :start_document }
  @listeners.each { |sym,match,block|
    block.start_document if sym == :start_document or sym.nil?
  }
  context = []
  while true
    event = @parser.pull
    case event[0]
    when :end_document
      handle( :end_document )
      break
    when :start_doctype
      handle( :doctype, *event[1..-1])
    when :end_doctype
      context = context[1]
    when :start_element
      @tag_stack.push(event[1])
      # find the observers for namespaces
      procs = get_procs( :start_prefix_mapping, event[1] )
      listeners = get_listeners( :start_prefix_mapping, event[1] )
      if procs or listeners
        # break out the namespace declarations
        # The attributes live in event[2]
        event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
        nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
        nsdecl.collect! { |n, value| [ n[6..-1], value ] }
        @namespace_stack.push({})
        nsdecl.each do |n,v|
          @namespace_stack[-1][n] = v
          # notify observers of namespaces
          procs.each { |ob| ob.call( n, v ) } if procs
          listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
        end
      end
      event[1] =~ Namespace::NAMESPLIT
      prefix = $1
      local = $2
      uri = get_namespace(prefix)
      # find the observers for start_element
      procs = get_procs( :start_element, event[1] )
      listeners = get_listeners( :start_element, event[1] )
      # notify observers
      procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
      listeners.each { |ob|
        ob.start_element( uri, local, event[1], event[2] )
      } if listeners
    when :end_element
      @tag_stack.pop
      event[1] =~ Namespace::NAMESPLIT
      prefix = $1
      local = $2
      uri = get_namespace(prefix)
      # find the observers for start_element
      procs = get_procs( :end_element, event[1] )
      listeners = get_listeners( :end_element, event[1] )
      # notify observers
      procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
      listeners.each { |ob|
        ob.end_element( uri, local, event[1] )
      } if listeners

      namespace_mapping = @namespace_stack.pop
      # find the observers for namespaces
      procs = get_procs( :end_prefix_mapping, event[1] )
      listeners = get_listeners( :end_prefix_mapping, event[1] )
      if procs or listeners
        namespace_mapping.each do |ns_prefix, ns_uri|
          # notify observers of namespaces
          procs.each { |ob| ob.call( ns_prefix ) } if procs
          listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners
        end
      end
    when :text
      unnormalized = @parser.unnormalize( event[1], @entities )
      handle( :characters, unnormalized )
    when :entitydecl
      handle_entitydecl( event )
    when :processing_instruction, :comment, :attlistdecl,
      :elementdecl, :cdata, :notationdecl, :xmldecl
      handle( *event )
    end
    handle( :progress, @parser.position )
  end
end
source() click to toggle source
# File lib/rexml/parsers/sax2parser.rb, line 21
def source
  @parser.source
end