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