2005-08-04 22:42:30 +02:00
|
|
|
#ifndef ARABICA_XPATHIC_XPATH_STEP_H
|
|
|
|
#define ARABICA_XPATHIC_XPATH_STEP_H
|
|
|
|
|
|
|
|
#include <DOM/Document.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "xpath_object.hpp"
|
|
|
|
#include "xpath_value.hpp"
|
|
|
|
#include "xpath_axis_enumerator.hpp"
|
|
|
|
#include "xpath_node_test.hpp"
|
|
|
|
#include "xpath_ast.hpp"
|
|
|
|
#include "xpath_ast_ids.hpp"
|
|
|
|
#include "xpath_namespace_context.hpp"
|
|
|
|
#include "xpath_compile_context.hpp"
|
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XPath
|
|
|
|
{
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
class StepExpression : public XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
StepExpression() { }
|
2005-08-17 12:13:05 +02:00
|
|
|
StepExpression(const std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> > *>& predicates) : predicates_(predicates) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
virtual ~StepExpression()
|
|
|
|
{
|
2005-08-17 12:13:05 +02:00
|
|
|
for(std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >*>::iterator p = predicates_.begin(), e = predicates_.end(); p != e; ++p)
|
2005-08-04 22:42:30 +02:00
|
|
|
delete *p;
|
|
|
|
} // ~StepExpression
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const = 0;
|
|
|
|
virtual XPathValuePtr<std::string> evaluate(NodeSet<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const = 0;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
bool has_predicates() const { return !predicates_.empty(); }
|
|
|
|
|
|
|
|
protected:
|
2005-08-17 12:13:05 +02:00
|
|
|
NodeSet<std::string> applyPredicates(NodeSet<std::string>& nodes, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& parentContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 12:13:05 +02:00
|
|
|
for(std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >*>::const_iterator p = predicates_.begin(), e = predicates_.end();
|
2005-08-04 22:42:30 +02:00
|
|
|
(p != e) && (!nodes.empty()); ++p)
|
|
|
|
nodes = applyPredicate(nodes, *p, parentContext);
|
|
|
|
return nodes;
|
|
|
|
} // applyPredicates
|
|
|
|
|
|
|
|
private:
|
2005-08-16 18:04:24 +02:00
|
|
|
NodeSet<std::string> applyPredicate(NodeSet<std::string>& nodes,
|
2005-08-17 12:13:05 +02:00
|
|
|
XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >* predicate,
|
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& parentContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-17 12:13:05 +02:00
|
|
|
ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> > executionContext(nodes.size(), parentContext);
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> results(nodes.forward());
|
2005-08-04 22:42:30 +02:00
|
|
|
unsigned int position = 1;
|
2005-08-16 16:17:22 +02:00
|
|
|
for(NodeSet<std::string>::iterator i = nodes.begin(); i != nodes.end(); ++i, ++position)
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
executionContext.setPosition(position);
|
2005-08-16 17:29:02 +02:00
|
|
|
XPathValuePtr<std::string> v = predicate->evaluate(*i, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
if((v->type() == NUMBER) && (position != v->asNumber()))
|
|
|
|
continue;
|
|
|
|
if(v->asBool() == false)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
results.push_back(*i);
|
|
|
|
} // for ...
|
|
|
|
return results;
|
|
|
|
} // applyPredicate
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >*> predicates_;
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // StepExpression
|
|
|
|
|
|
|
|
class TestStepExpression : public StepExpression
|
|
|
|
{
|
|
|
|
public:
|
2005-08-18 18:17:20 +02:00
|
|
|
TestStepExpression(Axis axis, NodeTest<std::string>* test) :
|
2005-08-04 22:42:30 +02:00
|
|
|
StepExpression(),
|
|
|
|
axis_(axis),
|
|
|
|
test_(test)
|
|
|
|
{
|
|
|
|
} // TestStepExpression
|
|
|
|
|
2005-08-18 18:17:20 +02:00
|
|
|
TestStepExpression(Axis axis, NodeTest<std::string>* test,
|
2005-08-17 12:13:05 +02:00
|
|
|
const std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >*>& predicates) :
|
2005-08-04 22:42:30 +02:00
|
|
|
StepExpression(predicates),
|
|
|
|
axis_(axis),
|
|
|
|
test_(test)
|
|
|
|
{
|
|
|
|
} // TestStepExpression
|
|
|
|
|
|
|
|
virtual ~TestStepExpression()
|
|
|
|
{
|
|
|
|
delete test_;
|
|
|
|
} // StepExpression
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> nodes;
|
2005-08-04 22:42:30 +02:00
|
|
|
enumerateOver(context, nodes, executionContext);
|
2005-08-17 10:31:47 +02:00
|
|
|
return XPathValuePtr<std::string>(new NodeSetValue<std::string, Arabica::default_string_adaptor<std::string> >(nodes));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(NodeSet<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> nodes;
|
|
|
|
for(NodeSet<std::string>::iterator n = context.begin(); n != context.end(); ++n)
|
2005-08-04 22:42:30 +02:00
|
|
|
enumerateOver(*n, nodes, executionContext);
|
2005-08-17 10:31:47 +02:00
|
|
|
return XPathValuePtr<std::string>(new NodeSetValue<std::string, Arabica::default_string_adaptor<std::string> >(nodes));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
|
|
|
|
private:
|
2005-08-16 16:17:22 +02:00
|
|
|
void enumerateOver(const DOM::Node<std::string>& context,
|
|
|
|
NodeSet<std::string>& results,
|
2005-08-17 12:13:05 +02:00
|
|
|
const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& parentContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
AxisEnumerator enumerator(context, axis_);
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> intermediate(enumerator.forward());
|
|
|
|
NodeSet<std::string>& d = (!has_predicates()) ? results : intermediate;
|
2005-08-04 22:42:30 +02:00
|
|
|
while(*enumerator != 0)
|
|
|
|
{
|
|
|
|
// if test
|
|
|
|
DOM::Node<std::string> node = *enumerator;
|
|
|
|
if((*test_)(node))
|
|
|
|
d.push_back(node);
|
|
|
|
++enumerator;
|
|
|
|
} // while ...
|
|
|
|
|
|
|
|
if(!has_predicates())
|
|
|
|
{
|
|
|
|
results.forward(enumerator.forward());
|
|
|
|
return;
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
intermediate = applyPredicates(intermediate, parentContext);
|
|
|
|
|
|
|
|
results.swap(intermediate);
|
|
|
|
} // enumerateOver
|
|
|
|
|
|
|
|
Axis axis_;
|
2005-08-18 18:17:20 +02:00
|
|
|
NodeTest<std::string>* test_;
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class TestStepExpression
|
|
|
|
|
|
|
|
class ExprStepExpression : public StepExpression
|
|
|
|
{
|
|
|
|
public:
|
2005-08-17 12:13:05 +02:00
|
|
|
ExprStepExpression(XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >* expr,
|
|
|
|
const std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >*>& predicates) :
|
2005-08-04 22:42:30 +02:00
|
|
|
StepExpression(predicates),
|
|
|
|
expr_(expr)
|
|
|
|
{
|
|
|
|
} // ExprStepExpression
|
|
|
|
|
|
|
|
virtual ~ExprStepExpression()
|
|
|
|
{
|
|
|
|
delete expr_;
|
|
|
|
} // ExprStepExpression
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
if(!has_predicates())
|
|
|
|
return expr_->evaluate(context, executionContext);
|
|
|
|
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> ns = expr_->evaluate(context, executionContext)->asNodeSet();
|
2005-08-17 10:31:47 +02:00
|
|
|
return XPathValuePtr<std::string>(new NodeSetValue<std::string, Arabica::default_string_adaptor<std::string> >(applyPredicates(ns, executionContext)));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // evaluate
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(NodeSet<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
DOM::Node<std::string> c = context.top();
|
|
|
|
return evaluate(c, executionContext);
|
|
|
|
} // evaluate
|
|
|
|
|
|
|
|
private:
|
2005-08-17 12:13:05 +02:00
|
|
|
XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >* expr_;
|
2005-08-04 22:42:30 +02:00
|
|
|
std::vector<XPathExpression*> predicates_;
|
|
|
|
}; // class ExprStepExpression
|
|
|
|
|
|
|
|
class StepFactory
|
|
|
|
{
|
|
|
|
public:
|
2005-08-17 10:50:41 +02:00
|
|
|
static StepExpression* createStep(node_iter_t& node,
|
|
|
|
node_iter_t const& end,
|
|
|
|
CompilationContext<std::string, Arabica::default_string_adaptor<std::string> >& context)
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
Axis axis = getAxis(node);
|
2005-08-18 18:17:20 +02:00
|
|
|
NodeTest<std::string>* test = getTest(node, context.namespaceContext());
|
2005-08-17 12:13:05 +02:00
|
|
|
XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >* thing = 0;
|
2005-08-04 22:42:30 +02:00
|
|
|
if(!test)
|
2005-08-16 22:59:04 +02:00
|
|
|
thing = XPath<std::string>::compile_expression(node++, context);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
std::vector<XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >*> preds;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
while((node != end) && (getNodeId(node) == impl::Predicate_id))
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
node_iter_t c = node->children.begin();
|
2005-08-16 19:54:20 +02:00
|
|
|
assert(getNodeId(c) == impl::LeftSquare_id);
|
2005-08-04 22:42:30 +02:00
|
|
|
++c;
|
2005-08-16 22:59:04 +02:00
|
|
|
preds.push_back(XPath<std::string>::compile_expression(c, context));
|
2005-08-04 22:42:30 +02:00
|
|
|
++c;
|
2005-08-16 19:54:20 +02:00
|
|
|
assert(getNodeId(c) == impl::RightSquare_id);
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
++node;
|
|
|
|
} // if ...
|
|
|
|
if(!test)
|
|
|
|
return new ExprStepExpression(thing, preds);
|
|
|
|
return new TestStepExpression(axis, test, preds);
|
|
|
|
} // createStep
|
|
|
|
|
2005-08-17 10:50:41 +02:00
|
|
|
static StepExpression* createStep(node_iter_t& node, CompilationContext<std::string, Arabica::default_string_adaptor<std::string> >& context)
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
Axis axis = getAxis(node);
|
2005-08-18 18:17:20 +02:00
|
|
|
NodeTest<std::string>* test = getTest(node, context.namespaceContext());
|
2005-08-04 22:42:30 +02:00
|
|
|
return new TestStepExpression(axis, test);
|
|
|
|
} // createStep
|
|
|
|
|
|
|
|
private:
|
|
|
|
static Axis getAxis(node_iter_t& node)
|
|
|
|
{
|
|
|
|
long id = getNodeId(node);
|
|
|
|
|
|
|
|
switch(id)
|
|
|
|
{
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Slash_id:
|
|
|
|
case impl::SelfSelect_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return SELF; // don't advance node, SelfSelect is axis specifier and node test in one
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::ParentSelect_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return PARENT;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::SlashSlash_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return DESCENDANT_OR_SELF;
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::AbbreviatedAxisSpecifier_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
++node;
|
|
|
|
return ATTRIBUTE;
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::AxisSpecifier_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
// skip on to the next bit
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return CHILD;
|
|
|
|
} // switch(id)
|
|
|
|
|
|
|
|
node_iter_t axis_node = node->children.begin();
|
|
|
|
long axis = getNodeId(skipWhitespace(axis_node));
|
|
|
|
++node;
|
|
|
|
switch(axis)
|
|
|
|
{
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::AncestorOrSelf_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return ANCESTOR_OR_SELF;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Ancestor_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return ANCESTOR;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::AbbreviatedAxisSpecifier_id:
|
|
|
|
case impl::Attribute_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return ATTRIBUTE;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Child_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return CHILD;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::DescendantOrSelf_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return DESCENDANT_OR_SELF;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Descendant_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return DESCENDANT;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::FollowingSibling_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return FOLLOWING_SIBLING;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Following_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return FOLLOWING;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Namespace_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return NAMESPACE;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Parent_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return PARENT;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::PrecedingSibling_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return PRECEDING_SIBLING;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Preceding_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return PRECEDING;
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Self_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
return SELF;
|
|
|
|
} // switch ...
|
|
|
|
|
|
|
|
assert(false);
|
|
|
|
return CHILD;
|
|
|
|
} // getAxis
|
|
|
|
|
2005-08-18 18:17:20 +02:00
|
|
|
static NodeTest<std::string>* getTest(node_iter_t& node, const NamespaceContext<std::string, Arabica::default_string_adaptor<std::string> >& namespaceContext)
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
long id = getNodeId(skipWhitespace(node));
|
|
|
|
|
|
|
|
switch(id)
|
|
|
|
{
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::NodeTest_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
node_iter_t c = node->children.begin();
|
2005-08-18 18:17:20 +02:00
|
|
|
NodeTest<std::string>* t = getTest(c, namespaceContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
++node;
|
|
|
|
return t;
|
|
|
|
} // case NodeTest_id
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::QName_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
node_iter_t c = node->children.begin();
|
|
|
|
std::string prefix(c->value.begin(), c->value.end());
|
|
|
|
std::string uri = namespaceContext.namespaceURI(prefix);
|
|
|
|
++c;
|
|
|
|
std::string name(c->value.begin(), c->value.end());
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new QNameNodeTest<std::string>(uri, name);
|
2005-08-04 22:42:30 +02:00
|
|
|
} //case QName_id
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::NCName_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string name(node->value.begin(), node->value.end());
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new NameNodeTest<std::string>(name);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case NameNodeTest
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Comment_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new CommentNodeTest<std::string>();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case CommentTest_id
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Text_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new TextNodeTest<std::string>();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case Text_id
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::ProcessingInstruction_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
++node;
|
2005-08-16 19:54:20 +02:00
|
|
|
if(getNodeId(node) != impl::Literal_id) // not sure if this is always safe
|
2005-08-18 18:17:20 +02:00
|
|
|
return new ProcessingInstructionNodeTest<std::string>();
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
std::string target(node->value.begin(), node->value.end());
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new ProcessingInstructionNodeTest<std::string>(target);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case ProcessingInstruction_id
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::SlashSlash_id:
|
|
|
|
case impl::Node_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new AnyNodeTest<std::string>();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case Node_id
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::Slash_id:
|
2005-08-18 18:17:20 +02:00
|
|
|
return new RootNodeTest<std::string>();
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::AnyName_id:
|
|
|
|
case impl::SelfSelect_id:
|
|
|
|
case impl::ParentSelect_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
++node;
|
2005-08-18 18:17:20 +02:00
|
|
|
return new StarNodeTest<std::string>();
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case AnyName_id:
|
|
|
|
|
2005-08-16 19:54:20 +02:00
|
|
|
case impl::NameTest_id:
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
node_iter_t prefixNode = node->children.begin();
|
|
|
|
++node;
|
|
|
|
std::string prefix(prefixNode->value.begin(), prefixNode->value.end());
|
|
|
|
std::string uri = namespaceContext.namespaceURI(prefix);
|
2005-08-18 18:17:20 +02:00
|
|
|
return new QStarNodeTest<std::string>(uri);
|
2005-08-04 22:42:30 +02:00
|
|
|
} // case
|
|
|
|
} // switch(id)
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
} // getTest
|
|
|
|
|
|
|
|
StepFactory();
|
|
|
|
}; // class StepFactory
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
class RelativeLocationPath : public XPathExpression<std::string, Arabica::default_string_adaptor<std::string> >
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
RelativeLocationPath(StepExpression* step) : steps_() { steps_.push_back(step); }
|
|
|
|
RelativeLocationPath(const StepList& steps) : steps_(steps) { }
|
|
|
|
|
|
|
|
virtual ~RelativeLocationPath()
|
|
|
|
{
|
|
|
|
for(StepList::const_iterator i = steps_.begin(); i != steps_.end(); ++i)
|
|
|
|
delete *i;
|
|
|
|
} // ~LocationPath
|
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> nodes;
|
2005-08-04 22:42:30 +02:00
|
|
|
nodes.push_back(context);
|
|
|
|
|
|
|
|
for(StepList::const_iterator i = steps_.begin(); i != steps_.end(); ++i)
|
|
|
|
{
|
2005-08-16 17:29:02 +02:00
|
|
|
XPathValuePtr<std::string> v = (*i)->evaluate(nodes, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
nodes = v->asNodeSet();
|
|
|
|
} // for ...
|
|
|
|
|
2005-08-17 10:31:47 +02:00
|
|
|
return XPathValuePtr<std::string>(new NodeSetValue<std::string, Arabica::default_string_adaptor<std::string> >(nodes));
|
2005-08-04 22:42:30 +02:00
|
|
|
} // do_evaluate
|
|
|
|
|
|
|
|
private:
|
|
|
|
StepList steps_;
|
|
|
|
}; // LocationPath
|
|
|
|
|
|
|
|
class AbsoluteLocationPath : public RelativeLocationPath
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AbsoluteLocationPath(StepExpression* step) : RelativeLocationPath(step) { }
|
2005-08-16 22:59:04 +02:00
|
|
|
AbsoluteLocationPath(const StepList& steps) : RelativeLocationPath(steps) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-17 12:13:05 +02:00
|
|
|
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext<std::string, Arabica::default_string_adaptor<std::string> >& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
int type = context.getNodeType();
|
|
|
|
if((type == DOM::Node<std::string>::DOCUMENT_NODE) ||
|
|
|
|
(type == DOM::Node<std::string>::DOCUMENT_FRAGMENT_NODE))
|
|
|
|
return RelativeLocationPath::evaluate(context, executionContext);
|
|
|
|
|
|
|
|
DOM::Document<std::string> document = context.getOwnerDocument();
|
|
|
|
return RelativeLocationPath::evaluate(document, executionContext);
|
|
|
|
} // evaluate
|
|
|
|
}; // class AbsoluteLocationPath
|
|
|
|
|
|
|
|
|
|
|
|
} // XPath
|
|
|
|
} // Arabica
|
|
|
|
#endif
|