Class | REXML::Parsers::SAX2Parser
In: | rexml/parsers/sax2parser.rb
Parent: | Object

SAX2Parser

### Methods

add_listener deafen listen new parse

### Public Class methods

new(source)

[Source]

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

### Public Instance methods

add_listener( listener )

[Source]

    # File rexml/parsers/sax2parser.rb, line 20
          def add_listener( listener )
            @parser.add_listener( listener )
          end

deafen( listener=nil, &blok )

[Source]

    # File rexml/parsers/sax2parser.rb, line 72
                            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

listen( *args, &blok )

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.

[Source]

    # File rexml/parsers/sax2parser.rb, line 54
                            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()

[Source]

    # File rexml/parsers/sax2parser.rb, line 81
                            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?
                                    }
                                    root = context = []
                                    while true
                                            event = @parser.pull
                                            case event[0]
                                            when :end_document
                                                    handle( :end_document )
                                                    break
                                            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 |prefix, uri|
                                                                    # notify observers of namespaces
                                                                    procs.each { |ob| ob.call( prefix ) } if procs
                                                                    listeners.each { |ob| ob.end_prefix_mapping(prefix) } if listeners
                                                            end
                                                    end
                                            when :text
                #normalized = @parser.normalize( event[1] )
                #handle( :characters, normalized )
                copy = event[1].clone
                @entities.each { |key, value| copy = copy.gsub("&#{key};", value) }
                copy.gsub!( Text::NUMERICENTITY ) {|m|
                  m=$1
                  m = "0#{m}" if m[0] == ?x
                  [Integer(m)].pack('U*')
                }
                handle( :characters, copy )
              when :entitydecl
                @entities[ event[1] ] = event[2] if event.size == 3
                                                    handle( *event )
                                            when :processing_instruction, :comment, :doctype, :attlistdecl,
                                                    :elementdecl, :cdata, :notationdecl, :xmldecl
                                                    handle( *event )
                                            end
              handle( :progress, @parser.source.position )
                                    end
                            end

[Validate]