2005-08-04 22:42:30 +02:00
|
|
|
#ifndef ARABICA_XPATH_FUNCTION_HPP
|
|
|
|
#define ARABICA_XPATH_FUNCTION_HPP
|
|
|
|
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
#include <cmath>
|
2007-09-05 00:55:47 +02:00
|
|
|
#include <XML/XMLCharacterClasses.hpp>
|
2007-09-10 19:24:17 +02:00
|
|
|
#include <text/UnicodeCharacters.hpp>
|
|
|
|
#include <text/normalize_whitespace.hpp>
|
2005-08-04 22:42:30 +02:00
|
|
|
#include "xpath_value.hpp"
|
|
|
|
#include "xpath_execution_context.hpp"
|
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XPath
|
|
|
|
{
|
|
|
|
|
2007-09-09 00:31:24 +02:00
|
|
|
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
|
2005-08-04 22:42:30 +02:00
|
|
|
class XPathFunction
|
|
|
|
{
|
|
|
|
protected:
|
2007-10-25 22:42:00 +02:00
|
|
|
XPathFunction(int minArgs, int maxArgs, const std::vector<XPathExpression<string_type, string_adaptor> >& args) :
|
2005-08-04 22:42:30 +02:00
|
|
|
args_(args)
|
|
|
|
{
|
|
|
|
if(((minArgs != -1) && (static_cast<int>(args.size()) < minArgs)) ||
|
|
|
|
((maxArgs != -1) && (static_cast<int>(args.size()) > maxArgs)))
|
|
|
|
throw SyntaxException("wrong number of arguments to function");
|
|
|
|
} // XPathFunction
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~XPathFunction() { }
|
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const = 0;
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:00:35 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
size_t argCount() const { return args_.size(); }
|
|
|
|
|
2007-10-22 19:42:50 +02:00
|
|
|
XPathValue<string_type, string_adaptor> arg(size_t index,
|
2007-09-08 01:52:30 +02:00
|
|
|
const DOM::Node<string_type, string_adaptor>& context,
|
2007-07-19 19:01:31 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
|
|
|
{
|
2007-10-25 22:42:00 +02:00
|
|
|
return args_[index].evaluate(context, executionContext);
|
2009-07-13 09:24:52 +02:00
|
|
|
} // arg
|
2007-07-19 19:01:31 +02:00
|
|
|
|
2005-08-04 22:42:30 +02:00
|
|
|
bool argAsBool(size_t index,
|
2007-09-08 01:52:30 +02:00
|
|
|
const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:00:35 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return args_[index].evaluateAsBool(context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // argAsBool
|
|
|
|
|
|
|
|
double argAsNumber(size_t index,
|
2007-09-08 01:52:30 +02:00
|
|
|
const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:00:35 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return args_[index].evaluateAsNumber(context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // argAsNumber
|
|
|
|
|
2005-08-18 11:00:35 +02:00
|
|
|
string_type argAsString(size_t index,
|
2007-09-08 01:52:30 +02:00
|
|
|
const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:00:35 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return args_[index].evaluateAsString(context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // argAsString
|
|
|
|
|
2007-09-08 01:52:30 +02:00
|
|
|
NodeSet<string_type, string_adaptor> argAsNodeSet(size_t index,
|
|
|
|
const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:00:35 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return args_[index].evaluateAsNodeSet(context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // argAsNodeSet
|
|
|
|
|
|
|
|
private:
|
2007-10-25 22:42:00 +02:00
|
|
|
const std::vector<XPathExpression<string_type, string_adaptor> > args_;
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class XPathFunction
|
|
|
|
|
2005-08-22 17:04:27 +02:00
|
|
|
namespace impl
|
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class BooleanFunction : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
BooleanFunction(int minArgs, int maxArgs, const std::vector<XPathExpression<string_type, string_adaptor> >& args) :
|
|
|
|
XPathFunction(minArgs, maxArgs, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
virtual ValueType type() const { return BOOL; }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:33:19 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return new BoolValue<string_type, string_adaptor>(doEvaluate(context, executionContext));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
|
|
|
|
}; // class BooleanFunction
|
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class NumericFunction : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
NumericFunction(int minArgs, int maxArgs, const std::vector<XPathExpression<string_type, string_adaptor> >& args) :
|
|
|
|
XPathFunction(minArgs, maxArgs, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return NUMBER; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:33:19 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return new NumericValue<string_type, string_adaptor>(doEvaluate(context, executionContext));
|
|
|
|
} // evaluate
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
|
|
|
|
}; // class NumericFunction
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// node-set functions
|
|
|
|
// number last()
|
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class LastFn : public NumericFunction<string_type, string_adaptor>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LastFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 0, args) { }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
|
|
|
{
|
|
|
|
return executionContext.last();
|
|
|
|
} // evaluate
|
|
|
|
}; // class LastFn
|
|
|
|
|
|
|
|
// number position()
|
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class PositionFn : public NumericFunction<string_type, string_adaptor>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PositionFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 0, args) { }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
|
|
|
{
|
|
|
|
return executionContext.position();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class PositionFn
|
|
|
|
|
|
|
|
// number count(node-set)
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class CountFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
CountFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return baseT::argAsNodeSet(0, context, executionContext).size();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class CountFn
|
|
|
|
|
|
|
|
// node-set id(object)
|
|
|
|
// string local-name(node-set?)
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class LocalNameFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
LocalNameFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:33:19 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2007-09-08 01:52:30 +02:00
|
|
|
DOM::Node<string_type, string_adaptor> node;
|
2005-08-18 11:33:19 +02:00
|
|
|
if(baseT::argCount() == 0)
|
2005-08-04 22:42:30 +02:00
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2007-09-08 01:52:30 +02:00
|
|
|
NodeSet<string_type, string_adaptor> ns = baseT::argAsNodeSet(0, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
if(ns.size() != 0)
|
|
|
|
node = ns.top();
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
if(node != 0)
|
|
|
|
switch(node.getNodeType())
|
|
|
|
{
|
|
|
|
case DOM::Node_base::ATTRIBUTE_NODE:
|
|
|
|
case DOM::Node_base::ELEMENT_NODE:
|
|
|
|
case DOM::Node_base::PROCESSING_INSTRUCTION_NODE:
|
2007-11-10 23:23:36 +01:00
|
|
|
case NAMESPACE_NODE_TYPE:
|
2005-08-18 11:33:19 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(node.hasNamespaceURI() ? node.getLocalName() : node.getNodeName());
|
2005-08-05 22:56:15 +02:00
|
|
|
default: // put this in to keep gcc quiet
|
|
|
|
;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // switch ...
|
2005-08-18 11:33:19 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>("");
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class LocalNameFn
|
|
|
|
|
|
|
|
// string namespace-uri(node-set?)
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class NamespaceURIFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
NamespaceURIFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:33:19 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2007-09-08 01:52:30 +02:00
|
|
|
DOM::Node<string_type, string_adaptor> node;
|
2005-08-18 11:33:19 +02:00
|
|
|
if(baseT::argCount() == 0)
|
2005-08-04 22:42:30 +02:00
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2007-09-08 01:52:30 +02:00
|
|
|
NodeSet<string_type, string_adaptor> ns = baseT::argAsNodeSet(0, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
if(ns.size() != 0)
|
|
|
|
node = ns.top();
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
if(node != 0)
|
|
|
|
switch(node.getNodeType())
|
|
|
|
{
|
|
|
|
case DOM::Node_base::ATTRIBUTE_NODE:
|
|
|
|
case DOM::Node_base::ELEMENT_NODE:
|
2005-08-18 11:33:19 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(node.getNamespaceURI());
|
2005-08-05 22:56:15 +02:00
|
|
|
default: // put this in to keep gcc quiet
|
|
|
|
;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // switch ...
|
2005-08-18 11:33:19 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>("");
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class NamespaceURIFn
|
|
|
|
|
|
|
|
// string name(node-set?)
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class NameFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
NameFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 11:33:19 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2007-09-08 01:52:30 +02:00
|
|
|
DOM::Node<string_type, string_adaptor> node;
|
2005-08-18 11:33:19 +02:00
|
|
|
if(baseT::argCount() == 0)
|
2005-08-04 22:42:30 +02:00
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2007-09-08 01:52:30 +02:00
|
|
|
NodeSet<string_type, string_adaptor> ns = baseT::argAsNodeSet(0, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
if(ns.size() != 0)
|
|
|
|
node = ns.top();
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
if(node != 0)
|
|
|
|
switch(node.getNodeType())
|
|
|
|
{
|
|
|
|
case DOM::Node_base::ATTRIBUTE_NODE:
|
|
|
|
case DOM::Node_base::ELEMENT_NODE:
|
|
|
|
case DOM::Node_base::PROCESSING_INSTRUCTION_NODE:
|
2007-07-19 19:01:31 +02:00
|
|
|
case NAMESPACE_NODE_TYPE:
|
2005-08-18 11:33:19 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(node.getNodeName());
|
2005-08-05 22:56:15 +02:00
|
|
|
default: // stop gcc generating a warning about unhandled enum values
|
|
|
|
;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // switch ...
|
2005-08-18 11:33:19 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>("");
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class NameFn
|
|
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
// string functions
|
|
|
|
|
|
|
|
// string string(object?)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class StringFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
StringFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-23 21:19:17 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue<string_type, string_adaptor>(context));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class StringFn
|
|
|
|
|
|
|
|
// string concat(string, string, string*)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class ConcatFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
ConcatFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, -1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
string_type s;
|
|
|
|
for(size_t a = 0, ae = baseT::argCount(); a < ae; ++a)
|
2005-09-30 23:36:11 +02:00
|
|
|
string_adaptor::append(s, baseT::argAsString(a, context, executionContext));
|
2005-08-18 13:32:29 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(s);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // ConcatFn
|
|
|
|
|
|
|
|
// boolean starts-with(string, string)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class StartsWithFn : public BooleanFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef BooleanFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
StartsWithFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(2, 2, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
string_type value = baseT::argAsString(0, context, executionContext);
|
|
|
|
string_type start = baseT::argAsString(1, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-09-30 23:36:11 +02:00
|
|
|
if(string_adaptor::length(value) < string_adaptor::length(start))
|
2009-07-13 09:24:52 +02:00
|
|
|
return false;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-10-22 05:17:39 +02:00
|
|
|
typename string_adaptor::const_iterator i = string_adaptor::begin(value);
|
|
|
|
typename string_adaptor::const_iterator s = string_adaptor::begin(start);
|
|
|
|
typename string_adaptor::const_iterator e = string_adaptor::end(start);
|
2005-09-30 23:36:11 +02:00
|
|
|
for(; s != e; ++s, ++i)
|
|
|
|
if(*i != *s)
|
2009-07-13 09:24:52 +02:00
|
|
|
return false;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
return true;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // StartsWithFn
|
|
|
|
|
|
|
|
// boolean contains(string, string)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class ContainsFn : public BooleanFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef BooleanFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
ContainsFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(2, 2, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return string_adaptor::find(baseT::argAsString(0, context, executionContext),
|
|
|
|
baseT::argAsString(1, context, executionContext)) != string_adaptor::npos();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class ContainsFn
|
|
|
|
|
|
|
|
// string substring-before(string, string)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class SubstringBeforeFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
SubstringBeforeFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
string_type value = baseT::argAsString(0, context, executionContext);
|
2005-09-30 23:36:11 +02:00
|
|
|
size_t splitAt = string_adaptor::find(value, baseT::argAsString(1, context, executionContext));
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2006-06-08 11:51:18 +02:00
|
|
|
if(splitAt == string_adaptor::npos())
|
2005-08-18 13:32:29 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>("");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-09-30 23:36:11 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(string_adaptor::substr(value, 0, splitAt));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class SubstringBeforeFn
|
|
|
|
|
|
|
|
// string substring-after(string, string)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class SubstringAfterFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
SubstringAfterFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
string_type value = baseT::argAsString(0, context, executionContext);
|
|
|
|
string_type split = baseT::argAsString(1, context, executionContext);
|
2005-09-30 23:36:11 +02:00
|
|
|
size_t splitAt = string_adaptor::find(value, split);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2006-06-08 11:51:18 +02:00
|
|
|
if((splitAt == string_adaptor::npos()) || ((splitAt + string_adaptor::length(split)) >= string_adaptor::length(value)))
|
2005-08-18 13:32:29 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>("");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-09-30 23:36:11 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(string_adaptor::substr(value, splitAt + string_adaptor::length(split)));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class SubstringAfterFn
|
|
|
|
|
|
|
|
// string substring(string, number, number?)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class SubstringFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
SubstringFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 3, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
string_type value = baseT::argAsString(0, context, executionContext);
|
2007-07-19 19:01:31 +02:00
|
|
|
if(string_adaptor::empty(value))
|
|
|
|
return new StringValue<string_type, string_adaptor>(value);
|
|
|
|
|
2005-08-18 13:32:29 +02:00
|
|
|
double startAt = roundNumber(baseT::argAsNumber(1, context, executionContext)) - 1;
|
|
|
|
double endAt = roundNumber((baseT::argCount() == 3 ? baseT::argAsNumber(2, context, executionContext) : Infinity)) + startAt;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-07 22:11:43 +02:00
|
|
|
if((endAt < 0) || (endAt < startAt) || (isNaN(endAt)))
|
2005-08-18 13:32:29 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>("");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
if(startAt < 0)
|
|
|
|
startAt = 0;
|
2005-09-30 23:36:11 +02:00
|
|
|
if((isInfinite(endAt)) || (endAt > string_adaptor::length(value)))
|
|
|
|
endAt = string_adaptor::length(value);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-09-30 23:36:11 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(string_adaptor::substr(value, static_cast<int>(startAt), static_cast<int>(endAt - startAt)));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // SubstringFn
|
|
|
|
|
|
|
|
// number string-length(string?)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class StringLengthFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
StringLengthFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-09-30 23:36:11 +02:00
|
|
|
string_type v = (baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue<string_type, string_adaptor>(context);
|
2009-07-13 09:24:52 +02:00
|
|
|
return string_adaptor::length(v);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // StringLengthFn
|
|
|
|
|
|
|
|
// string normalize-space(string?)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class NormalizeSpaceFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
NormalizeSpaceFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2006-07-13 22:47:51 +02:00
|
|
|
string_type initial = ((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue<string_type, string_adaptor>(context));
|
2007-09-10 19:24:17 +02:00
|
|
|
string_type value = Arabica::text::normalize_whitespace<string_type, string_adaptor>(initial);
|
2007-07-19 19:01:31 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(value);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class NormalizeSpaceFn
|
|
|
|
|
|
|
|
// string translate(string, string, string)
|
2005-08-18 13:32:29 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class TranslateFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
typedef XPathFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2007-10-25 22:42:00 +02:00
|
|
|
TranslateFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(3, 3, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2007-12-19 00:03:16 +01:00
|
|
|
virtual ValueType type() const { return STRING; }
|
|
|
|
|
Some time ago, it was gently suggested to me that XPathValuePtr and XPathExpressionPtr both exposed an implementation detail, because they derive fromboost::shared_ptr, and provided an interface that was inconsisted with the DOM classes, because you accessed the member functions via -> rather than .
At the time, I was just pleased to have got the XPath stuff done and wasn't really fussed, so I left it. Since then though, it's niggled and niggled away at the back of my mind and now I've decided to do something about it.
XPathValuePtr will become XPathValue, with the member functions accessed through the . operator. The XPathValuePtr name and -> member access will be retained for the meantime, so that existing code won't be broken. XPathExpressionPtr will be similarly changed.
This commit is the first bit of that work, now I've satisfied myself it's going to be pretty easy so long as I pay proper attention.
2007-10-19 23:59:24 +02:00
|
|
|
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 13:32:29 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 13:32:29 +02:00
|
|
|
string_type str = baseT::argAsString(0, context, executionContext);
|
|
|
|
string_type from = baseT::argAsString(1, context, executionContext);
|
|
|
|
string_type to = baseT::argAsString(2, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-10-22 05:17:39 +02:00
|
|
|
typename string_adaptor::mutable_iterator p = string_adaptor::begin(str);
|
|
|
|
for(typename string_adaptor::mutable_iterator i = string_adaptor::begin(str), ie = string_adaptor::end(str); i != ie; ++i)
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-09-30 23:36:11 +02:00
|
|
|
size_t r = string_adaptor::find(from, *i);
|
2006-06-08 11:51:18 +02:00
|
|
|
if(r == string_adaptor::npos())
|
2005-08-04 22:42:30 +02:00
|
|
|
++p;
|
2005-09-30 23:36:11 +02:00
|
|
|
else if(r < string_adaptor::length(to))
|
|
|
|
*p++ = *(string_adaptor::begin(to) + r);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // for ...
|
2005-09-30 23:36:11 +02:00
|
|
|
if(p != string_adaptor::end(str))
|
|
|
|
*p = 0;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2006-07-13 23:03:00 +02:00
|
|
|
return new StringValue<string_type, string_adaptor>(string_adaptor::construct(string_adaptor::begin(str), p));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class TranslateFn
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// boolean functions
|
|
|
|
|
|
|
|
// boolean boolean(object)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class BooleanFn : public BooleanFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef BooleanFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
BooleanFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(1, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return baseT::argAsBool(0, context, executionContext);
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class BooleanFn
|
|
|
|
|
|
|
|
// boolean not(boolean)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class NotFn : public BooleanFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef BooleanFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
NotFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(1, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return !baseT::argAsBool(0, context, executionContext);
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class NotFn
|
|
|
|
|
|
|
|
// boolean true()
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class TrueFn : public BooleanFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
TrueFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
2005-08-18 15:18:33 +02:00
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return true;
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // TrueFn
|
|
|
|
|
|
|
|
// boolean false()
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class FalseFn : public BooleanFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
FalseFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(0, 0, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return false;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // FalseFn
|
|
|
|
|
|
|
|
// boolean lang(string)
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
// number functions
|
|
|
|
|
|
|
|
// number number(object?)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class NumberFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
NumberFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 15:18:33 +02:00
|
|
|
double result = (baseT::argCount() > 0) ? baseT::argAsNumber(0, context, executionContext) :
|
2005-08-23 21:19:17 +02:00
|
|
|
StringValue<string_type, string_adaptor>(nodeStringValue<string_type, string_adaptor>(context)).asNumber();
|
2009-07-13 09:24:52 +02:00
|
|
|
return result;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // NumberFn
|
|
|
|
|
|
|
|
// number sum(node-set)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class SumFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
SumFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
double sum = 0;
|
2007-09-08 01:52:30 +02:00
|
|
|
NodeSet<string_type, string_adaptor> ns = baseT::argAsNodeSet(0, context, executionContext);
|
|
|
|
for(typename NodeSet<string_type, string_adaptor>::const_iterator n = ns.begin(), end = ns.end(); n != end; ++n)
|
2005-08-23 21:19:17 +02:00
|
|
|
sum += nodeNumberValue<string_type, string_adaptor>(*n);
|
2009-07-13 09:24:52 +02:00
|
|
|
return sum;
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class SumFn
|
|
|
|
|
|
|
|
// number floor(number)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class FloorFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
FloorFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return std::floor(baseT::argAsNumber(0, context, executionContext));
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class FloorFn
|
|
|
|
|
|
|
|
// number ceiling(number)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class CeilingFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
CeilingFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return std::ceil(baseT::argAsNumber(0, context, executionContext));
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class CeilingFn
|
|
|
|
|
|
|
|
// number round(number)
|
2005-08-18 15:18:33 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2009-07-13 09:24:52 +02:00
|
|
|
class RoundFn : public NumericFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
typedef NumericFunction<string_type, string_adaptor> baseT;
|
2005-08-04 22:42:30 +02:00
|
|
|
public:
|
2009-07-13 09:24:52 +02:00
|
|
|
RoundFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
|
2007-12-19 00:03:16 +01:00
|
|
|
|
2009-07-13 09:24:52 +02:00
|
|
|
protected:
|
|
|
|
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2009-07-13 09:24:52 +02:00
|
|
|
return roundNumber(baseT::argAsNumber(0, context, executionContext));
|
|
|
|
} // doEvaluate
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class RoundFn
|
|
|
|
|
2005-08-22 17:04:27 +02:00
|
|
|
} // namespace impl
|
2005-08-04 22:42:30 +02:00
|
|
|
} // namespace XPath
|
|
|
|
} // namespace Arabica
|
|
|
|
|
|
|
|
#endif
|