class REXML::Parsers::BaseParser
Using the Pull Parser¶ ↑
This API is experimental, and subject to change.
parser = PullParser.new( "<a>text<b att='val'/>txet</a>" ) while parser.has_next? res = parser.next puts res[1]['att'] if res.start_tag? and res[0] == 'b' end
See the PullEvent
class for information on the content of the results. The data is identical to the arguments passed for the various events to the StreamListener
API.
Notice that:
parser = PullParser.new( "<a>BAD DOCUMENT" ) while parser.has_next? res = parser.next raise res[1] if res.error? end
Nat Price gave me some good ideas for the API.
Constants
- ATTDEF
- ATTDEF_RE
- ATTLISTDECL_PATTERN
- ATTLISTDECL_START
- ATTRIBUTE_PATTERN
- ATTTYPE
- ATTVALUE
- CDATA_END
- CDATA_PATTERN
- CDATA_START
- CLOSE_MATCH
- COMBININGCHAR
- COMMENT_PATTERN
- COMMENT_START
- DEFAULTDECL
- DEFAULT_ENTITIES
- DIGIT
- DOCTYPE_END
- DOCTYPE_START
- ELEMENTDECL_PATTERN
- ELEMENTDECL_START
- ENCODING
- ENTITYDECL
- ENTITYDEF
- ENTITYVALUE
- ENTITY_START
- ENUMERATEDTYPE
- ENUMERATION
- EREFERENCE
- EXTENDER
- EXTERNALID
- EXTERNAL_ID_PUBLIC
- EXTERNAL_ID_SYSTEM
- GEDECL
- INSTRUCTION_PATTERN
- INSTRUCTION_START
- LETTER
- NAME
- NAMECHAR
- NCNAME_STR
- NDATADECL
- NMTOKEN
- NMTOKENS
- NOTATIONDECL_START
- NOTATIONTYPE
- PEDECL
- PEDEF
- PEREFERENCE
- PUBIDCHAR
Entity
constants- PUBIDLITERAL
- PUBLIC_ID
- QNAME
- QNAME_STR
- REFERENCE
- REFERENCE_RE
- STANDALONE
- SYSTEMENTITY
- SYSTEMLITERAL
- TAG_MATCH
- TEXT_PATTERN
- UNAME_STR
Just for backward compatibility. For example, kramdown uses this. It's not used in
REXML
.- VERSION
- XMLDECL_PATTERN
- XMLDECL_START
Attributes
Public Class Methods
# File lib/rexml/parsers/baseparser.rb, line 128 def initialize( source ) self.stream = source @listeners = [] end
Public Instance Methods
# File lib/rexml/parsers/baseparser.rb, line 133 def add_listener( listener ) @listeners << listener end
Returns true if there are no more events
# File lib/rexml/parsers/baseparser.rb, line 159 def empty? return (@source.empty? and @stack.empty?) end
# File lib/rexml/parsers/baseparser.rb, line 446 def entity( reference, entities ) value = nil value = entities[ reference ] if entities if not value value = DEFAULT_ENTITIES[ reference ] value = value[2] if value end unnormalize( value, entities ) if value end
Returns true if there are more events. Synonymous with !empty?
# File lib/rexml/parsers/baseparser.rb, line 164 def has_next? return !(@source.empty? and @stack.empty?) end
Escapes all possible entities
# File lib/rexml/parsers/baseparser.rb, line 457 def normalize( input, entities=nil, entity_filter=nil ) copy = input.clone # Doing it like this rather than in a loop improves the speed copy.gsub!( EREFERENCE, '&' ) entities.each do |key, value| copy.gsub!( value, "&#{key};" ) unless entity_filter and entity_filter.include?(entity) end if entities copy.gsub!( EREFERENCE, '&' ) DEFAULT_ENTITIES.each do |key, value| copy.gsub!( value[3], value[1] ) end copy end
Peek at the depth
event in the stack. The first element on the stack is at depth 0. If depth
is -1, will parse to the end of the input stream and return the last event, which is always :end_document. Be aware that this causes the stream to be parsed up to the depth
event, so you can effectively pre-parse the entire document (pull the entire thing into memory) using this method.
# File lib/rexml/parsers/baseparser.rb, line 180 def peek depth=0 raise %Q[Illegal argument "#{depth}"] if depth < -1 temp = [] if depth == -1 temp.push(pull()) until empty? else while @stack.size+temp.size < depth+1 temp.push(pull()) end end @stack += temp if temp.size > 0 @stack[depth] end
# File lib/rexml/parsers/baseparser.rb, line 149 def position if @source.respond_to? :position @source.position else # FIXME 0 end end
Returns the next event. This is a PullEvent
object.
# File lib/rexml/parsers/baseparser.rb, line 195 def pull pull_event.tap do |event| @listeners.each do |listener| listener.receive event end end end
# File lib/rexml/parsers/baseparser.rb, line 139 def stream=( source ) @source = SourceFactory.create_from( source ) @closed = nil @document_status = nil @tags = [] @stack = [] @entities = [] @nsstack = [] end
Unescapes all possible entities
# File lib/rexml/parsers/baseparser.rb, line 473 def unnormalize( string, entities=nil, filter=nil ) rv = string.gsub( /\r\n?/, "\n" ) matches = rv.scan( REFERENCE_RE ) return rv if matches.size == 0 rv.gsub!( /�*((?:\d+)|(?:x[a-fA-F0-9]+));/ ) { m=$1 m = "0#{m}" if m[0] == ?x [Integer(m)].pack('U*') } matches.collect!{|x|x[0]}.compact! if matches.size > 0 matches.each do |entity_reference| unless filter and filter.include?(entity_reference) entity_value = entity( entity_reference, entities ) if entity_value re = /&#{entity_reference};/ rv.gsub!( re, entity_value ) else er = DEFAULT_ENTITIES[entity_reference] rv.gsub!( er[0], er[2] ) if er end end end rv.gsub!( /&/, '&' ) end rv end
Push an event back on the head of the stream. This method has (theoretically) infinite depth.
# File lib/rexml/parsers/baseparser.rb, line 170 def unshift token @stack.unshift(token) end