diff options
author | ser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-06-10 02:01:04 +0000 |
---|---|---|
committer | ser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-06-10 02:01:04 +0000 |
commit | 3289dfc78b4c5051b0079217a193ce50d5349506 (patch) | |
tree | 564ff1057a5341fa9b28cf03218851f8d0255f4f /lib/rexml/parsers | |
parent | f2b75020ba193b6d20788c800fde583ca8e900d5 (diff) | |
download | ruby-3289dfc78b4c5051b0079217a193ce50d5349506.tar.gz |
-
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rexml/parsers')
-rw-r--r-- | lib/rexml/parsers/baseparser.rb | 39 | ||||
-rw-r--r-- | lib/rexml/parsers/lightparser.rb | 4 | ||||
-rw-r--r-- | lib/rexml/parsers/pullparser.rb | 6 | ||||
-rw-r--r-- | lib/rexml/parsers/sax2parser.rb | 5 | ||||
-rw-r--r-- | lib/rexml/parsers/streamparser.rb | 9 | ||||
-rw-r--r-- | lib/rexml/parsers/ultralightparser.rb | 4 | ||||
-rw-r--r-- | lib/rexml/parsers/xpathparser.rb | 164 |
7 files changed, 192 insertions, 39 deletions
diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb index fbb1ec06a8..16e5c80237 100644 --- a/lib/rexml/parsers/baseparser.rb +++ b/lib/rexml/parsers/baseparser.rb @@ -100,6 +100,23 @@ module REXML self.stream = source end + def add_listener( listener ) + if !defined?(@listeners) or !@listeners + @listeners = [] + instance_eval <<-EOL + alias :_old_pull :pull + def pull + event = _old_pull + @listeners.each do |listener| + listener.receive event + end + event + end + EOL + end + @listeners << listener + end + attr_reader :source def stream=( source ) @@ -162,11 +179,11 @@ module REXML # Returns the next event. This is a +PullEvent+ object. def pull - return [ :end_document ] if empty? if @closed x, @closed = @closed, nil return [ :end_element, x ] end + return [ :end_document ] if empty? return @stack.shift if @stack.size > 0 @source.read if @source.buffer.size<2 if @document_status == nil @@ -411,3 +428,23 @@ module REXML end end end + +=begin + case event[0] + when :start_element + when :text + when :end_element + when :processing_instruction + when :cdata + when :comment + when :xmldecl + when :start_doctype + when :end_doctype + when :externalentity + when :elementdecl + when :entity + when :attlistdecl + when :notationdecl + when :end_doctype + end +=end diff --git a/lib/rexml/parsers/lightparser.rb b/lib/rexml/parsers/lightparser.rb index 8c555f7960..0f35034993 100644 --- a/lib/rexml/parsers/lightparser.rb +++ b/lib/rexml/parsers/lightparser.rb @@ -10,6 +10,10 @@ module REXML @parser = REXML::Parsers::BaseParser.new( stream ) end + def add_listener( listener ) + @parser.add_listener( listener ) + end + def rewind @stream.rewind @parser.stream = @stream diff --git a/lib/rexml/parsers/pullparser.rb b/lib/rexml/parsers/pullparser.rb index aeda6251fe..fe4d41c959 100644 --- a/lib/rexml/parsers/pullparser.rb +++ b/lib/rexml/parsers/pullparser.rb @@ -29,8 +29,14 @@ module REXML def initialize stream super @entities = {} + @listeners = nil end + def add_listener( listener ) + @listeners = [] unless @listeners + @listeners << listener + end + def each while has_next? yield self.pull diff --git a/lib/rexml/parsers/sax2parser.rb b/lib/rexml/parsers/sax2parser.rb index 8c82cf8fc1..96440d17bf 100644 --- a/lib/rexml/parsers/sax2parser.rb +++ b/lib/rexml/parsers/sax2parser.rb @@ -14,6 +14,10 @@ module REXML @tag_stack = [] end + def add_listener( listener ) + @parser.add_listener( listener ) + end + # Listen arguments: # # Symbol, Array, Block @@ -89,6 +93,7 @@ module REXML if procs or listeners # break out the namespace declarations # The attributes live in event[2] + event[2].each {|n, v| event[2][n] = @parser.normalize(v)} nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ } nsdecl.collect! { |n, value| [ n[6..-1], value ] } @namespace_stack.push({}) diff --git a/lib/rexml/parsers/streamparser.rb b/lib/rexml/parsers/streamparser.rb index 49bef0d8fa..357cc186e6 100644 --- a/lib/rexml/parsers/streamparser.rb +++ b/lib/rexml/parsers/streamparser.rb @@ -6,6 +6,10 @@ module REXML @parser = BaseParser.new( source ) end + def add_listener( listener ) + @parser.add_listener( listener ) + end + def parse # entity string while true @@ -14,7 +18,10 @@ module REXML when :end_document return when :start_element - @listener.tag_start( event[1], event[2] ) + attrs = event[2].each do |n, v| + event[2][n] = @parser.unnormalize( v ) + end + @listener.tag_start( event[1], attrs ) when :end_element @listener.tag_end( event[1] ) when :text diff --git a/lib/rexml/parsers/ultralightparser.rb b/lib/rexml/parsers/ultralightparser.rb index f3b208bf0f..adc4af18e2 100644 --- a/lib/rexml/parsers/ultralightparser.rb +++ b/lib/rexml/parsers/ultralightparser.rb @@ -9,6 +9,10 @@ module REXML @parser = REXML::Parsers::BaseParser.new( stream ) end + def add_listener( listener ) + @parser.add_listener( listener ) + end + def rewind @stream.rewind @parser.stream = @stream diff --git a/lib/rexml/parsers/xpathparser.rb b/lib/rexml/parsers/xpathparser.rb index 082f8255ad..41b2b8a5c1 100644 --- a/lib/rexml/parsers/xpathparser.rb +++ b/lib/rexml/parsers/xpathparser.rb @@ -30,46 +30,126 @@ module REXML parsed end - def to_string( path ) + def abbreviate( path ) + path = path.kind_of?(String) ? parse( path ) : path string = "" + document = false while path.size > 0 - case path[0] - when :ancestor, :ancestor_or_self, :attribute, :child, :descendant, :descendant_or_self, :following, :following_sibling, :namespace, :parent, :preceding, :preceding_sibling, :self - op = path.shift + op = path.shift + case op + when :node + when :attribute + string << "/" if string.size > 0 + string << "@" + when :child + string << "/" if string.size > 0 + when :descendant_or_self + string << "/" + when :self + string << "." + when :parent + string << ".." + when :any + string << "*" + when :text + string << "text()" + when :following, :following_sibling, + :ancestor, :ancestor_or_self, :descendant, + :namespace, :preceding, :preceding_sibling + string << "/" unless string.size == 0 + string << op.to_s.tr("_", "-") + string << "::" + when :qname + prefix = path.shift + name = path.shift + string << prefix+":" if prefix.size > 0 + string << name + when :predicate + string << '[' + string << predicate_to_string( path.shift ) {|x| abbreviate( x ) } + string << ']' + when :document + document = true + when :function + string << path.shift + string << "( " + string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )} + string << " )" + when :literal + string << %Q{ "#{path.shift}" } + else + string << "/" unless string.size == 0 + string << "UNKNOWN(" + string << op.inspect + string << ")" + end + end + string = "/"+string if document + return string + end + + def expand( path ) + path = path.kind_of?(String) ? parse( path ) : path + string = "" + document = false + while path.size > 0 + op = path.shift + case op + when :node + string << "node()" + when :attribute, :child, :following, :following_sibling, + :ancestor, :ancestor_or_self, :descendant, :descendant_or_self, + :namespace, :preceding, :preceding_sibling, :self, :parent string << "/" unless string.size == 0 - string << op.to_s + string << op.to_s.tr("_", "-") string << "::" when :any - path.shift string << "*" when :qname - path.shift prefix = path.shift name = path.shift string << prefix+":" if prefix.size > 0 string << name when :predicate - path.shift string << '[' - string << predicate_to_string( path.shift ) - string << ' ]' + string << predicate_to_string( path.shift ) { |x| expand(x) } + string << ']' + when :document + document = true else string << "/" unless string.size == 0 string << "UNKNOWN(" - string << path.shift.inspect + string << op.inspect string << ")" end end + string = "/"+string if document return string end - def predicate_to_string( path ) + def predicate_to_string( path, &block ) string = "" case path[0] - when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :neq, :union + when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union op = path.shift - left = predicate_to_string( path.shift ) - right = predicate_to_string( path.shift ) + case op + when :eq + op = "=" + when :lt + op = "<" + when :gt + op = ">" + when :lteq + op = "<=" + when :gteq + op = ">=" + when :neq + op = "!=" + when :union + op = "|" + end + left = predicate_to_string( path.shift, &block ) + right = predicate_to_string( path.shift, &block ) string << " " string << left string << " " @@ -82,7 +162,7 @@ module REXML name = path.shift string << name string << "( " - string << predicate_to_string( path.shift ) + string << predicate_to_string( path.shift, &block ) string << " )" when :literal path.shift @@ -91,7 +171,7 @@ module REXML string << " " else string << " " - string << to_string( path ) + string << yield( path ) string << " " end return string.squeeze(" ") @@ -534,7 +614,6 @@ module REXML #| FUNCTION_NAME '(' ( expr ( ',' expr )* )? ')' def FunctionCall rest, parsed path, arguments = parse_args(rest) - #puts "Function call >>> (#{arguments.inspect})" argset = [] for argument in arguments args = [] @@ -567,28 +646,39 @@ module REXML def parse_args( string ) arguments = [] ind = 0 + inquot = false + inapos = false depth = 1 begin case string[ind] - when ?( - depth += 1 - if depth == 1 - string = string[1..-1] - ind -= 1 - end - when ?) - depth -= 1 - if depth == 0 - s = string[0,ind].strip - arguments << s unless s == "" - string = string[ind+1..-1] - end - when ?, - if depth == 1 - s = string[0,ind].strip - arguments << s unless s == "" - string = string[ind+1..-1] - ind = 0 + when ?" + inquot = !inquot unless inapos + when ?' + inapos = !inapos unless inquot + else + unless inquot or inapos + case string[ind] + when ?( + depth += 1 + if depth == 1 + string = string[1..-1] + ind -= 1 + end + when ?) + depth -= 1 + if depth == 0 + s = string[0,ind].strip + arguments << s unless s == "" + string = string[ind+1..-1] + end + when ?, + if depth == 1 + s = string[0,ind].strip + arguments << s unless s == "" + string = string[ind+1..-1] + ind = -1 + end + end end end ind += 1 |