arabica/include/XPath/impl/xpath_step.hpp

533 lines
21 KiB
C++
Raw Normal View History

2005-08-04 22:42:30 +02:00
#ifndef ARABICA_XPATHIC_XPATH_STEP_H
#define ARABICA_XPATHIC_XPATH_STEP_H
2007-09-05 00:55:47 +02:00
#include <DOM/Document.hpp>
2005-08-04 22:42:30 +02:00
#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
{
2007-12-21 00:24:16 +01:00
template<class string_type, class string_adaptor>
class MatchExpr;
namespace impl
{
template<class string_type, class string_adaptor>
class StepExpression : public XPathExpression_impl<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
StepExpression() { }
StepExpression(XPathExpression_impl<string_type, string_adaptor>* pred) { predicates_.push_back(pred); }
StepExpression(const std::vector<XPathExpression_impl<string_type, string_adaptor> *>& predicates) : predicates_(predicates) { }
2005-08-04 22:42:30 +02:00
virtual ~StepExpression()
{
for(typename std::vector<XPathExpression_impl<string_type, string_adaptor>*>::iterator p = predicates_.begin(), e = predicates_.end(); p != e; ++p)
2005-08-04 22:42:30 +02:00
delete *p;
} // ~StepExpression
virtual ValueType type() const { return NODE_SET; }
virtual XPathValue<string_type, string_adaptor> evaluate(const DOM::Node<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
virtual XPathValue<string_type, string_adaptor> evaluate(NodeSet<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
2005-08-04 22:42:30 +02:00
bool has_predicates() const { return !predicates_.empty(); }
protected:
NodeSet<string_type, string_adaptor> applyPredicates(NodeSet<string_type, string_adaptor>& nodes, const ExecutionContext<string_type, string_adaptor>& parentContext) const
2005-08-04 22:42:30 +02:00
{
for(typename std::vector<XPathExpression_impl<string_type, string_adaptor>*>::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:
NodeSet<string_type, string_adaptor> applyPredicate(NodeSet<string_type, string_adaptor>& nodes,
XPathExpression_impl<string_type, string_adaptor>* predicate,
const ExecutionContext<string_type, string_adaptor>& parentContext) const
2005-08-04 22:42:30 +02:00
{
ExecutionContext<string_type, string_adaptor> executionContext(nodes.size(), parentContext);
NodeSet<string_type, string_adaptor> results(nodes.forward());
2005-08-04 22:42:30 +02:00
unsigned int position = 1;
for(typename NodeSet<string_type, string_adaptor>::iterator i = nodes.begin(); i != nodes.end(); ++i, ++position)
2005-08-04 22:42:30 +02:00
{
executionContext.setPosition(position);
XPathValue<string_type, string_adaptor> v = predicate->evaluate(*i, executionContext);
2005-08-04 22:42:30 +02:00
if((v.type() == NUMBER) && (position != v.asNumber()))
2005-08-04 22:42:30 +02:00
continue;
if(v.asBool() == false)
2005-08-04 22:42:30 +02:00
continue;
results.push_back(*i);
} // for ...
return results;
} // applyPredicate
std::vector<XPathExpression_impl<string_type, string_adaptor>*> predicates_;
friend class MatchExpr<string_type, string_adaptor>;
2005-08-04 22:42:30 +02:00
}; // StepExpression
2005-08-18 22:54:26 +02:00
template<class string_type, class string_adaptor>
class TestStepExpression : public StepExpression<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 22:54:26 +02:00
typedef StepExpression<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
TestStepExpression(Axis axis, NodeTest<string_type, string_adaptor>* test) :
2005-08-18 22:54:26 +02:00
StepExpression<string_type, string_adaptor>(),
2005-08-04 22:42:30 +02:00
axis_(axis),
test_(test)
{
} // TestStepExpression
TestStepExpression(Axis axis, NodeTest<string_type, string_adaptor>* test,
XPathExpression_impl<string_type, string_adaptor>* pred) :
StepExpression<string_type, string_adaptor>(pred),
axis_(axis),
test_(test)
{
} // TestStepExpression
TestStepExpression(Axis axis, NodeTest<string_type, string_adaptor>* test,
const std::vector<XPathExpression_impl<string_type, string_adaptor>*>& predicates) :
2005-08-18 22:54:26 +02:00
StepExpression<string_type, string_adaptor>(predicates),
2005-08-04 22:42:30 +02:00
axis_(axis),
test_(test)
{
} // TestStepExpression
virtual ~TestStepExpression()
{
delete test_;
} // StepExpression
virtual XPathValue<string_type, string_adaptor> evaluate(const DOM::Node<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
NodeSet<string_type, string_adaptor> nodes;
2005-08-04 22:42:30 +02:00
enumerateOver(context, nodes, executionContext);
return XPathValue<string_type, string_adaptor>(new NodeSetValue<string_type, string_adaptor>(nodes));
2005-08-04 22:42:30 +02:00
} // evaluate
virtual XPathValue<string_type, string_adaptor> evaluate(NodeSet<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
NodeSet<string_type, string_adaptor> nodes;
for(typename NodeSet<string_type, string_adaptor>::iterator n = context.begin(); n != context.end(); ++n)
2005-08-04 22:42:30 +02:00
enumerateOver(*n, nodes, executionContext);
return XPathValue<string_type, string_adaptor>(new NodeSetValue<string_type, string_adaptor>(nodes));
2005-08-04 22:42:30 +02:00
} // evaluate
private:
void enumerateOver(const DOM::Node<string_type, string_adaptor>& context,
NodeSet<string_type, string_adaptor>& results,
2005-08-18 22:54:26 +02:00
const ExecutionContext<string_type, string_adaptor>& parentContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-19 11:05:11 +02:00
AxisEnumerator<string_type, string_adaptor> enumerator(context, axis_);
results.forward(enumerator.forward());
NodeSet<string_type, string_adaptor> intermediate(enumerator.forward());
NodeSet<string_type, string_adaptor>& d = (!baseT::has_predicates()) ? results : intermediate;
2005-08-04 22:42:30 +02:00
while(*enumerator != 0)
{
// if test
DOM::Node<string_type, string_adaptor> node = *enumerator;
2005-08-04 22:42:30 +02:00
if((*test_)(node))
d.push_back(node);
++enumerator;
} // while ...
2005-08-18 22:54:26 +02:00
if(!baseT::has_predicates())
2005-08-04 22:42:30 +02:00
return;
2005-08-18 22:54:26 +02:00
intermediate = baseT::applyPredicates(intermediate, parentContext);
2005-08-04 22:42:30 +02:00
results.insert(results.end(), intermediate.begin(), intermediate.end());
2005-08-04 22:42:30 +02:00
} // enumerateOver
Axis axis_;
NodeTest<string_type, string_adaptor>* test_;
friend class MatchExpr<string_type, string_adaptor>;
2005-08-04 22:42:30 +02:00
}; // class TestStepExpression
2005-08-18 23:41:33 +02:00
template<class string_type, class string_adaptor>
class ExprStepExpression : public StepExpression<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 23:41:33 +02:00
typedef StepExpression<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
ExprStepExpression(XPathExpression_impl<string_type, string_adaptor>* expr,
const std::vector<XPathExpression_impl<string_type, string_adaptor>*>& predicates) :
2005-08-18 23:41:33 +02:00
StepExpression<string_type, string_adaptor>(predicates),
2005-08-04 22:42:30 +02:00
expr_(expr)
{
} // ExprStepExpression
virtual ~ExprStepExpression()
{
delete expr_;
} // ExprStepExpression
virtual XPathValue<string_type, string_adaptor> evaluate(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 23:41:33 +02:00
if(!baseT::has_predicates())
2005-08-04 22:42:30 +02:00
return expr_->evaluate(context, executionContext);
NodeSet<string_type, string_adaptor> ns = expr_->evaluate(context, executionContext).asNodeSet();
2007-07-19 19:01:31 +02:00
ns.to_document_order();
return XPathValue<string_type, string_adaptor>(new NodeSetValue<string_type, string_adaptor>(baseT::applyPredicates(ns, executionContext)));
2005-08-04 22:42:30 +02:00
} // evaluate
virtual XPathValue<string_type, string_adaptor> evaluate(NodeSet<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
DOM::Node<string_type, string_adaptor> c = context.top();
2005-08-04 22:42:30 +02:00
return evaluate(c, executionContext);
} // evaluate
private:
XPathExpression_impl<string_type, string_adaptor>* expr_;
std::vector<XPathExpression_impl<string_type, string_adaptor>*> predicates_;
2005-08-04 22:42:30 +02:00
}; // class ExprStepExpression
2005-08-18 23:45:14 +02:00
template<class string_type, class string_adaptor>
2005-08-04 22:42:30 +02:00
class StepFactory
{
public:
2005-08-18 23:45:14 +02:00
static StepExpression<string_type, string_adaptor>*
2005-09-25 22:09:49 +02:00
createStep(typename types<string_adaptor>::node_iter_t& node,
typename types<string_adaptor>::node_iter_t const& end,
2005-08-18 23:45:14 +02:00
CompilationContext<string_type, string_adaptor>& context)
2005-08-04 22:42:30 +02:00
{
Axis axis = getAxis(node);
2005-12-18 23:22:13 +01:00
return createStep(node, end, context, axis);
} // createStep
static StepExpression<string_type, string_adaptor>*
createStep(typename types<string_adaptor>::node_iter_t& node,
typename types<string_adaptor>::node_iter_t const& end,
CompilationContext<string_type, string_adaptor>& context,
2007-07-19 19:01:31 +02:00
Axis axis,
bool is_attr = false)
2005-12-18 23:22:13 +01:00
{
2008-05-04 16:41:23 +02:00
std::auto_ptr<NodeTest<string_type, string_adaptor> > test(getTest(node, end, !is_attr ? axis : ATTRIBUTE, context.namespaceContext()));
std::auto_ptr<XPathExpression_impl<string_type, string_adaptor> > thing;
if(test.get() == 0)
thing.reset(XPath<string_type, string_adaptor>::compile_expression(node++, end, context));
2005-08-04 22:42:30 +02:00
2008-05-04 16:41:23 +02:00
std::vector<XPathExpression_impl<string_type, string_adaptor>*> preds = createPredicates(node, end, context);
2005-08-04 22:42:30 +02:00
2008-05-04 16:41:23 +02:00
if(test.get() == 0)
return new ExprStepExpression<string_type, string_adaptor>(thing.release(), preds);
return new TestStepExpression<string_type, string_adaptor>(axis, test.release(), preds);
2005-08-04 22:42:30 +02:00
} // createStep
2007-07-19 19:01:31 +02:00
static StepExpression<string_type, string_adaptor>* createFilter(const typename types<string_adaptor>::node_iter_t& node,
CompilationContext<string_type, string_adaptor>& context)
{
typename types<string_adaptor>::node_iter_t c = node->children.begin();
typename types<string_adaptor>::node_iter_t const ce = node->children.end();
XPathExpression_impl<string_type, string_adaptor>* step = XPath<string_type, string_adaptor>::compile_expression(c, ce, context);
2007-07-19 19:01:31 +02:00
++c;
std::vector<XPathExpression_impl<string_type, string_adaptor>*> preds = createPredicates(c, ce, context);
2007-07-19 19:01:31 +02:00
return new ExprStepExpression<string_type, string_adaptor>(step, preds);
} // createFilter
static StepExpression<string_type, string_adaptor>* createSingleStep(typename types<string_adaptor>::node_iter_t& node,
typename types<string_adaptor>::node_iter_t const& end,
CompilationContext<string_type, string_adaptor>& context)
2005-08-04 22:42:30 +02:00
{
Axis axis = getAxis(node);
return createSingleStep(node, end, context, axis);
2005-08-04 22:42:30 +02:00
} // createStep
static StepExpression<string_type, string_adaptor>* createSingleStep(typename types<string_adaptor>::node_iter_t& node,
typename types<string_adaptor>::node_iter_t const& end,
CompilationContext<string_type, string_adaptor>& context,
Axis axis)
2005-12-18 23:22:13 +01:00
{
NodeTest<string_type, string_adaptor>* test = getTest(node, end, axis, context.namespaceContext());
2005-12-18 23:22:13 +01:00
return new TestStepExpression<string_type, string_adaptor>(axis, test);
return 0;
2005-12-18 23:22:13 +01:00
} // createStep
private:
2005-09-25 22:09:49 +02:00
static Axis getAxis(typename types<string_adaptor>::node_iter_t& node)
2005-08-04 22:42:30 +02:00
{
2005-09-25 22:09:49 +02:00
long id = getNodeId<string_adaptor>(node);
2005-08-04 22:42:30 +02:00
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;
case impl::AxisSpecifier_id:
{
typename types<string_adaptor>::node_iter_t axis_node = node->children.begin();
skipWhitespace<string_adaptor>(axis_node);
++node;
return getAxis(axis_node);
}
2005-08-16 19:54:20 +02:00
case impl::AbbreviatedAxisSpecifier_id:
case impl::Attribute_id:
2005-08-04 22:42:30 +02:00
++node;
return ATTRIBUTE;
2005-08-16 19:54:20 +02:00
case impl::AncestorOrSelf_id:
++node;
2005-08-04 22:42:30 +02:00
return ANCESTOR_OR_SELF;
2005-08-16 19:54:20 +02:00
case impl::Ancestor_id:
++node;
2005-08-04 22:42:30 +02:00
return ANCESTOR;
2005-08-16 19:54:20 +02:00
case impl::Child_id:
++node;
2005-08-04 22:42:30 +02:00
return CHILD;
2005-08-16 19:54:20 +02:00
case impl::DescendantOrSelf_id:
++node;
2005-08-04 22:42:30 +02:00
return DESCENDANT_OR_SELF;
2005-08-16 19:54:20 +02:00
case impl::Descendant_id:
++node;
2005-08-04 22:42:30 +02:00
return DESCENDANT;
2005-08-16 19:54:20 +02:00
case impl::FollowingSibling_id:
++node;
2005-08-04 22:42:30 +02:00
return FOLLOWING_SIBLING;
2005-08-16 19:54:20 +02:00
case impl::Following_id:
++node;
2005-08-04 22:42:30 +02:00
return FOLLOWING;
2005-08-16 19:54:20 +02:00
case impl::Namespace_id:
++node;
2005-08-04 22:42:30 +02:00
return NAMESPACE;
2005-08-16 19:54:20 +02:00
case impl::Parent_id:
++node;
2005-08-04 22:42:30 +02:00
return PARENT;
2005-08-16 19:54:20 +02:00
case impl::PrecedingSibling_id:
++node;
2005-08-04 22:42:30 +02:00
return PRECEDING_SIBLING;
2005-08-16 19:54:20 +02:00
case impl::Preceding_id:
++node;
2005-08-04 22:42:30 +02:00
return PRECEDING;
2005-08-16 19:54:20 +02:00
case impl::Self_id:
++node;
2005-08-04 22:42:30 +02:00
return SELF;
default:
return CHILD;
} // switch(id)
2005-08-04 22:42:30 +02:00
return CHILD;
} // getAxis
static std::vector<XPathExpression_impl<string_type, string_adaptor>*> createPredicates(typename types<string_adaptor>::node_iter_t& node,
2007-07-19 19:01:31 +02:00
typename types<string_adaptor>::node_iter_t const& end,
CompilationContext<string_type, string_adaptor>& context)
{
std::vector<XPathExpression_impl<string_type, string_adaptor>*> preds;
2007-07-19 19:01:31 +02:00
while((node != end) && (getNodeId<string_adaptor>(node) == impl::Predicate_id))
{
typename types<string_adaptor>::node_iter_t c = node->children.begin();
assert(getNodeId<string_adaptor>(c) == impl::LeftSquare_id);
++c;
preds.push_back(XPath<string_type, string_adaptor>::compile_expression(c, node->children.end(), context));
2007-07-19 19:01:31 +02:00
++c;
assert(getNodeId<string_adaptor>(c) == impl::RightSquare_id);
++node;
} // if ...
return preds;
} // createPredicates
static NodeTest<string_type, string_adaptor>* getTest(typename types<string_adaptor>::node_iter_t& node,
typename types<string_adaptor>::node_iter_t const& end,
Axis axis,
const NamespaceContext<string_type, string_adaptor>& namespaceContext)
2005-08-04 22:42:30 +02:00
{
2005-09-25 22:09:49 +02:00
long id = getNodeId<string_adaptor>(skipWhitespace<string_adaptor>(node));
2005-08-04 22:42:30 +02:00
switch(id)
{
2005-08-16 19:54:20 +02:00
case impl::NodeTest_id:
2005-08-04 22:42:30 +02:00
{
2005-09-25 22:09:49 +02:00
typename types<string_adaptor>::node_iter_t c = node->children.begin();
NodeTest<string_type, string_adaptor>* t = getTest(c, node->children.end(), axis, 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
{
2005-09-25 22:09:49 +02:00
typename types<string_adaptor>::node_iter_t c = node->children.begin();
2005-09-30 23:36:11 +02:00
string_type prefix = string_adaptor::construct(c->value.begin(), c->value.end());
2005-08-18 23:45:14 +02:00
string_type uri = namespaceContext.namespaceURI(prefix);
2005-08-04 22:42:30 +02:00
++c;
2005-09-30 23:36:11 +02:00
string_type name = string_adaptor::construct(c->value.begin(), c->value.end());
2005-08-04 22:42:30 +02:00
++node;
2007-07-19 19:01:31 +02:00
if(axis == ATTRIBUTE)
{
if(prefix == string_adaptor::construct_from_utf8("xmlns"))
return new FailNodeTest<string_type, string_adaptor>();
return new AttributeQNameNodeTest<string_type, string_adaptor>(uri, name);
}
return new QNameNodeTest<string_type, string_adaptor>(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
{
2005-09-30 23:36:11 +02:00
string_type name = string_adaptor::construct(node->value.begin(), node->value.end());
2005-08-04 22:42:30 +02:00
++node;
2007-07-19 19:01:31 +02:00
if(axis == ATTRIBUTE)
{
if(name == string_adaptor::construct_from_utf8("xmlns"))
return new FailNodeTest<string_type, string_adaptor>();
2007-07-19 19:01:31 +02:00
return new AttributeNameNodeTest<string_type, string_adaptor>(name);
}
return new NameNodeTest<string_type, string_adaptor>(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;
return new CommentNodeTest<string_type, string_adaptor>();
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;
return new TextNodeTest<string_type, string_adaptor>();
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;
if((node == end) || (getNodeId<string_adaptor>(node) != impl::Literal_id))
return new ProcessingInstructionNodeTest<string_type, string_adaptor>();
2005-08-04 22:42:30 +02:00
2005-09-30 23:36:11 +02:00
string_type target = string_adaptor::construct(node->value.begin(), node->value.end());
2005-08-04 22:42:30 +02:00
++node;
return new ProcessingInstructionNodeTest<string_type, string_adaptor>(target);
2005-08-04 22:42:30 +02:00
} // case ProcessingInstruction_id
2005-08-16 19:54:20 +02:00
case impl::SlashSlash_id:
2006-01-10 16:05:44 +01:00
case impl::SelfSelect_id:
2007-07-19 19:01:31 +02:00
case impl::ParentSelect_id:
case impl::Node_id:
2005-08-04 22:42:30 +02:00
{
++node;
return new AnyNodeTest<string_type, string_adaptor>();
2005-08-04 22:42:30 +02:00
} // case Node_id
case impl::NodeMatchPattern_id:
2007-07-19 19:01:31 +02:00
{
++node;
return new NodeNodeTest<string_type, string_adaptor>();
} // case NodeMatchPattern_id
2007-07-19 19:01:31 +02:00
2005-08-16 19:54:20 +02:00
case impl::Slash_id:
return new RootNodeTest<string_type, string_adaptor>();
2005-08-04 22:42:30 +02:00
2005-08-16 19:54:20 +02:00
case impl::AnyName_id:
2005-08-04 22:42:30 +02:00
{
++node;
2007-07-19 19:01:31 +02:00
if(axis == ATTRIBUTE)
return new AttributeNodeTest<string_type, string_adaptor>();
return new StarNodeTest<string_type, string_adaptor>();
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
{
2005-09-25 22:09:49 +02:00
typename types<string_adaptor>::node_iter_t prefixNode = node->children.begin();
2005-08-04 22:42:30 +02:00
++node;
2005-09-30 23:36:11 +02:00
string_type prefix = string_adaptor::construct(prefixNode->value.begin(), prefixNode->value.end());
2005-08-18 23:45:14 +02:00
string_type uri = namespaceContext.namespaceURI(prefix);
2007-07-19 19:01:31 +02:00
if(axis == ATTRIBUTE)
{
if(prefix == string_adaptor::construct_from_utf8("xmlns"))
return new FailNodeTest<string_type, string_adaptor>();
return new AttributeQStarNodeTest<string_type, string_adaptor>(uri);
}
return new QStarNodeTest<string_type, string_adaptor>(uri);
2005-08-04 22:42:30 +02:00
} // case
} // switch(id)
return 0;
} // getTest
StepFactory();
}; // class StepFactory
template<class string_type, class string_adaptor>
class RelativeLocationPath : public XPathExpression_impl<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
RelativeLocationPath(StepExpression<string_type, string_adaptor>* step) : steps_() { steps_.push_back(step); }
RelativeLocationPath(const StepList<string_type, string_adaptor>& steps) : steps_(steps) { }
2005-08-04 22:42:30 +02:00
virtual ~RelativeLocationPath()
{
2005-08-21 14:48:00 +02:00
for(typename StepList<string_type, string_adaptor>::const_iterator i = steps_.begin(); i != steps_.end(); ++i)
2005-08-04 22:42:30 +02:00
delete *i;
2007-07-19 19:01:31 +02:00
} // ~RelativeLocationPath
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return NODE_SET; }
virtual XPathValue<string_type, string_adaptor> evaluate(const DOM::Node<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
NodeSet<string_type, string_adaptor> nodes;
2005-08-04 22:42:30 +02:00
nodes.push_back(context);
2005-08-21 14:48:00 +02:00
for(typename StepList<string_type, string_adaptor>::const_iterator i = steps_.begin(); i != steps_.end(); ++i)
2005-08-04 22:42:30 +02:00
{
XPathValue<string_type, string_adaptor> v = (*i)->evaluate(nodes, executionContext);
nodes = v.asNodeSet();
2005-08-04 22:42:30 +02:00
} // for ...
2007-07-19 19:01:31 +02:00
nodes.sort();
return XPathValue<string_type, string_adaptor>(new NodeSetValue<string_type, string_adaptor>(nodes));
2007-07-19 19:01:31 +02:00
} // evaluate
2005-08-04 22:42:30 +02:00
private:
StepList<string_type, string_adaptor> steps_;
friend class MatchExpr<string_type, string_adaptor>;
2007-07-19 19:01:31 +02:00
}; // RelativeLocationPath
2005-08-04 22:42:30 +02:00
template<class string_type, class string_adaptor>
class AbsoluteLocationPath : public RelativeLocationPath<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
AbsoluteLocationPath(StepExpression<string_type, string_adaptor>* step) : RelativeLocationPath<string_type, string_adaptor>(step) { }
AbsoluteLocationPath(const StepList<string_type, string_adaptor>& steps) : RelativeLocationPath<string_type, string_adaptor>(steps) { }
2005-08-04 22:42:30 +02:00
virtual XPathValue<string_type, string_adaptor> evaluate(const DOM::Node<string_type, string_adaptor>& context, const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
int type = context.getNodeType();
if((type == DOM::Node_base::DOCUMENT_NODE) ||
(type == DOM::Node_base::DOCUMENT_FRAGMENT_NODE))
return RelativeLocationPath<string_type, string_adaptor>::evaluate(context, executionContext);
2005-08-04 22:42:30 +02:00
DOM::Document<string_type, string_adaptor> document = context.getOwnerDocument();
return RelativeLocationPath<string_type, string_adaptor>::evaluate(document, executionContext);
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class AbsoluteLocationPath
} // impl
2005-08-04 22:42:30 +02:00
} // XPath
} // Arabica
#endif