1 | require 'rexml/validation/validationexception'
|
---|
2 |
|
---|
3 | module REXML
|
---|
4 | module Parsers
|
---|
5 | class TreeParser
|
---|
6 | def initialize( source, build_context = Document.new )
|
---|
7 | @build_context = build_context
|
---|
8 | @parser = Parsers::BaseParser.new( source )
|
---|
9 | end
|
---|
10 |
|
---|
11 | def add_listener( listener )
|
---|
12 | @parser.add_listener( listener )
|
---|
13 | end
|
---|
14 |
|
---|
15 | def parse
|
---|
16 | tag_stack = []
|
---|
17 | in_doctype = false
|
---|
18 | entities = nil
|
---|
19 | begin
|
---|
20 | while true
|
---|
21 | event = @parser.pull
|
---|
22 | #STDERR.puts "TREEPARSER GOT #{event.inspect}"
|
---|
23 | case event[0]
|
---|
24 | when :end_document
|
---|
25 | unless tag_stack.empty?
|
---|
26 | #raise ParseException.new("No close tag for #{tag_stack.inspect}")
|
---|
27 | raise ParseException.new("No close tag for #{@build_context.xpath}")
|
---|
28 | end
|
---|
29 | return
|
---|
30 | when :start_element
|
---|
31 | tag_stack.push(event[1])
|
---|
32 | # find the observers for namespaces
|
---|
33 | @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
|
---|
90 | raise ParseException.new( $!.message, @parser.source, @parser, $! )
|
---|
91 | end
|
---|
92 | end
|
---|
93 | end
|
---|
94 | end
|
---|
95 | end
|
---|