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) convert = process(expression, context)
if convert.is_a?(XML::NodeSet) if convert.is_a?(XML::NodeSet)
convert = convert.first convert = convert[0]
end end
else else
convert = current_node convert = current_node
@ -815,9 +815,28 @@ module Oga
# @return [Float] # @return [Float]
# #
def on_call_number(context, expression = nil) 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 end
## ##

View File

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