Change soft-fail to use the config, rather than env
[rbx.git] / lib / rexml / parsers / treeparser.rb
blob5c3e142ea70a2b451ba57e54882871a04198182d
1 require 'rexml/validation/validationexception'
2 require 'rexml/undefinednamespaceexception'
4 module 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
12       def add_listener( listener )
13         @parser.add_listener( listener )
14       end
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], event[2] )
34             when :end_element
35               tag_stack.pop
36               @build_context = @build_context.parent
37             when :text
38               if not in_doctype
39                 if @build_context[-1].instance_of? Text
40                   @build_context[-1] << event[1]
41                 else
42                   @build_context.add( 
43                     Text.new(event[1], @build_context.whitespace, nil, true) 
44                   ) unless (
45                     @build_context.ignore_whitespace_nodes and
46                     event[1].strip.size==0
47                   )
48                 end
49               end
50             when :comment
51               c = Comment.new( event[1] )
52               @build_context.add( c )
53             when :cdata
54               c = CData.new( event[1] )
55               @build_context.add( c )
56             when :processing_instruction
57               @build_context.add( Instruction.new( event[1], event[2] ) )
58             when :end_doctype
59               in_doctype = false
60               entities.each { |k,v| entities[k] = @build_context.entities[k].value }
61               @build_context = @build_context.parent
62             when :start_doctype
63               doctype = DocType.new( event[1..-1], @build_context )
64               @build_context = doctype
65               entities = {}
66               in_doctype = true
67             when :attlistdecl
68               n = AttlistDecl.new( event[1..-1] )
69               @build_context.add( n )
70             when :externalentity
71               n = ExternalEntity.new( event[1] )
72               @build_context.add( n )
73             when :elementdecl
74               n = ElementDecl.new( event[1] )
75               @build_context.add(n)
76             when :entitydecl
77               entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
78               @build_context.add(Entity.new(event))
79             when :notationdecl
80               n = NotationDecl.new( *event[1..-1] )
81               @build_context.add( n )
82             when :xmldecl
83               x = XMLDecl.new( event[1], event[2], event[3] )
84               @build_context.add( x )
85             end
86           end
87         rescue REXML::Validation::ValidationException
88           raise
89         rescue REXML::UndefinedNamespaceException
90           raise
91         rescue
92           raise ParseException.new( $!.message, @parser.source, @parser, $! )
93         end
94       end
95     end
96   end
97 end