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>
|
|
|
|
#include <XML/XMLCharacterClasses.h>
|
|
|
|
#include <XML/UnicodeCharacters.h>
|
|
|
|
#include "xpath_value.hpp"
|
|
|
|
#include "xpath_execution_context.hpp"
|
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XPath
|
|
|
|
{
|
|
|
|
|
2005-08-18 11:00:35 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
class XPathFunction
|
|
|
|
{
|
|
|
|
protected:
|
2005-08-18 11:00:35 +02:00
|
|
|
XPathFunction(int minArgs, int maxArgs, const std::vector<XPathExpressionPtr<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() { }
|
|
|
|
|
2005-08-18 11:00:35 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
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(); }
|
|
|
|
|
|
|
|
bool argAsBool(size_t index,
|
2005-08-18 11:00:35 +02:00
|
|
|
const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asBool();
|
|
|
|
} // argAsBool
|
|
|
|
|
|
|
|
double argAsNumber(size_t index,
|
2005-08-18 11:00:35 +02:00
|
|
|
const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asNumber();
|
|
|
|
} // argAsNumber
|
|
|
|
|
2005-08-18 11:00:35 +02:00
|
|
|
string_type argAsString(size_t index,
|
|
|
|
const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asString();
|
|
|
|
} // argAsString
|
|
|
|
|
2005-08-18 11:00:35 +02:00
|
|
|
NodeSet<string_type> argAsNodeSet(size_t index,
|
|
|
|
const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asNodeSet();
|
|
|
|
} // argAsNodeSet
|
|
|
|
|
|
|
|
private:
|
2005-08-18 11:00:35 +02:00
|
|
|
const std::vector<XPathExpressionPtr<string_type, string_adaptor> > args_;
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class XPathFunction
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// node-set functions
|
|
|
|
// number last()
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class LastFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:33:19 +02:00
|
|
|
LastFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
return new NumericValue<string_type, string_adaptor>(executionContext.last());
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class LastFn
|
|
|
|
|
|
|
|
// number position()
|
2005-08-18 11:33:19 +02:00
|
|
|
template<class string_type, class string_adaptor>
|
|
|
|
class PositionFn : public XPathFunction<string_type, string_adaptor>
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:33:19 +02:00
|
|
|
PositionFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
return new NumericValue<string_type, string_adaptor>(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>
|
|
|
|
class CountFn : 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:
|
2005-08-18 11:33:19 +02:00
|
|
|
CountFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
return new NumericValue<string_type, string_adaptor>(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:
|
2005-08-18 11:33:19 +02:00
|
|
|
LocalNameFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
DOM::Node<string_type> node;
|
|
|
|
if(baseT::argCount() == 0)
|
2005-08-04 22:42:30 +02:00
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
NodeSet<string_type> 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:
|
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:
|
2005-08-18 11:33:19 +02:00
|
|
|
NamespaceURIFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
DOM::Node<string_type> node;
|
|
|
|
if(baseT::argCount() == 0)
|
2005-08-04 22:42:30 +02:00
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
NodeSet<string_type> 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:
|
2005-08-18 11:33:19 +02:00
|
|
|
NameFn(const std::vector<XPathExpressionPtr<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-18 11:33:19 +02:00
|
|
|
virtual XPathValue<string_type>* evaluate(const DOM::Node<string_type>& context,
|
|
|
|
const ExecutionContext<string_type, string_adaptor>& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
DOM::Node<string_type> node;
|
|
|
|
if(baseT::argCount() == 0)
|
2005-08-04 22:42:30 +02:00
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2005-08-18 11:33:19 +02:00
|
|
|
NodeSet<string_type> 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:
|
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 11:00:35 +02:00
|
|
|
class StringFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
StringFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class StringFn
|
|
|
|
|
|
|
|
// string concat(string, string, string*)
|
2005-08-18 11:00:35 +02:00
|
|
|
class ConcatFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
ConcatFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, -1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
for(size_t a = 0, ae = argCount(); a < ae; ++a)
|
|
|
|
s.append(argAsString(a, context, executionContext));
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(s);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // ConcatFn
|
|
|
|
|
|
|
|
// boolean starts-with(string, string)
|
2005-08-18 11:00:35 +02:00
|
|
|
class StartsWithFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
StartsWithFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
std::string start = argAsString(1, context, executionContext);
|
|
|
|
|
|
|
|
if(value.length() < start.length())
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(false);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
for(size_t i = 0, ie = start.length(); i < ie; ++i)
|
|
|
|
if(value[i] != start[i])
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(false);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(true);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // StartsWithFn
|
|
|
|
|
|
|
|
// boolean contains(string, string)
|
2005-08-18 11:00:35 +02:00
|
|
|
class ContainsFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
ContainsFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(argAsString(0, context, executionContext).find(argAsString(1, context, executionContext)) != std::string::npos);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class ContainsFn
|
|
|
|
|
|
|
|
// string substring-before(string, string)
|
2005-08-18 11:00:35 +02:00
|
|
|
class SubstringBeforeFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
SubstringBeforeFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
size_t splitAt = value.find(argAsString(1, context, executionContext));
|
|
|
|
|
|
|
|
if(splitAt == std::string::npos)
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >("");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value.substr(0, splitAt));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class SubstringBeforeFn
|
|
|
|
|
|
|
|
// string substring-after(string, string)
|
2005-08-18 11:00:35 +02:00
|
|
|
class SubstringAfterFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
SubstringAfterFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
std::string split = argAsString(1, context, executionContext);
|
|
|
|
size_t splitAt = value.find(split);
|
|
|
|
|
|
|
|
if((splitAt == std::string::npos) || ((splitAt + split.length()) >= value.length()))
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >("");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value.substr(splitAt + split.length()));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class SubstringAfterFn
|
|
|
|
|
|
|
|
// string substring(string, number, number?)
|
2005-08-18 11:00:35 +02:00
|
|
|
class SubstringFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
SubstringFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(2, 3, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
double startAt = roundNumber(argAsNumber(1, context, executionContext)) - 1;
|
|
|
|
double endAt = roundNumber((argCount() == 3 ? argAsNumber(2, context, executionContext) : Infinity)) + startAt;
|
|
|
|
|
2005-08-07 22:11:43 +02:00
|
|
|
if((endAt < 0) || (endAt < startAt) || (isNaN(endAt)))
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >("");
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
if(startAt < 0)
|
|
|
|
startAt = 0;
|
|
|
|
if((isInfinite(endAt)) || (endAt > value.length()))
|
|
|
|
endAt = value.length();
|
|
|
|
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value.substr(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 11:00:35 +02:00
|
|
|
class StringLengthFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
StringLengthFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 09:01:27 +02:00
|
|
|
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context)).length());
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // StringLengthFn
|
|
|
|
|
|
|
|
// string normalize-space(string?)
|
2005-08-18 11:00:35 +02:00
|
|
|
class NormalizeSpaceFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
NormalizeSpaceFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = ((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context));
|
|
|
|
size_t i = 0, ie = value.length();
|
|
|
|
|
|
|
|
// string leading space
|
|
|
|
while((i != ie) && (XML::is_space(static_cast<wchar_t>(value[i]))))
|
|
|
|
++i;
|
|
|
|
|
|
|
|
size_t p = 0;
|
|
|
|
while(i != ie)
|
|
|
|
{
|
|
|
|
while((i != ie) && (!XML::is_space(static_cast<wchar_t>(value[i]))))
|
|
|
|
value[p++] = value[i++];
|
|
|
|
while((i != ie) && (XML::is_space(static_cast<wchar_t>(value[i]))))
|
|
|
|
++i;
|
|
|
|
if(i != ie)
|
|
|
|
value[p++] = Unicode<char>::SPACE;
|
|
|
|
} // while ...
|
|
|
|
if(p != ie)
|
|
|
|
value.resize(p);
|
|
|
|
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(value);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class NormalizeSpaceFn
|
|
|
|
|
|
|
|
// string translate(string, string, string)
|
2005-08-18 11:00:35 +02:00
|
|
|
class TranslateFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
TranslateFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(3, 3, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string str = argAsString(0, context, executionContext);
|
|
|
|
std::string from = argAsString(1, context, executionContext);
|
|
|
|
std::string to = argAsString(2, context, executionContext);
|
|
|
|
|
|
|
|
size_t p = 0;
|
|
|
|
for(size_t i = 0, ie = str.length(); i != ie; ++i)
|
|
|
|
{
|
|
|
|
size_t r = from.find(str[i]);
|
|
|
|
if(r == std::string::npos)
|
|
|
|
++p;
|
|
|
|
else if(r < to.length())
|
|
|
|
str[p++] = to[r];
|
|
|
|
} // for ...
|
|
|
|
if(p != str.length())
|
|
|
|
str.resize(p);
|
|
|
|
|
2005-08-17 10:25:24 +02:00
|
|
|
return new StringValue<std::string, Arabica::default_string_adaptor<std::string> >(str);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class TranslateFn
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// boolean functions
|
|
|
|
|
|
|
|
// boolean boolean(object)
|
2005-08-18 11:00:35 +02:00
|
|
|
class BooleanFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
BooleanFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(argAsBool(0, context, executionContext));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class BooleanFn
|
|
|
|
|
|
|
|
// boolean not(boolean)
|
2005-08-18 11:00:35 +02:00
|
|
|
class NotFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
NotFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(!argAsBool(0, context, executionContext));
|
2005-08-04 22:42:30 +02:00
|
|
|
}
|
|
|
|
}; // class NotFn
|
|
|
|
|
|
|
|
// boolean true()
|
2005-08-18 11:00:35 +02:00
|
|
|
class TrueFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
TrueFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(true);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // TrueFn
|
|
|
|
|
|
|
|
// boolean false()
|
2005-08-18 11:00:35 +02:00
|
|
|
class FalseFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
FalseFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 00:11:27 +02:00
|
|
|
return new BoolValue<std::string, Arabica::default_string_adaptor<std::string> >(false);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // FalseFn
|
|
|
|
|
|
|
|
// boolean lang(string)
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
// number functions
|
|
|
|
|
|
|
|
// number number(object?)
|
2005-08-18 11:00:35 +02:00
|
|
|
class NumberFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
NumberFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
double result = (argCount() > 0) ? argAsNumber(0, context, executionContext) :
|
2005-08-17 10:25:24 +02:00
|
|
|
StringValue<std::string, Arabica::default_string_adaptor<std::string> >(nodeStringValue(context)).asNumber();
|
2005-08-17 09:01:27 +02:00
|
|
|
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(result);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // NumberFn
|
|
|
|
|
|
|
|
// number sum(node-set)
|
2005-08-18 11:00:35 +02:00
|
|
|
class SumFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
SumFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
double sum = 0;
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> ns = argAsNodeSet(0, context, executionContext);
|
|
|
|
for(NodeSet<std::string>::const_iterator n = ns.begin(), end = ns.end(); n != end; ++n)
|
2005-08-04 22:42:30 +02:00
|
|
|
sum += nodeNumberValue(*n);
|
2005-08-17 09:01:27 +02:00
|
|
|
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(sum);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class SumFn
|
|
|
|
|
|
|
|
// number floor(number)
|
2005-08-18 11:00:35 +02:00
|
|
|
class FloorFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
FloorFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 09:01:27 +02:00
|
|
|
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(std::floor(argAsNumber(0, context, executionContext)));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class FloorFn
|
|
|
|
|
|
|
|
// number ceiling(number)
|
2005-08-18 11:00:35 +02:00
|
|
|
class CeilingFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
CeilingFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 09:01:27 +02:00
|
|
|
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(std::ceil(argAsNumber(0, context, executionContext)));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class CeilingFn
|
|
|
|
|
|
|
|
// number round(number)
|
2005-08-18 11:00:35 +02:00
|
|
|
class RoundFn : public XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-08-18 11:00:35 +02:00
|
|
|
RoundFn(const std::vector<XPathExpressionPtr<std::string, Arabica::default_string_adaptor<std::string> > >& args) : XPathFunction<std::string, Arabica::default_string_adaptor<std::string> >(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 09:01:27 +02:00
|
|
|
return new NumericValue<std::string, Arabica::default_string_adaptor<std::string> >(roundNumber(argAsNumber(0, context, executionContext)));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
}; // class RoundFn
|
|
|
|
|
|
|
|
} // namespace XPath
|
|
|
|
} // namespace Arabica
|
|
|
|
|
|
|
|
#endif
|