1require 'rexml/validation/validationexception' 2require 'rexml/undefinednamespaceexception' 3 4module REXML 5 module Parsers 6 class TreeParser 7 def initialize( source, build_context = Document.new ) 8 @build_context = build_context 9 @parser = Parsers::BaseParser.new( source ) 10 end 11 12 def add_listener( listener ) 13 @parser.add_listener( listener ) 14 end 15 16 def parse 17 tag_stack = [] 18 in_doctype = false 19 entities = nil 20 begin 21 while true 22 event = @parser.pull 23 #STDERR.puts "TREEPARSER GOT #{event.inspect}" 24 case event[0] 25 when :end_document 26 unless tag_stack.empty? 27 #raise ParseException.new("No close tag for #{tag_stack.inspect}") 28 raise ParseException.new("No close tag for #{@build_context.xpath}") 29 end 30 return 31 when :start_element 32 tag_stack.push(event[1]) 33 el = @build_context = @build_context.add_element( event[1] ) 34 event[2].each do |key, value| 35 el.attributes[key]=Attribute.new(key,value,self) 36 end 37 when :end_element 38 tag_stack.pop 39 @build_context = @build_context.parent 40 when :text 41 if not in_doctype 42 if @build_context[-1].instance_of? Text 43 @build_context[-1] << event[1] 44 else 45 @build_context.add( 46 Text.new(event[1], @build_context.whitespace, nil, true) 47 ) unless ( 48 @build_context.ignore_whitespace_nodes and 49 event[1].strip.size==0 50 ) 51 end 52 end 53 when :comment 54 c = Comment.new( event[1] ) 55 @build_context.add( c ) 56 when :cdata 57 c = CData.new( event[1] ) 58 @build_context.add( c ) 59 when :processing_instruction 60 @build_context.add( Instruction.new( event[1], event[2] ) ) 61 when :end_doctype 62 in_doctype = false 63 entities.each { |k,v| entities[k] = @build_context.entities[k].value } 64 @build_context = @build_context.parent 65 when :start_doctype 66 doctype = DocType.new( event[1..-1], @build_context ) 67 @build_context = doctype 68 entities = {} 69 in_doctype = true 70 when :attlistdecl 71 n = AttlistDecl.new( event[1..-1] ) 72 @build_context.add( n ) 73 when :externalentity 74 n = ExternalEntity.new( event[1] ) 75 @build_context.add( n ) 76 when :elementdecl 77 n = ElementDecl.new( event[1] ) 78 @build_context.add(n) 79 when :entitydecl 80 entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/ 81 @build_context.add(Entity.new(event)) 82 when :notationdecl 83 n = NotationDecl.new( *event[1..-1] ) 84 @build_context.add( n ) 85 when :xmldecl 86 x = XMLDecl.new( event[1], event[2], event[3] ) 87 @build_context.add( x ) 88 end 89 end 90 rescue REXML::Validation::ValidationException 91 raise 92 rescue REXML::UndefinedNamespaceException 93 raise 94 rescue 95 raise ParseException.new( $!.message, @parser.source, @parser, $! ) 96 end 97 end 98 end 99 end 100end 101