summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-09-08 02:03:44 +0000
committerser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2006-09-08 02:03:44 +0000
commitec847fad4e0c1b96c6cf91e7ff14ef0820f7ccc3 (patch)
tree5e6ceeb9a9fcb13bfba05d7eef0b49d398f78a76
parentb2a8ca6dd61358ed72c3d4f5f61767052c9b4d27 (diff)
Merged changes into HEAD from REXML 3.1.5.
The list of bug fixes/enhancements is at: http://www.germane-software.com/projects/rexml/query?status=closed&milestone=3.1.5 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10888 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--lib/rexml/comment.rb24
-rw-r--r--lib/rexml/element.rb23
-rw-r--r--lib/rexml/functions.rb4
-rw-r--r--lib/rexml/parsers/baseparser.rb13
-rw-r--r--lib/rexml/parsers/xpathparser.rb8
-rw-r--r--lib/rexml/rexml.rb8
-rw-r--r--lib/rexml/xpath.rb14
-rw-r--r--lib/rexml/xpath_parser.rb40
8 files changed, 87 insertions, 47 deletions
diff --git a/lib/rexml/comment.rb b/lib/rexml/comment.rb
index cb91d47f8c..a4fcb58c8d 100644
--- a/lib/rexml/comment.rb
+++ b/lib/rexml/comment.rb
@@ -35,31 +35,19 @@ module REXML
end
# output::
- # Where to write the string
+ # Where to write the string
# indent::
- # An integer. If -1, no indenting will be used; otherwise, the
- # indentation will be this number of spaces, and children will be
- # indented an additional amount.
+ # An integer. If -1, no indenting will be used; otherwise, the
+ # indentation will be this number of spaces, and children will be
+ # indented an additional amount.
# transitive::
- # If transitive is true and indent is >= 0, then the output will be
- # pretty-printed in such a way that the added whitespace does not affect
- # the absolute *value* of the document -- that is, it leaves the value
- # and number of Text nodes in the document unchanged.
+ # Ignored by this class. The contents of comments are never modified.
# ie_hack::
- # Internet Explorer is the worst piece of crap to have ever been
- # written, with the possible exception of Windows itself. Since IE is
- # unable to parse proper XML, we have to provide a hack to generate XML
- # that IE's limited abilities can handle. This hack inserts a space
- # before the /> on empty tags.
- #
+ # Needed for conformity to the child API, but not used by this class.
def write( output, indent=-1, transitive=false, ie_hack=false )
indent( output, indent )
output << START
output << @string
- if indent>-1
- output << "\n"
- indent( output, indent )
- end
output << STOP
end
diff --git a/lib/rexml/element.rb b/lib/rexml/element.rb
index 80463d95b7..435076420a 100644
--- a/lib/rexml/element.rb
+++ b/lib/rexml/element.rb
@@ -938,6 +938,29 @@ module REXML
def each( xpath=nil, &block)
XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
end
+
+ def collect( xpath=nil, &block )
+ collection = []
+ XPath::each( @element, xpath ) {|e|
+ collection << yield(e) if e.kind_of?(Element)
+ }
+ collection
+ end
+
+ def inject( xpath=nil, initial=nil, &block )
+ first = true
+ XPath::each( @element, xpath ) {|e|
+ if (e.kind_of? Element)
+ if (first and initial == nil)
+ initial = e
+ first = false
+ else
+ initial = yield( initial, e ) if e.kind_of? Element
+ end
+ end
+ }
+ initial
+ end
# Returns the number of +Element+ children of the parent object.
# doc = Document.new '<a>sean<b/>elliott<b/>russell<b/></a>'
diff --git a/lib/rexml/functions.rb b/lib/rexml/functions.rb
index c09ffdeae7..d741dbdab7 100644
--- a/lib/rexml/functions.rb
+++ b/lib/rexml/functions.rb
@@ -326,8 +326,8 @@ module REXML
else
str = string( object )
#puts "STRING OF #{object.inspect} = #{str}"
- if str =~ /^\d+/
- object.to_s.to_f
+ if str =~ /^-?\.?\d/
+ str.to_f
else
(0.0 / 0.0)
end
diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb
index bce4ba4c20..2cfcf02308 100644
--- a/lib/rexml/parsers/baseparser.rb
+++ b/lib/rexml/parsers/baseparser.rb
@@ -96,6 +96,13 @@ module REXML
"apos" => [/&apos;/, "&apos;", "'", /'/]
}
+
+ ######################################################################
+ # These are patterns to identify common markup errors, to make the
+ # error messages more informative.
+ ######################################################################
+ MISSING_ATTRIBUTE_QUOTES = /^<#{NAME_STR}\s+#{NAME_STR}\s*=\s*[^"']/um
+
def initialize( source )
self.stream = source
end
@@ -335,7 +342,11 @@ module REXML
else
# Get the next tag
md = @source.match(TAG_MATCH, true)
- raise REXML::ParseException.new("malformed XML: missing tag start", @source) unless md
+ unless md
+ # Check for missing attribute quotes
+ raise REXML::ParseException.new("missing attribute quote", @source) if @source.match(MISSING_ATTRIBUTE_QUOTES )
+ raise REXML::ParseException.new("malformed XML: missing tag start", @source)
+ end
attrs = []
if md[2].size > 0
attrs = md[2].scan( ATTRIBUTE_PATTERN )
diff --git a/lib/rexml/parsers/xpathparser.rb b/lib/rexml/parsers/xpathparser.rb
index 6bac852d6b..6f5b21cd93 100644
--- a/lib/rexml/parsers/xpathparser.rb
+++ b/lib/rexml/parsers/xpathparser.rb
@@ -596,7 +596,13 @@ module REXML
parsed << :function
parsed << fname
path = FunctionCall(path, parsed)
- when LITERAL, NUMBER
+ when NUMBER
+ #puts "LITERAL or NUMBER: #$1"
+ varname = $1.nil? ? $2 : $1
+ path = $'
+ parsed << :literal
+ parsed << (varname.include?('.') ? varname.to_f : varname.to_i)
+ when LITERAL
#puts "LITERAL or NUMBER: #$1"
varname = $1.nil? ? $2 : $1
path = $'
diff --git a/lib/rexml/rexml.rb b/lib/rexml/rexml.rb
index ca154443b5..68759ab3f8 100644
--- a/lib/rexml/rexml.rb
+++ b/lib/rexml/rexml.rb
@@ -10,8 +10,8 @@
#
# Main page:: http://www.germane-software.com/software/rexml
# Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
-# Version:: 3.1.4
-# Date:: 2006/104
+# Version:: 3.1.5
+# Date:: 2006/250
#
# This API documentation can be downloaded from the REXML home page, or can
# 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]
module REXML
COPYRIGHT = "Copyright © 2001-2006 Sean Russell <ser@germane-software.com>"
- DATE = "2006/104"
- VERSION = "3.1.4"
+ DATE = "2006/250"
+ VERSION = "3.1.5"
Copyright = COPYRIGHT
Version = VERSION
diff --git a/lib/rexml/xpath.rb b/lib/rexml/xpath.rb
index 1ed440868b..939399e283 100644
--- a/lib/rexml/xpath.rb
+++ b/lib/rexml/xpath.rb
@@ -19,9 +19,9 @@ module REXML
# XPath.first( node )
# XPath.first( doc, "//b"} )
# XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
- def XPath::first element, path=nil, namespaces={}, variables={}
- raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.kind_of? Hash
- raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of? Hash
+ def XPath::first element, path=nil, namespaces=nil, variables={}
+ raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
+ raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
parser = XPathParser.new
parser.namespaces = namespaces
parser.variables = variables
@@ -42,9 +42,9 @@ module REXML
# XPath.each( node ) { |el| ... }
# XPath.each( node, '/*[@attr='v']' ) { |el| ... }
# XPath.each( node, 'ancestor::x' ) { |el| ... }
- def XPath::each element, path=nil, namespaces={}, variables={}, &block
- raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.kind_of? Hash
- raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of? Hash
+ def XPath::each element, path=nil, namespaces=nil, variables={}, &block
+ raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
+ raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
parser = XPathParser.new
parser.namespaces = namespaces
parser.variables = variables
@@ -54,7 +54,7 @@ module REXML
end
# Returns an array of nodes matching a given XPath.
- def XPath::match element, path=nil, namespaces={}, variables={}
+ def XPath::match element, path=nil, namespaces=nil, variables={}
parser = XPathParser.new
parser.namespaces = namespaces
parser.variables = variables
diff --git a/lib/rexml/xpath_parser.rb b/lib/rexml/xpath_parser.rb
index 98ed70cc10..a813236e10 100644
--- a/lib/rexml/xpath_parser.rb
+++ b/lib/rexml/xpath_parser.rb
@@ -10,9 +10,13 @@ class Object
end
end
class Symbol
- def dclone
- self
- end
+ def dclone ; self ; end
+end
+class Fixnum
+ def dclone ; self ; end
+end
+class Float
+ def dclone ; self ; end
end
class Array
def dclone
@@ -34,7 +38,7 @@ module REXML
def initialize( )
@parser = REXML::Parsers::XPathParser.new
- @namespaces = {}
+ @namespaces = nil
@variables = {}
end
@@ -130,6 +134,21 @@ module REXML
private
+ # Returns a String namespace for a node, given a prefix
+ # The rules are:
+ #
+ # 1. Use the supplied namespace mapping first.
+ # 2. If no mapping was supplied, use the context node to look up the namespace
+ def get_namespace( node, prefix )
+ if @namespaces
+ return @namespaces[prefix] || ''
+ else
+ return node.namespace( prefix ) if node.node_type == :element
+ return ''
+ end
+ end
+
+
# Expr takes a stack of path elements and a set of nodes (either a Parent
# or an Array and returns an Array of matching nodes
ALL = [ :attribute, :element, :text, :processing_instruction, :comment ]
@@ -152,12 +171,9 @@ module REXML
#puts "IN QNAME"
prefix = path_stack.shift
name = path_stack.shift
- default_ns = @namespaces[prefix]
- default_ns = default_ns ? default_ns : ''
nodeset.delete_if do |node|
- ns = default_ns
# FIXME: This DOUBLES the time XPath searches take
- ns = node.namespace( prefix ) if node.node_type == :element and ns == ''
+ ns = get_namespace( node, prefix )
#puts "NS = #{ns.inspect}"
#puts "node.node_type == :element => #{node.node_type == :element}"
if node.node_type == :element
@@ -209,11 +225,7 @@ module REXML
node_types = ELEMENTS
when :literal
- literal = path_stack.shift
- if literal =~ /^\d+(\.\d+)?$/
- return ($1 ? literal.to_f : literal.to_i)
- end
- return literal
+ return path_stack.shift
when :attribute
new_nodeset = []
@@ -224,7 +236,7 @@ module REXML
for element in nodeset
if element.node_type == :element
#puts element.name
- attr = element.attribute( name, @namespaces[prefix] )
+ attr = element.attribute( name, get_namespace(element, prefix) )
new_nodeset << attr if attr
end
end