mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* Cross-patch from Ruby CVS; mostly Nabu edits.
* Fixes ticket:68. ***** Note that this is an API change!!! ***** NOTE that this involves an API change! Entity declarations in the doctype now generate events that carry two, not one, arguments. * Implements ticket:15, using gwrite's suggestion. This allows Element to be subclassed. * Fixed namespaces handling in XPath and element. ***** Note that this is an API change!!! ***** Element.namespaces() now returns a hash of namespace mappings which are relevant for that node. * Fixes a bug in multiple decodings * The changeset 1230:1231 was bad. The default behavior is *not* to use the native REXML encodings by default, but rather to use ICONV by default. I'll have to think of a better way of managing translations, but the REXML codecs are (a) less reliable than ICONV, but more importantly (b) slower. The real solution is to use ICONV by default, but allow users to specify that they want to use the pure Ruby codecs. * Fixes ticket:61 (xpath_parser) * Fixes ticket:63 (UTF-16; UNILE decoding was bad) * Improves parsing error messages a little * Adds the ability to override the encoding detection in Source construction * Fixes an edge case in Functions::string, where document nodes weren't correctly converted * Fixes Functions::string() for Element and Document nodes * Fixes some problems in entity handling * Addresses ticket:66 * Fixes ticket:71 * Addresses ticket:78 NOTE: that this also fixes what is technically another bug in REXML. REXML's XPath parser used to allow exponential notation in numbers. The XPath spec is specific about what a number is, and scientific notation is not included. Therefore, this has been fixed. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@11315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d2205c869e
commit
f114b85d89
14 changed files with 136 additions and 81 deletions
|
@ -94,7 +94,7 @@ module REXML
|
||||||
# new_a = d.root.clone
|
# new_a = d.root.clone
|
||||||
# puts new_a # => "<a/>"
|
# puts new_a # => "<a/>"
|
||||||
def clone
|
def clone
|
||||||
Element.new self
|
self.class.new self
|
||||||
end
|
end
|
||||||
|
|
||||||
# Evaluates to the root node of the document that this element
|
# Evaluates to the root node of the document that this element
|
||||||
|
@ -200,9 +200,9 @@ module REXML
|
||||||
end
|
end
|
||||||
|
|
||||||
def namespaces
|
def namespaces
|
||||||
namespaces = []
|
namespaces = {}
|
||||||
namespaces = parent.namespaces if parent
|
namespaces = parent.namespaces if parent
|
||||||
namespaces |= attributes.namespaces
|
namespaces = namespaces.merge( attributes.namespaces )
|
||||||
return namespaces
|
return namespaces
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -494,13 +494,12 @@ module REXML
|
||||||
# doc.root.add_element 'c' #-> '<a><b/>Elliott<c/></a>'
|
# doc.root.add_element 'c' #-> '<a><b/>Elliott<c/></a>'
|
||||||
# doc.root.text = 'Russell' #-> '<a><b/>Russell<c/></a>'
|
# doc.root.text = 'Russell' #-> '<a><b/>Russell<c/></a>'
|
||||||
# doc.root.text = nil #-> '<a><b/><c/></a>'
|
# doc.root.text = nil #-> '<a><b/><c/></a>'
|
||||||
def text=( text )
|
def text=( text )
|
||||||
if text.kind_of? String
|
if text.kind_of? String
|
||||||
text = Text.new( text, whitespace(), nil, raw() )
|
text = Text.new( text, whitespace(), nil, raw() )
|
||||||
elsif text and !text.kind_of? Text
|
elsif text and !text.kind_of? Text
|
||||||
text = Text.new( text.to_s, whitespace(), nil, raw() )
|
text = Text.new( text.to_s, whitespace(), nil, raw() )
|
||||||
end
|
end
|
||||||
|
|
||||||
old_text = get_text
|
old_text = get_text
|
||||||
if text.nil?
|
if text.nil?
|
||||||
old_text.remove unless old_text.nil?
|
old_text.remove unless old_text.nil?
|
||||||
|
@ -557,13 +556,9 @@ module REXML
|
||||||
#################################################
|
#################################################
|
||||||
|
|
||||||
def attribute( name, namespace=nil )
|
def attribute( name, namespace=nil )
|
||||||
prefix = ''
|
prefix = nil
|
||||||
if namespace
|
prefix = namespaces.index(namespace) if namespace
|
||||||
prefix = attributes.prefixes.each { |prefix|
|
attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
|
||||||
return "#{prefix}:" if namespace( prefix ) == namespace
|
|
||||||
} || ''
|
|
||||||
end
|
|
||||||
attributes.get_attribute( "#{prefix}#{name}" )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Evaluates to +true+ if this element has any attributes set, false
|
# Evaluates to +true+ if this element has any attributes set, false
|
||||||
|
@ -1172,16 +1167,16 @@ module REXML
|
||||||
end
|
end
|
||||||
|
|
||||||
def namespaces
|
def namespaces
|
||||||
namespaces = []
|
namespaces = {}
|
||||||
each_attribute do |attribute|
|
each_attribute do |attribute|
|
||||||
namespaces << attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
|
namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
|
||||||
end
|
end
|
||||||
if @element.document and @element.document.doctype
|
if @element.document and @element.document.doctype
|
||||||
expn = @element.expanded_name
|
expn = @element.expanded_name
|
||||||
expn = @element.document.doctype.name if expn.size == 0
|
expn = @element.document.doctype.name if expn.size == 0
|
||||||
@element.document.doctype.attributes_of(expn).each {
|
@element.document.doctype.attributes_of(expn).each {
|
||||||
|attribute|
|
|attribute|
|
||||||
namespaces << attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
|
namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
namespaces
|
namespaces
|
||||||
|
|
|
@ -24,21 +24,22 @@ module REXML
|
||||||
old_verbosity = $VERBOSE
|
old_verbosity = $VERBOSE
|
||||||
begin
|
begin
|
||||||
$VERBOSE = false
|
$VERBOSE = false
|
||||||
return if defined? @encoding and enc == @encoding
|
enc = enc.nil? ? nil : enc.upcase
|
||||||
|
return false if defined? @encoding and enc == @encoding
|
||||||
if enc and enc != UTF_8
|
if enc and enc != UTF_8
|
||||||
@encoding = enc.upcase
|
@encoding = enc
|
||||||
|
raise ArgumentError, "Bad encoding name #@encoding" unless @encoding =~ /^[\w-]+$/
|
||||||
|
@encoding.untaint
|
||||||
begin
|
begin
|
||||||
require 'rexml/encodings/ICONV.rb'
|
require 'rexml/encodings/ICONV.rb'
|
||||||
Encoding.apply(self, "ICONV")
|
Encoding.apply(self, "ICONV")
|
||||||
rescue LoadError, Exception => err
|
rescue LoadError, Exception
|
||||||
raise ArgumentError, "Bad encoding name #@encoding" unless @encoding =~ /^[\w-]+$/
|
|
||||||
@encoding.untaint
|
|
||||||
enc_file = File.join( "rexml", "encodings", "#@encoding.rb" )
|
|
||||||
begin
|
begin
|
||||||
|
enc_file = File.join( "rexml", "encodings", "#@encoding.rb" )
|
||||||
require enc_file
|
require enc_file
|
||||||
Encoding.apply(self, @encoding)
|
Encoding.apply(self, @encoding)
|
||||||
rescue LoadError
|
rescue LoadError => err
|
||||||
puts $!.message
|
puts err.message
|
||||||
raise ArgumentError, "No decoder found for encoding #@encoding. Please install iconv."
|
raise ArgumentError, "No decoder found for encoding #@encoding. Please install iconv."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -50,6 +51,7 @@ module REXML
|
||||||
ensure
|
ensure
|
||||||
$VERBOSE = old_verbosity
|
$VERBOSE = old_verbosity
|
||||||
end
|
end
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_encoding str
|
def check_encoding str
|
||||||
|
|
|
@ -18,7 +18,7 @@ module REXML
|
||||||
def decode_unile(str)
|
def decode_unile(str)
|
||||||
array_enc=str.unpack('C*')
|
array_enc=str.unpack('C*')
|
||||||
array_utf8 = []
|
array_utf8 = []
|
||||||
2.step(array_enc.size-1, 2){|i|
|
0.step(array_enc.size-1, 2){|i|
|
||||||
array_utf8 << (array_enc.at(i) + array_enc.at(i+1)*0x100)
|
array_utf8 << (array_enc.at(i) + array_enc.at(i+1)*0x100)
|
||||||
}
|
}
|
||||||
array_utf8.pack('U*')
|
array_utf8.pack('U*')
|
||||||
|
|
|
@ -16,9 +16,10 @@ module REXML
|
||||||
end
|
end
|
||||||
|
|
||||||
def decode_utf16(str)
|
def decode_utf16(str)
|
||||||
|
str = str[2..-1] if /^\376\377/ =~ str
|
||||||
array_enc=str.unpack('C*')
|
array_enc=str.unpack('C*')
|
||||||
array_utf8 = []
|
array_utf8 = []
|
||||||
2.step(array_enc.size-1, 2){|i|
|
0.step(array_enc.size-1, 2){|i|
|
||||||
array_utf8 << (array_enc.at(i+1) + array_enc.at(i)*0x100)
|
array_utf8 << (array_enc.at(i+1) + array_enc.at(i)*0x100)
|
||||||
}
|
}
|
||||||
array_utf8.pack('U*')
|
array_utf8.pack('U*')
|
||||||
|
|
|
@ -117,16 +117,30 @@ module REXML
|
||||||
elsif defined? object.node_type
|
elsif defined? object.node_type
|
||||||
if object.node_type == :attribute
|
if object.node_type == :attribute
|
||||||
object.value
|
object.value
|
||||||
elsif object.node_type == :element
|
elsif object.node_type == :element || object.node_type == :document
|
||||||
object.text
|
string_value(object)
|
||||||
else
|
else
|
||||||
object.to_s
|
object.to_s
|
||||||
end
|
end
|
||||||
|
elsif object.nil?
|
||||||
|
return ""
|
||||||
else
|
else
|
||||||
object.to_s
|
object.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def Functions::string_value( o )
|
||||||
|
rv = ""
|
||||||
|
o.children.each { |e|
|
||||||
|
if e.node_type == :text
|
||||||
|
rv << e.to_s
|
||||||
|
elsif e.node_type == :element
|
||||||
|
rv << string_value( e )
|
||||||
|
end
|
||||||
|
}
|
||||||
|
rv
|
||||||
|
end
|
||||||
|
|
||||||
# UNTESTED
|
# UNTESTED
|
||||||
def Functions::concat( *objects )
|
def Functions::concat( *objects )
|
||||||
objects.join
|
objects.join
|
||||||
|
@ -139,7 +153,7 @@ module REXML
|
||||||
|
|
||||||
# Fixed by Mike Stok
|
# Fixed by Mike Stok
|
||||||
def Functions::contains( string, test )
|
def Functions::contains( string, test )
|
||||||
string(string).include? string(test)
|
string(string).include?(string(test))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Kouhei fixed this
|
# Kouhei fixed this
|
||||||
|
@ -326,7 +340,9 @@ module REXML
|
||||||
else
|
else
|
||||||
str = string( object )
|
str = string( object )
|
||||||
#puts "STRING OF #{object.inspect} = #{str}"
|
#puts "STRING OF #{object.inspect} = #{str}"
|
||||||
if str =~ /^-?\.?\d/
|
# If XPath ever gets scientific notation...
|
||||||
|
#if str =~ /^\s*-?(\d*\.?\d+|\d+\.)([Ee]\d*)?\s*$/
|
||||||
|
if str =~ /^\s*-?(\d*\.?\d+|\d+\.)\s*$/
|
||||||
str.to_f
|
str.to_f
|
||||||
else
|
else
|
||||||
(0.0 / 0.0)
|
(0.0 / 0.0)
|
||||||
|
|
|
@ -55,10 +55,8 @@ module REXML
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the index that +self+ has in its parent's elements array, so that
|
# Returns the position that +self+ holds in its parent's array, indexed
|
||||||
# the following equation holds true:
|
# from 1.
|
||||||
#
|
|
||||||
# node == node.parent.elements[node.index_in_parent]
|
|
||||||
def index_in_parent
|
def index_in_parent
|
||||||
parent.index(self)+1
|
parent.index(self)+1
|
||||||
end
|
end
|
||||||
|
|
|
@ -146,8 +146,6 @@ module REXML
|
||||||
|
|
||||||
# Returns true if there are no more events
|
# Returns true if there are no more events
|
||||||
def empty?
|
def empty?
|
||||||
#STDERR.puts "@source.empty? = #{@source.empty?}"
|
|
||||||
#STDERR.puts "@stack.empty? = #{@stack.empty?}"
|
|
||||||
return (@source.empty? and @stack.empty?)
|
return (@source.empty? and @stack.empty?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -365,8 +363,6 @@ module REXML
|
||||||
else
|
else
|
||||||
md = @source.match( TEXT_PATTERN, true )
|
md = @source.match( TEXT_PATTERN, true )
|
||||||
if md[0].length == 0
|
if md[0].length == 0
|
||||||
puts "EMPTY = #{empty?}"
|
|
||||||
puts "BUFFER = \"#{@source.buffer}\""
|
|
||||||
@source.match( /(\s+)/, true )
|
@source.match( /(\s+)/, true )
|
||||||
end
|
end
|
||||||
#STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0
|
#STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0
|
||||||
|
|
|
@ -16,6 +16,10 @@ module REXML
|
||||||
@tag_stack = []
|
@tag_stack = []
|
||||||
@entities = {}
|
@entities = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def source
|
||||||
|
@parser.source
|
||||||
|
end
|
||||||
|
|
||||||
def add_listener( listener )
|
def add_listener( listener )
|
||||||
@parser.add_listener( listener )
|
@parser.add_listener( listener )
|
||||||
|
|
|
@ -23,7 +23,8 @@ module REXML
|
||||||
case event[0]
|
case event[0]
|
||||||
when :end_document
|
when :end_document
|
||||||
unless tag_stack.empty?
|
unless tag_stack.empty?
|
||||||
raise ParseException.new("No close tag for #{tag_stack.inspect}")
|
#raise ParseException.new("No close tag for #{tag_stack.inspect}")
|
||||||
|
raise ParseException.new("No close tag for #{@build_context.xpath}")
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
when :start_element
|
when :start_element
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#
|
#
|
||||||
# Main page:: http://www.germane-software.com/software/rexml
|
# Main page:: http://www.germane-software.com/software/rexml
|
||||||
# Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
|
# Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
|
||||||
# Version:: 3.1.5
|
# Version:: 3.1.6
|
||||||
# Date:: 2006/250
|
# Date:: 2006/335
|
||||||
#
|
#
|
||||||
# This API documentation can be downloaded from the REXML home page, or can
|
# This API documentation can be downloaded from the REXML home page, or can
|
||||||
# be accessed online[http://www.germane-software.com/software/rexml_doc]
|
# be accessed online[http://www.germane-software.com/software/rexml_doc]
|
||||||
|
@ -21,8 +21,8 @@
|
||||||
# online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
|
# online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
|
||||||
module REXML
|
module REXML
|
||||||
COPYRIGHT = "Copyright © 2001-2006 Sean Russell <ser@germane-software.com>"
|
COPYRIGHT = "Copyright © 2001-2006 Sean Russell <ser@germane-software.com>"
|
||||||
DATE = "2006/250"
|
DATE = "2006/335"
|
||||||
VERSION = "3.1.5"
|
VERSION = "3.1.6"
|
||||||
|
|
||||||
Copyright = COPYRIGHT
|
Copyright = COPYRIGHT
|
||||||
Version = VERSION
|
Version = VERSION
|
||||||
|
|
|
@ -70,7 +70,7 @@ module REXML
|
||||||
# ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
|
# ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
|
||||||
# <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
|
# <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
|
||||||
# ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
|
# ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
|
||||||
def entitydecl content
|
def entitydecl name, decl
|
||||||
end
|
end
|
||||||
# <!NOTATION ...>
|
# <!NOTATION ...>
|
||||||
def notationdecl content
|
def notationdecl content
|
||||||
|
|
|
@ -6,7 +6,7 @@ module REXML
|
||||||
# Generates a Source object
|
# Generates a Source object
|
||||||
# @param arg Either a String, or an IO
|
# @param arg Either a String, or an IO
|
||||||
# @return a Source, or nil if a bad argument was given
|
# @return a Source, or nil if a bad argument was given
|
||||||
def SourceFactory::create_from arg#, slurp=true
|
def SourceFactory::create_from(arg)
|
||||||
if arg.kind_of? String
|
if arg.kind_of? String
|
||||||
Source.new(arg)
|
Source.new(arg)
|
||||||
elsif arg.respond_to? :read and
|
elsif arg.respond_to? :read and
|
||||||
|
@ -35,16 +35,23 @@ module REXML
|
||||||
|
|
||||||
# Constructor
|
# Constructor
|
||||||
# @param arg must be a String, and should be a valid XML document
|
# @param arg must be a String, and should be a valid XML document
|
||||||
def initialize(arg)
|
# @param encoding if non-null, sets the encoding of the source to this
|
||||||
|
# value, overriding all encoding detection
|
||||||
|
def initialize(arg, encoding=nil)
|
||||||
@orig = @buffer = arg
|
@orig = @buffer = arg
|
||||||
self.encoding = check_encoding( @buffer )
|
if encoding
|
||||||
|
self.encoding = encoding
|
||||||
|
else
|
||||||
|
self.encoding = check_encoding( @buffer )
|
||||||
|
end
|
||||||
@line = 0
|
@line = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Inherited from Encoding
|
# Inherited from Encoding
|
||||||
# Overridden to support optimized en/decoding
|
# Overridden to support optimized en/decoding
|
||||||
def encoding=(enc)
|
def encoding=(enc)
|
||||||
super
|
return unless super
|
||||||
@line_break = encode( '>' )
|
@line_break = encode( '>' )
|
||||||
if enc != UTF_8
|
if enc != UTF_8
|
||||||
@buffer = decode(@buffer)
|
@buffer = decode(@buffer)
|
||||||
|
@ -124,7 +131,7 @@ module REXML
|
||||||
#attr_reader :block_size
|
#attr_reader :block_size
|
||||||
|
|
||||||
# block_size has been deprecated
|
# block_size has been deprecated
|
||||||
def initialize(arg, block_size=500)
|
def initialize(arg, block_size=500, encoding=nil)
|
||||||
@er_source = @source = arg
|
@er_source = @source = arg
|
||||||
@to_utf = false
|
@to_utf = false
|
||||||
# Determining the encoding is a deceptively difficult issue to resolve.
|
# Determining the encoding is a deceptively difficult issue to resolve.
|
||||||
|
@ -134,10 +141,12 @@ module REXML
|
||||||
# if there is one. If there isn't one, the file MUST be UTF-8, as per
|
# if there is one. If there isn't one, the file MUST be UTF-8, as per
|
||||||
# the XML spec. If there is one, we can determine the encoding from
|
# the XML spec. If there is one, we can determine the encoding from
|
||||||
# it.
|
# it.
|
||||||
|
@buffer = ""
|
||||||
str = @source.read( 2 )
|
str = @source.read( 2 )
|
||||||
if /\A(?:\xfe\xff|\xff\xfe)/n =~ str
|
if encoding
|
||||||
|
self.encoding = encoding
|
||||||
|
elsif /\A(?:\xfe\xff|\xff\xfe)/n =~ str
|
||||||
self.encoding = check_encoding( str )
|
self.encoding = check_encoding( str )
|
||||||
@line_break = encode( '>' )
|
|
||||||
else
|
else
|
||||||
@line_break = '>'
|
@line_break = '>'
|
||||||
end
|
end
|
||||||
|
@ -159,6 +168,8 @@ module REXML
|
||||||
str = @source.readline(@line_break)
|
str = @source.readline(@line_break)
|
||||||
str = decode(str) if @to_utf and str
|
str = decode(str) if @to_utf and str
|
||||||
@buffer << str
|
@buffer << str
|
||||||
|
rescue Iconv::IllegalSequence
|
||||||
|
raise
|
||||||
rescue
|
rescue
|
||||||
@source = nil
|
@source = nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,6 +42,7 @@ module REXML
|
||||||
# Use this field if you have entities defined for some text, and you don't
|
# Use this field if you have entities defined for some text, and you don't
|
||||||
# want REXML to escape that text in output.
|
# want REXML to escape that text in output.
|
||||||
# Text.new( "<&", false, nil, false ) #-> "<&"
|
# Text.new( "<&", false, nil, false ) #-> "<&"
|
||||||
|
# Text.new( "<&", false, nil, false ) #-> "&lt;&amp;"
|
||||||
# Text.new( "<&", false, nil, true ) #-> Parse exception
|
# Text.new( "<&", false, nil, true ) #-> Parse exception
|
||||||
# Text.new( "<&", false, nil, true ) #-> "<&"
|
# Text.new( "<&", false, nil, true ) #-> "<&"
|
||||||
# # Assume that the entity "s" is defined to be "sean"
|
# # Assume that the entity "s" is defined to be "sean"
|
||||||
|
@ -172,17 +173,6 @@ module REXML
|
||||||
end
|
end
|
||||||
@unnormalized = Text::unnormalize( @string, doctype )
|
@unnormalized = Text::unnormalize( @string, doctype )
|
||||||
end
|
end
|
||||||
|
|
||||||
def wrap(string, width, addnewline=false)
|
|
||||||
# Recursivly wrap string at width.
|
|
||||||
return string if string.length <= width
|
|
||||||
place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
|
|
||||||
if addnewline then
|
|
||||||
return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
|
|
||||||
else
|
|
||||||
return string[0,place] + "\n" + wrap(string[place+1..-1], width)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sets the contents of this text node. This expects the text to be
|
# Sets the contents of this text node. This expects the text to be
|
||||||
# unnormalized. It returns self.
|
# unnormalized. It returns self.
|
||||||
|
@ -198,17 +188,28 @@ module REXML
|
||||||
@raw = false
|
@raw = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def indent_text(string, level=1, style="\t", indentfirstline=true)
|
def wrap(string, width, addnewline=false)
|
||||||
return string if level < 0
|
# Recursivly wrap string at width.
|
||||||
new_string = ''
|
return string if string.length <= width
|
||||||
string.each { |line|
|
place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
|
||||||
indent_string = style * level
|
if addnewline then
|
||||||
new_line = (indent_string + line).sub(/[\s]+$/,'')
|
return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
|
||||||
new_string << new_line
|
else
|
||||||
}
|
return string[0,place] + "\n" + wrap(string[place+1..-1], width)
|
||||||
new_string.strip! unless indentfirstline
|
end
|
||||||
return new_string
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def indent_text(string, level=1, style="\t", indentfirstline=true)
|
||||||
|
return string if level < 0
|
||||||
|
new_string = ''
|
||||||
|
string.each { |line|
|
||||||
|
indent_string = style * level
|
||||||
|
new_line = (indent_string + line).sub(/[\s]+$/,'')
|
||||||
|
new_string << new_line
|
||||||
|
}
|
||||||
|
new_string.strip! unless indentfirstline
|
||||||
|
return new_string
|
||||||
|
end
|
||||||
|
|
||||||
def write( writer, indent=-1, transitive=false, ie_hack=false )
|
def write( writer, indent=-1, transitive=false, ie_hack=false )
|
||||||
s = to_s()
|
s = to_s()
|
||||||
|
@ -286,9 +287,10 @@ module REXML
|
||||||
def Text::normalize( input, doctype=nil, entity_filter=nil )
|
def Text::normalize( input, doctype=nil, entity_filter=nil )
|
||||||
copy = input
|
copy = input
|
||||||
# Doing it like this rather than in a loop improves the speed
|
# Doing it like this rather than in a loop improves the speed
|
||||||
|
#copy = copy.gsub( EREFERENCE, '&' )
|
||||||
|
copy = copy.gsub( "&", "&" )
|
||||||
if doctype
|
if doctype
|
||||||
# Replace all ampersands that aren't part of an entity
|
# Replace all ampersands that aren't part of an entity
|
||||||
copy = copy.gsub( EREFERENCE, '&' )
|
|
||||||
doctype.entities.each_value do |entity|
|
doctype.entities.each_value do |entity|
|
||||||
copy = copy.gsub( entity.value,
|
copy = copy.gsub( entity.value,
|
||||||
"&#{entity.name};" ) if entity.value and
|
"&#{entity.name};" ) if entity.value and
|
||||||
|
@ -296,7 +298,6 @@ module REXML
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Replace all ampersands that aren't part of an entity
|
# Replace all ampersands that aren't part of an entity
|
||||||
copy = copy.gsub( EREFERENCE, '&' )
|
|
||||||
DocType::DEFAULT_ENTITIES.each_value do |entity|
|
DocType::DEFAULT_ENTITIES.each_value do |entity|
|
||||||
copy = copy.gsub(entity.value, "&#{entity.name};" )
|
copy = copy.gsub(entity.value, "&#{entity.name};" )
|
||||||
end
|
end
|
||||||
|
|
|
@ -162,6 +162,10 @@ module REXML
|
||||||
while path_stack.length > 0
|
while path_stack.length > 0
|
||||||
#puts "Path stack = #{path_stack.inspect}"
|
#puts "Path stack = #{path_stack.inspect}"
|
||||||
#puts "Nodeset is #{nodeset.inspect}"
|
#puts "Nodeset is #{nodeset.inspect}"
|
||||||
|
if nodeset.length == 0
|
||||||
|
path_stack.clear
|
||||||
|
return []
|
||||||
|
end
|
||||||
case (op = path_stack.shift)
|
case (op = path_stack.shift)
|
||||||
when :document
|
when :document
|
||||||
nodeset = [ nodeset[0].root_node ]
|
nodeset = [ nodeset[0].root_node ]
|
||||||
|
@ -235,9 +239,11 @@ module REXML
|
||||||
name = path_stack.shift
|
name = path_stack.shift
|
||||||
for element in nodeset
|
for element in nodeset
|
||||||
if element.node_type == :element
|
if element.node_type == :element
|
||||||
#puts element.name
|
#puts "Element name = #{element.name}"
|
||||||
attr = element.attribute( name, get_namespace(element, prefix) )
|
#puts "get_namespace( #{element.inspect}, #{prefix} ) = #{get_namespace(element, prefix)}"
|
||||||
new_nodeset << attr if attr
|
attrib = element.attribute( name, get_namespace(element, prefix) )
|
||||||
|
#puts "attrib = #{attrib.inspect}"
|
||||||
|
new_nodeset << attrib if attrib
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
when :any
|
when :any
|
||||||
|
@ -299,8 +305,10 @@ module REXML
|
||||||
#puts "Adding node #{node.inspect}" if result == (index+1)
|
#puts "Adding node #{node.inspect}" if result == (index+1)
|
||||||
new_nodeset << node if result == (index+1)
|
new_nodeset << node if result == (index+1)
|
||||||
elsif result.instance_of? Array
|
elsif result.instance_of? Array
|
||||||
#puts "Adding node #{node.inspect}" if result.size > 0
|
if result.size > 0 and result.inject(false) {|k,s| s or k}
|
||||||
new_nodeset << node if result.size > 0
|
#puts "Adding node #{node.inspect}" if result.size > 0
|
||||||
|
new_nodeset << node if result.size > 0
|
||||||
|
end
|
||||||
else
|
else
|
||||||
#puts "Adding node #{node.inspect}" if result
|
#puts "Adding node #{node.inspect}" if result
|
||||||
new_nodeset << node if result
|
new_nodeset << node if result
|
||||||
|
@ -381,9 +389,19 @@ module REXML
|
||||||
node_types = ELEMENTS
|
node_types = ELEMENTS
|
||||||
|
|
||||||
when :namespace
|
when :namespace
|
||||||
new_set = []
|
new_nodeset = []
|
||||||
|
prefix = path_stack.shift
|
||||||
for node in nodeset
|
for node in nodeset
|
||||||
new_nodeset << node.namespace if node.node_type == :element or node.node_type == :attribute
|
if (node.node_type == :element or node.node_type == :attribute)
|
||||||
|
if (node.node_type == :element)
|
||||||
|
namespaces = node.namespaces
|
||||||
|
else
|
||||||
|
namespaces = node.element.namesapces
|
||||||
|
end
|
||||||
|
if (node.namespace == namespaces[prefix])
|
||||||
|
new_nodeset << node
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
nodeset = new_nodeset
|
nodeset = new_nodeset
|
||||||
|
|
||||||
|
@ -404,6 +422,18 @@ module REXML
|
||||||
#puts "RES => #{res.inspect}"
|
#puts "RES => #{res.inspect}"
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
when :and
|
||||||
|
left = expr( path_stack.shift, nodeset.dup, context )
|
||||||
|
#puts "LEFT => #{left.inspect} (#{left.class.name})"
|
||||||
|
if left == false || left.nil? || !left.inject(false) {|a,b| a | b}
|
||||||
|
return []
|
||||||
|
end
|
||||||
|
right = expr( path_stack.shift, nodeset.dup, context )
|
||||||
|
#puts "RIGHT => #{right.inspect} (#{right.class.name})"
|
||||||
|
res = equality_relational_compare( left, op, right )
|
||||||
|
#puts "RES => #{res.inspect}"
|
||||||
|
return res
|
||||||
|
|
||||||
when :div
|
when :div
|
||||||
left = Functions::number(expr(path_stack.shift, nodeset, context)).to_f
|
left = Functions::number(expr(path_stack.shift, nodeset, context)).to_f
|
||||||
right = Functions::number(expr(path_stack.shift, nodeset, context)).to_f
|
right = Functions::number(expr(path_stack.shift, nodeset, context)).to_f
|
||||||
|
@ -477,7 +507,7 @@ module REXML
|
||||||
# The next two methods are BAD MOJO!
|
# The next two methods are BAD MOJO!
|
||||||
# This is my achilles heel. If anybody thinks of a better
|
# This is my achilles heel. If anybody thinks of a better
|
||||||
# way of doing this, be my guest. This really sucks, but
|
# way of doing this, be my guest. This really sucks, but
|
||||||
# it took me three days to get it to work at all.
|
# it is a wonder it works at all.
|
||||||
# ########################################################
|
# ########################################################
|
||||||
|
|
||||||
def descendant_or_self( path_stack, nodeset )
|
def descendant_or_self( path_stack, nodeset )
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue