Better conversion of types to numbers.

The XPath number() function should also be capable of converting booleans to
numbers, something it previously was not able to do. In order to do this
reliably we can't rely on the string() function as this would make it impossible
to distinguish between literal string values and booleans. This is due to
true(), which returns a TrueClass, being converted to the string "true". This
string in turn can't be converted to a float.
This commit is contained in:
Yorick Peterse 2014-08-27 23:38:47 +02:00
parent fcb28d5ae8
commit ac06670c24
2 changed files with 34 additions and 3 deletions

View File

@ -780,7 +780,7 @@ module Oga
convert = process(expression, context)
if convert.is_a?(XML::NodeSet)
convert = convert.first
convert = convert[0]
end
else
convert = current_node
@ -815,9 +815,28 @@ module Oga
# @return [Float]
#
def on_call_number(context, expression = nil)
str_val = on_call_string(context, expression)
convert = nil
return Float(str_val) rescue Float::NAN
if expression
exp_retval = process(expression, context)
if exp_retval.is_a?(XML::NodeSet)
convert = first_node_text(exp_retval)
elsif exp_retval == true
convert = 1.0
elsif exp_retval == false
convert = 0.0
elsif exp_retval
convert = exp_retval
end
else
convert = current_node.text
end
return Float(convert) rescue Float::NAN
end
##

View File

@ -15,6 +15,14 @@ describe Oga::XPath::Evaluator do
@evaluator.evaluate('number("10.5")').should == 10.5
end
example 'convert boolean true to a number' do
@evaluator.evaluate('number(true())').should == 1.0
end
example 'convert boolean false to a number' do
@evaluator.evaluate('number(false())').should be_zero
end
example 'convert a node set to a number' do
@evaluator.evaluate('number(root/a)').should == 10.0
end
@ -30,5 +38,9 @@ describe Oga::XPath::Evaluator do
example 'return NaN for values that can not be converted to floats' do
@evaluator.evaluate('number("a")').should be_nan
end
example 'return NaN for empty node sets' do
@evaluator.evaluate('number(foo)').should be_nan
end
end
end