mirror of
https://github.com/jezhiggins/arabica
synced 2025-01-30 08:38:15 +01:00
In XPath numbers do not have leading +, so, while '-1.5' converts to -1.5,
'+1.5' converts to NaN. Weird and counter-intuitive perhaps, but it's there in the spec. Sort now sets context node appropriately, so current() works in sorting expressions.
This commit is contained in:
commit
f74170e268
3 changed files with 81 additions and 9 deletions
|
@ -413,7 +413,14 @@ template<class string_type, class string_adaptor>
|
|||
double stringAsNumber(const string_type& str)
|
||||
{
|
||||
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
|
||||
catch(const boost::bad_lexical_cast&) {
|
||||
return NaN;
|
||||
|
|
|
@ -74,8 +74,8 @@ private:
|
|||
typedef bool(Sort::*sortFn)(const DOM::Node<std::string>& n1, const DOM::Node<std::string>& n2) const;
|
||||
bool numberAscending(const DOM::Node<std::string>& n1, const DOM::Node<std::string>& n2) const
|
||||
{
|
||||
double v1 = select_->evaluateAsNumber(n1, context_->xpathContext());
|
||||
double v2 = select_->evaluateAsNumber(n2, context_->xpathContext());
|
||||
double v1 = grabAsNumber(n1);
|
||||
double v2 = grabAsNumber(n2);
|
||||
|
||||
bool nan1 = Arabica::XPath::isNaN(v1);
|
||||
bool nan2 = Arabica::XPath::isNaN(v2);
|
||||
|
@ -92,8 +92,8 @@ private:
|
|||
} // numberAscending
|
||||
bool numberDescending(const DOM::Node<std::string>& n1, const DOM::Node<std::string>& n2) const
|
||||
{
|
||||
double v1 = select_->evaluateAsNumber(n1, context_->xpathContext());
|
||||
double v2 = select_->evaluateAsNumber(n2, context_->xpathContext());
|
||||
double v1 = grabAsNumber(n1);
|
||||
double v2 = grabAsNumber(n2);
|
||||
|
||||
bool nan1 = Arabica::XPath::isNaN(v1);
|
||||
bool nan2 = Arabica::XPath::isNaN(v2);
|
||||
|
@ -110,8 +110,8 @@ private:
|
|||
} // numberDescending
|
||||
bool stringAscending(const DOM::Node<std::string>& n1, const DOM::Node<std::string>& n2) const
|
||||
{
|
||||
std::string v1 = select_->evaluateAsString(n1, context_->xpathContext());
|
||||
std::string v2 = select_->evaluateAsString(n2, context_->xpathContext());
|
||||
std::string v1 = grabAsString(n1);
|
||||
std::string v2 = grabAsString(n2);
|
||||
|
||||
if((v1 == v2) && (sub_sort_))
|
||||
return (*sub_sort_)(n1, n2);
|
||||
|
@ -120,8 +120,8 @@ private:
|
|||
} // stringAscending
|
||||
bool stringDescending(const DOM::Node<std::string>& n1, const DOM::Node<std::string>& n2) const
|
||||
{
|
||||
std::string v1 = select_->evaluateAsString(n1, context_->xpathContext());
|
||||
std::string v2 = select_->evaluateAsString(n2, context_->xpathContext());
|
||||
std::string v1 = grabAsString(n1);
|
||||
std::string v2 = grabAsString(n2);
|
||||
|
||||
if((v1 == v2) && (sub_sort_))
|
||||
return (*sub_sort_)(n1, n2);
|
||||
|
@ -129,6 +129,17 @@ private:
|
|||
return v1 > v2;
|
||||
} // stringAscending
|
||||
|
||||
std::string grabAsString(const DOM::Node<std::string>& n) const
|
||||
{
|
||||
context_->setPosition(n, 1);
|
||||
return select_->evaluateAsString(n, context_->xpathContext());
|
||||
} // grabAsString
|
||||
double grabAsNumber(const DOM::Node<std::string>& n) const
|
||||
{
|
||||
context_->setPosition(n, 1);
|
||||
return select_->evaluateAsNumber(n, context_->xpathContext());
|
||||
} // grabAsString
|
||||
|
||||
Arabica::XPath::XPathExpressionPtr<std::string> select_;
|
||||
Arabica::XPath::XPathExpressionPtr<std::string> lang_;
|
||||
Arabica::XPath::XPathExpressionPtr<std::string> datatype_;
|
||||
|
|
|
@ -1116,6 +1116,54 @@ public:
|
|||
assertTrue(isNaN(result.asNumber()));
|
||||
} // 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()
|
||||
{
|
||||
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> >("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> >("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> >("testFloorFn2", &ExecuteTest<string_type, string_adaptor>::testFloorFn2));
|
||||
suiteOfTests->addTest(new TestCaller<ExecuteTest<string_type, string_adaptor> >("testFloorFn3", &ExecuteTest<string_type, string_adaptor>::testFloorFn3));
|
||||
|
|
Loading…
Add table
Reference in a new issue