mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
-
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f2b75020ba
commit
3289dfc78b
13 changed files with 246 additions and 123 deletions
|
@ -152,6 +152,12 @@ module REXML
|
|||
write( rv )
|
||||
rv
|
||||
end
|
||||
|
||||
def xpath
|
||||
path = @element.xpath
|
||||
path += "/@#{self.expanded_name}"
|
||||
return path
|
||||
end
|
||||
end
|
||||
end
|
||||
#vim:ts=2 sw=2 noexpandtab:
|
||||
|
|
|
@ -9,6 +9,7 @@ require "rexml/parseexception"
|
|||
require "rexml/output"
|
||||
require "rexml/parsers/baseparser"
|
||||
require "rexml/parsers/streamparser"
|
||||
require "rexml/parsers/treeparser"
|
||||
|
||||
module REXML
|
||||
# Represents a full XML document, including PIs, a doctype, etc. A
|
||||
|
@ -171,77 +172,7 @@ module REXML
|
|||
|
||||
private
|
||||
def build( source )
|
||||
build_context = self
|
||||
parser = Parsers::BaseParser.new( source )
|
||||
tag_stack = []
|
||||
in_doctype = false
|
||||
entities = nil
|
||||
begin
|
||||
while true
|
||||
event = parser.pull
|
||||
case event[0]
|
||||
when :end_document
|
||||
return
|
||||
when :start_element
|
||||
tag_stack.push(event[1])
|
||||
# find the observers for namespaces
|
||||
build_context = build_context.add_element( event[1], event[2] )
|
||||
when :end_element
|
||||
tag_stack.pop
|
||||
build_context = build_context.parent
|
||||
when :text
|
||||
if not in_doctype
|
||||
if build_context[-1].instance_of? Text
|
||||
build_context[-1] << event[1]
|
||||
else
|
||||
build_context.add(
|
||||
Text.new( event[1], build_context.whitespace, nil, true )
|
||||
) unless (
|
||||
event[1].strip.size==0 and
|
||||
build_context.ignore_whitespace_nodes
|
||||
)
|
||||
end
|
||||
end
|
||||
when :comment
|
||||
c = Comment.new( event[1] )
|
||||
build_context.add( c )
|
||||
when :cdata
|
||||
c = CData.new( event[1] )
|
||||
build_context.add( c )
|
||||
when :processing_instruction
|
||||
build_context.add( Instruction.new( event[1], event[2] ) )
|
||||
when :end_doctype
|
||||
in_doctype = false
|
||||
entities.each { |k,v| entities[k] = build_context.entities[k].value }
|
||||
build_context = build_context.parent
|
||||
when :start_doctype
|
||||
doctype = DocType.new( event[1..-1], build_context )
|
||||
build_context = doctype
|
||||
entities = {}
|
||||
in_doctype = true
|
||||
when :attlistdecl
|
||||
n = AttlistDecl.new( event[1..-1] )
|
||||
build_context.add( n )
|
||||
when :externalentity
|
||||
n = ExternalEntity.new( event[1] )
|
||||
build_context.add( n )
|
||||
when :elementdecl
|
||||
n = ElementDecl.new( event[1] )
|
||||
build_context.add(n)
|
||||
when :entitydecl
|
||||
entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
|
||||
build_context.add(Entity.new(event))
|
||||
when :notationdecl
|
||||
n = NotationDecl.new( *event[1..-1] )
|
||||
build_context.add( n )
|
||||
when :xmldecl
|
||||
x = XMLDecl.new( event[1], event[2], event[3] )
|
||||
build_context.add( x )
|
||||
end
|
||||
end
|
||||
rescue
|
||||
raise ParseException.new( $!.message, parser.source, parser, $! )
|
||||
end
|
||||
Parsers::TreeParser.new( source, self ).parse
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -73,7 +73,8 @@ module REXML
|
|||
@attributes.each_attribute do |attr|
|
||||
rv << " "
|
||||
attr.write( rv, 0 )
|
||||
end unless @attributes.empty?
|
||||
end
|
||||
rv << ">"
|
||||
|
||||
if children.size > 0
|
||||
rv << " ... </>"
|
||||
|
@ -517,6 +518,17 @@ module REXML
|
|||
:element
|
||||
end
|
||||
|
||||
def xpath
|
||||
path_elements = []
|
||||
cur = self
|
||||
path_elements << __to_xpath_helper( self )
|
||||
while cur.parent
|
||||
cur = cur.parent
|
||||
path_elements << __to_xpath_helper( cur )
|
||||
end
|
||||
return path_elements.reverse.join( "/" )
|
||||
end
|
||||
|
||||
#################################################
|
||||
# Attributes #
|
||||
#################################################
|
||||
|
@ -677,6 +689,20 @@ module REXML
|
|||
|
||||
|
||||
private
|
||||
def __to_xpath_helper node
|
||||
rv = node.expanded_name
|
||||
if node.parent
|
||||
results = node.parent.find_all {|n|
|
||||
n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name
|
||||
}
|
||||
if results.length > 1
|
||||
idx = results.index( node )
|
||||
rv << "[#{idx+1}]"
|
||||
end
|
||||
end
|
||||
rv
|
||||
end
|
||||
|
||||
# A private helper method
|
||||
def each_with_something( test, max=0, name=nil )
|
||||
num = 0
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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({})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
string << "/" unless string.size == 0
|
||||
string << op.to_s
|
||||
string << "::"
|
||||
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
|
||||
path.shift
|
||||
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
|
||||
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| 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 << path.shift.inspect
|
||||
string << op.inspect
|
||||
string << ")"
|
||||
end
|
||||
end
|
||||
string = "/"+string if document
|
||||
return string
|
||||
end
|
||||
|
||||
def predicate_to_string( path )
|
||||
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.tr("_", "-")
|
||||
string << "::"
|
||||
when :any
|
||||
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| expand(x) }
|
||||
string << ']'
|
||||
when :document
|
||||
document = true
|
||||
else
|
||||
string << "/" unless string.size == 0
|
||||
string << "UNKNOWN("
|
||||
string << op.inspect
|
||||
string << ")"
|
||||
end
|
||||
end
|
||||
string = "/"+string if document
|
||||
return string
|
||||
end
|
||||
|
||||
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
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#
|
||||
# Main page:: http://www.germane-software.com/software/rexml
|
||||
# Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
|
||||
# Version:: 3.0.9
|
||||
# Date:: +2004/137
|
||||
# Version:: 3.1.1
|
||||
# Date:: +2004/162
|
||||
#
|
||||
# This API documentation can be downloaded from the REXML home page, or can
|
||||
# be accessed online[http://www.germane-software.com/software/rexml_doc]
|
||||
|
@ -20,7 +20,7 @@
|
|||
# or can be accessed
|
||||
# online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
|
||||
module REXML
|
||||
Copyright = "Copyright © 2001, 2002, 2003, 2004 Sean Russell <ser@germane-software.com>"
|
||||
Date = "+2004/137"
|
||||
Version = "3.0.9"
|
||||
Copyright = "Copyright © 2001, 2002, 2003, 2004 Sean Russell <ser@germane-software.com>"
|
||||
Date = "+2004/162"
|
||||
Version = "3.1.1"
|
||||
end
|
||||
|
|
|
@ -218,6 +218,14 @@ module REXML
|
|||
writer << s
|
||||
end
|
||||
|
||||
# FIXME
|
||||
# This probably won't work properly
|
||||
def xpath
|
||||
path = @parent.xpath
|
||||
path += "/text()"
|
||||
return path
|
||||
end
|
||||
|
||||
# Writes out text, substituting special characters beforehand.
|
||||
# +out+ A String, IO, or any other object supporting <<( String )
|
||||
# +input+ the text to substitute and the write out
|
||||
|
|
|
@ -43,8 +43,6 @@ module REXML
|
|||
@variables[ variable_name ] = value
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def match( path_stack, nodeset )
|
||||
while ( path_stack.size > 0 and nodeset.size > 0 )
|
||||
#puts "PARSE: #{path_stack.inspect} '#{nodeset.collect{|n|n.class}.inspect}'"
|
||||
|
@ -55,6 +53,8 @@ module REXML
|
|||
nodeset
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def internal_parse path_stack, nodeset
|
||||
#puts "INTERNAL_PARSE RETURNING WITH NO RESULTS" if nodeset.size == 0 or path_stack.size == 0
|
||||
return nodeset if nodeset.size == 0 or path_stack.size == 0
|
||||
|
@ -423,10 +423,9 @@ module REXML
|
|||
current_index = all_siblings.index( node )
|
||||
preceding_siblings = all_siblings[ 0 .. current_index-1 ]
|
||||
|
||||
preceding_siblings.reverse!
|
||||
preceding = []
|
||||
recurse( preceding_siblings ) { |node| preceding << node }
|
||||
preceding.reverse
|
||||
recurse( preceding_siblings ) { |node| preceding.unshift( node ) }
|
||||
preceding
|
||||
end
|
||||
|
||||
def equality_relational_compare( set1, op, set2 )
|
||||
|
|
Loading…
Reference in a new issue