#ifndef ARABICA_XPATHIC_XPATH_UNION_HPP #define ARABICA_XPATHIC_XPATH_UNION_HPP #include "xpath_value.hpp" #include namespace Arabica { namespace XPath { namespace impl { template class UnionExpression : private BinaryExpression, public XPathExpression { typedef BinaryExpression baseT; public: UnionExpression(XPathExpression* lhs, XPathExpression* rhs) : BinaryExpression(lhs, rhs) { } virtual XPathValuePtr evaluate(const DOM::Node& context, const ExecutionContext& executionContext) const { XPathValuePtr p1 = baseT::lhs()->evaluate(context, executionContext); if(p1->type() != NODE_SET) throw RuntimeException("Union operator joins node-sets. First argument is not a node-set."); XPathValuePtr p2 = baseT::rhs()->evaluate(context, executionContext); if(p2->type() != NODE_SET) throw RuntimeException("Union operator joins node-sets. Second argument is not a node-set."); NodeSet ns1(p1->asNodeSet()); NodeSet ns2(p2->asNodeSet()); // do the obvious optimizations if(ns1.empty()) return wrap(ns2); if(ns2.empty()) return wrap(ns1); ns1.insert(ns1.end()-1, ns2.begin(), ns2.end()); ns1.to_document_order(); return wrap(ns1); } // evaluate private: XPathValuePtr wrap(const NodeSet& ns) const { return XPathValuePtr(new NodeSetValue(ns)); } // wrap }; // UnionExpression } // namespace impl } // namespace XPath } // namespace Arabica #endif