In XPath numbers do not have leading +, so, while '-1.5' converts to -1.5, '+1.5' converts to NaN. Weird and counter-intuitive, but in the spec.

This commit is contained in:
jez 2008-11-03 18:29:10 +00:00
parent b9a2e6e2f6
commit db54b7c7bc
2 changed files with 62 additions and 1 deletions

View file

@ -413,7 +413,14 @@ template<class string_type, class string_adaptor>
double stringAsNumber(const string_type& str) double stringAsNumber(const string_type& str)
{ {
try { try {
return boost::lexical_cast<double>(Arabica::text::normalize_whitespace<string_type, string_adaptor>(str)); static string_type PLUS = string_adaptor::construct_from_utf8("+");
string_type n_str = Arabica::text::normalize_whitespace<string_type, string_adaptor>(str);
// '+1.5' is not a number according to XPath spec, counter intuitive as that is
if(string_adaptor::find(n_str, PLUS) == 0)
return NaN;
return boost::lexical_cast<double>(n_str);
} // try } // try
catch(const boost::bad_lexical_cast&) { catch(const boost::bad_lexical_cast&) {
return NaN; return NaN;

View file

@ -1116,6 +1116,54 @@ public:
assertTrue(isNaN(result.asNumber())); assertTrue(isNaN(result.asNumber()));
} // testNumberFn7 } // testNumberFn7
void testNumberFn8()
{
using namespace Arabica::XPath;
XPathValue<string_type, string_adaptor> result = parser.evaluate_expr(SA::construct_from_utf8("number('-1.5')"), document_);
assertValuesEqual(NUMBER, result.type());
assertDoublesEqual(-1.5, result.asNumber(), 0.0);
} // testNumberFn8
void testNumberFn9()
{
using namespace Arabica::XPath;
XPathValue<string_type, string_adaptor> result = parser.evaluate_expr(SA::construct_from_utf8("number('+1.5')"), document_);
assertValuesEqual(NUMBER, result.type());
assertTrue(isNaN(result.asNumber()));
} // testNumberFn9
void testNumberFn10()
{
using namespace Arabica::XPath;
XPathValue<string_type, string_adaptor> result = parser.evaluate_expr(SA::construct_from_utf8("number('-1.5 ')"), document_);
assertValuesEqual(NUMBER, result.type());
assertDoublesEqual(-1.5, result.asNumber(), 0.0);
} // testNumberFn10
void testNumberFn11()
{
using namespace Arabica::XPath;
XPathValue<string_type, string_adaptor> result = parser.evaluate_expr(SA::construct_from_utf8("number('+1.5')"), document_);
assertValuesEqual(NUMBER, result.type());
assertTrue(isNaN(result.asNumber()));
} // testNumberFn11
void testNumberFn12()
{
using namespace Arabica::XPath;
XPathValue<string_type, string_adaptor> result = parser.evaluate_expr(SA::construct_from_utf8("number(' -1.5 ')"), document_);
assertValuesEqual(NUMBER, result.type());
assertDoublesEqual(-1.5, result.asNumber(), 0.0);
} // testNumberFn12
void testNumberFn13()
{
using namespace Arabica::XPath;
XPathValue<string_type, string_adaptor> result = parser.evaluate_expr(SA::construct_from_utf8("number(' +1.5 ')"), document_);
assertValuesEqual(NUMBER, result.type());
assertTrue(isNaN(result.asNumber()));
} // testNumberFn13
void testFloorFn1() void testFloorFn1()
{ {
using namespace Arabica::XPath; using namespace Arabica::XPath;
@ -2575,6 +2623,12 @@ TestSuite* ExecuteTest_suite()
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn5", &ExecuteTest<string_type, string_adaptor>::testNumberFn5)); suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn5", &ExecuteTest<string_type, string_adaptor>::testNumberFn5));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn6", &ExecuteTest<string_type, string_adaptor>::testNumberFn6)); suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn6", &ExecuteTest<string_type, string_adaptor>::testNumberFn6));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn7", &ExecuteTest<string_type, string_adaptor>::testNumberFn7)); suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn7", &ExecuteTest<string_type, string_adaptor>::testNumberFn7));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn8", &ExecuteTest<string_type, string_adaptor>::testNumberFn8));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn9", &ExecuteTest<string_type, string_adaptor>::testNumberFn9));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn10", &ExecuteTest<string_type, string_adaptor>::testNumberFn10));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn11", &ExecuteTest<string_type, string_adaptor>::testNumberFn11));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn12", &ExecuteTest<string_type, string_adaptor>::testNumberFn12));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testNumberFn13", &ExecuteTest<string_type, string_adaptor>::testNumberFn13));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn1", &ExecuteTest<string_type, string_adaptor>::testFloorFn1)); suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn1", &ExecuteTest<string_type, string_adaptor>::testFloorFn1));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn2", &ExecuteTest<string_type, string_adaptor>::testFloorFn2)); suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn2", &ExecuteTest<string_type, string_adaptor>::testFloorFn2));
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn3", &ExecuteTest<string_type, string_adaptor>::testFloorFn3)); suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn3", &ExecuteTest<string_type, string_adaptor>::testFloorFn3));