class REXML::Parsers::SAX2Parser
公共类方法
new(source) 点击切换源代码
# File rexml-3.4.0/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
公共实例方法
add_listener( listener ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 37 def add_listener( listener ) @parser.add_listener( listener ) end
deafen( listener=nil, &blok ) 点击切换源代码
# File rexml-3.4.0/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() 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 25 def entity_expansion_count @parser.entity_expansion_count end
entity_expansion_limit=( limit ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 29 def entity_expansion_limit=( limit ) @parser.entity_expansion_limit = limit end
entity_expansion_text_limit=( limit ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 33 def entity_expansion_text_limit=( limit ) @parser.entity_expansion_text_limit = limit end
listen( *args, &blok ) 点击切换源代码
Listen 参数
符号,数组,代码块
Listen to Symbol events on Array elements
符号,代码块
Listen to Symbol events
数组,监听器
Listen to all events on Array elements
数组,代码块
Listen to :start_element events on Array elements
监听器
Listen to All events
符号可以是以下之一::start_element、:end_element、:start_prefix_mapping、:end_prefix_mapping、:characters、:processing_instruction、:doctype、:attlistdecl、:elementdecl、:entitydecl、:notationdecl、:cdata、:xmldecl、:comment
还有一个额外的符号可以监听::progress。这将为生成的每个事件调用,传入当前流位置。
数组包含正则表达式或字符串,它们将与完全限定的元素名称进行匹配。
监听器必须实现 SAX2Listener
中的方法
代码块将传递与 SAX2Listener
方法相同的参数,其中方法名称与匹配的符号相同。有关更多信息,请参阅 SAX2Listener
。
# File rexml-3.4.0/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() 点击切换源代码
# File rexml-3.4.0/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() 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 21 def source @parser.source end
私有实例方法
add( pair ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 252 def add( pair ) if pair[-1].respond_to? :call @procs << pair unless @procs.include? pair else @listeners << pair unless @listeners.include? pair @has_listeners = true end end
get_listeners( symbol, name ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 238 def get_listeners( symbol, name ) return nil if @listeners.size == 0 @listeners.find_all do |sym, match, block| ( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match) ) ) ) end.collect{|x| x[-1]} end
get_namespace( prefix ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 261 def get_namespace( prefix ) return nil if @namespace_stack.empty? uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) || (@namespace_stack.find { |ns| not ns[nil].nil? }) uris[-1][prefix] unless uris.nil? or 0 == uris.size end
get_procs( symbol, name ) 点击切换源代码
以下方法是重复的,但比使用辅助方法更快
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 225 def get_procs( symbol, name ) return nil if @procs.size == 0 @procs.find_all do |sym, match, block| ( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match) ) ) ) end.collect{|x| x[-1]} end
handle( symbol, *arguments ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 185 def handle( symbol, *arguments ) tag = @tag_stack[-1] procs = get_procs( symbol, tag ) listeners = get_listeners( symbol, tag ) # notify observers procs.each { |ob| ob.call( *arguments ) } if procs listeners.each { |l| l.send( symbol.to_s, *arguments ) } if listeners end
handle_entitydecl( event ) 点击切换源代码
# File rexml-3.4.0/lib/rexml/parsers/sax2parser.rb, line 196 def handle_entitydecl( event ) @entities[ event[1] ] = event[2] if event.size == 3 parameter_reference_p = false case event[2] when "SYSTEM" if event.size == 5 if event.last == "%" parameter_reference_p = true else event[4, 0] = "NDATA" end end when "PUBLIC" if event.size == 6 if event.last == "%" parameter_reference_p = true else event[5, 0] = "NDATA" end end else parameter_reference_p = (event.size == 4) end event[1, 0] = event.pop if parameter_reference_p handle( event[0], event[1..-1] ) end