3 require 'rexml/parseexception'
4 require 'rexml/parsers/baseparser'
5 require 'rexml/xmltokens'
9 # = Using the Pull Parser
10 # <em>This API is experimental, and subject to change.</em>
11 # parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
12 # while parser.has_next?
14 # puts res[1]['att'] if res.start_tag? and res[0] == 'b'
16 # See the PullEvent class for information on the content of the results.
17 # The data is identical to the arguments passed for the various events to
18 # the StreamListener API.
21 # parser = PullParser.new( "<a>BAD DOCUMENT" )
22 # while parser.has_next?
24 # raise res[1] if res.error?
27 # Nat Price gave me some good ideas for the API.
32 def_delegators( :@parser, :has_next? )
33 def_delegators( :@parser, :entity )
34 def_delegators( :@parser, :empty? )
35 def_delegators( :@parser, :source )
40 @parser = BaseParser.new( stream )
44 def add_listener( listener )
45 @listeners = [] unless @listeners
46 @listeners << listener
56 if @my_stack.length <= depth
57 (depth - @my_stack.length + 1).times {
58 e = PullEvent.new(@parser.pull)
66 return @my_stack.shift if @my_stack.length > 0
71 @entities[ event[1] ] =
72 event[2] unless event[2] =~ /PUBLIC|SYSTEM/
74 unnormalized = @parser.unnormalize( event[1], @entities )
77 PullEvent.new( event )
81 @my_stack.unshift token
85 # A parsing event. The contents of the event are accessed as an +Array?,
86 # and the type is given either by the ...? methods, or by accessing the
87 # +type+ accessor. The contents of this object vary from event to event,
88 # but are identical to the arguments passed to +StreamListener+s for each
91 # The type of this event. Will be one of :tag_start, :tag_end, :text,
92 # :processing_instruction, :comment, :doctype, :attlistdecl, :entitydecl,
93 # :notationdecl, :entity, :cdata, :xmldecl, or :error.
98 def []( start, endd=nil)
99 if start.kind_of? Range
100 @contents.slice( start.begin+1 .. start.end )
101 elsif start.kind_of? Numeric
103 @contents.slice( start+1 )
105 @contents.slice( start+1, endd )
108 raise "Illegal argument #{start.inspect} (#{start.class})"
116 # Content: [ String tag_name, Hash attributes ]
118 @contents[0] == :start_element
121 # Content: [ String tag_name ]
123 @contents[0] == :end_element
126 # Content: [ String raw_text, String unnormalized_text ]
128 @contents[0] == :text
131 # Content: [ String text ]
133 @contents[0] == :processing_instruction
136 # Content: [ String text ]
138 @contents[0] == :comment
141 # Content: [ String name, String pub_sys, String long_name, String uri ]
143 @contents[0] == :start_doctype
146 # Content: [ String text ]
148 @contents[0] == :attlistdecl
151 # Content: [ String text ]
153 @contents[0] == :elementdecl
156 # Due to the wonders of DTDs, an entity declaration can be just about
157 # anything. There's no way to normalize it; you'll have to interpret the
158 # content yourself. However, the following is true:
160 # * If the entity declaration is an internal entity:
161 # [ String name, String value ]
162 # Content: [ String text ]
164 @contents[0] == :entitydecl
167 # Content: [ String text ]
169 @contents[0] == :notationdecl
172 # Content: [ String text ]
174 @contents[0] == :entity
177 # Content: [ String text ]
179 @contents[0] == :cdata
182 # Content: [ String version, String encoding, String standalone ]
184 @contents[0] == :xmldecl
188 @contents[0] == :error
192 @contents[0].to_s + ": " + @contents[1..-1].inspect