From db54b7c7bc7408f5e853b61f51b3977d7f9ed2e2 Mon Sep 17 00:00:00 2001 From: jez Date: Mon, 3 Nov 2008 18:29:10 +0000 Subject: [PATCH] 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. --- include/XPath/impl/xpath_object.hpp | 9 ++++- tests/XPath/execute_test.hpp | 54 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/include/XPath/impl/xpath_object.hpp b/include/XPath/impl/xpath_object.hpp index 683e2b0a..4fe4813b 100644 --- a/include/XPath/impl/xpath_object.hpp +++ b/include/XPath/impl/xpath_object.hpp @@ -413,7 +413,14 @@ template double stringAsNumber(const string_type& str) { try { - return boost::lexical_cast(Arabica::text::normalize_whitespace(str)); + static string_type PLUS = string_adaptor::construct_from_utf8("+"); + + string_type n_str = Arabica::text::normalize_whitespace(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(n_str); } // try catch(const boost::bad_lexical_cast&) { return NaN; diff --git a/tests/XPath/execute_test.hpp b/tests/XPath/execute_test.hpp index 288304e8..c922c42e 100644 --- a/tests/XPath/execute_test.hpp +++ b/tests/XPath/execute_test.hpp @@ -1116,6 +1116,54 @@ public: assertTrue(isNaN(result.asNumber())); } // testNumberFn7 + void testNumberFn8() + { + using namespace Arabica::XPath; + XPathValue 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 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 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 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 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 result = parser.evaluate_expr(SA::construct_from_utf8("number(' +1.5 ')"), document_); + assertValuesEqual(NUMBER, result.type()); + assertTrue(isNaN(result.asNumber())); + } // testNumberFn13 + void testFloorFn1() { using namespace Arabica::XPath; @@ -2575,6 +2623,12 @@ TestSuite* ExecuteTest_suite() suiteOfTests->addTest(new TestCaller >("testNumberFn5", &ExecuteTest::testNumberFn5)); suiteOfTests->addTest(new TestCaller >("testNumberFn6", &ExecuteTest::testNumberFn6)); suiteOfTests->addTest(new TestCaller >("testNumberFn7", &ExecuteTest::testNumberFn7)); + suiteOfTests->addTest(new TestCaller >("testNumberFn8", &ExecuteTest::testNumberFn8)); + suiteOfTests->addTest(new TestCaller >("testNumberFn9", &ExecuteTest::testNumberFn9)); + suiteOfTests->addTest(new TestCaller >("testNumberFn10", &ExecuteTest::testNumberFn10)); + suiteOfTests->addTest(new TestCaller >("testNumberFn11", &ExecuteTest::testNumberFn11)); + suiteOfTests->addTest(new TestCaller >("testNumberFn12", &ExecuteTest::testNumberFn12)); + suiteOfTests->addTest(new TestCaller >("testNumberFn13", &ExecuteTest::testNumberFn13)); suiteOfTests->addTest(new TestCaller >("testFloorFn1", &ExecuteTest::testFloorFn1)); suiteOfTests->addTest(new TestCaller >("testFloorFn2", &ExecuteTest::testFloorFn2)); suiteOfTests->addTest(new TestCaller >("testFloorFn3", &ExecuteTest::testFloorFn3));