#ifndef ARABICA_XSLT_COMPILATION_CONTEXT #define ARABICA_XSLT_COMPILATION_CONTEXT #include #include #include #include #include #include "xslt_stylesheet_parser.hpp" #include "xslt_functions.hpp" namespace Arabica { namespace XSLT { template class CompiledStylesheet; template class ItemContainer; template > class CompilationContext : private Arabica::XPath::FunctionResolver, private Arabica::XPath::NamespaceContext, private Arabica::XPath::DefaultVariableCompileTimeResolver { private: typedef Arabica::XPath::DefaultVariableCompileTimeResolver CTVariableResolverT; typedef StylesheetConstant SC; public: typedef StylesheetParser StylesheetParserT; typedef CompiledStylesheet CompiledStylesheetT; typedef SAX::DefaultHandler DefaultHandlerT; typedef SAX::ContentHandler ContentHandlerT; typedef SAX::Attributes AttributesT; typedef Arabica::XPath::XPathExpressionPtr XPathExpressionPtrT; typedef Arabica::XPath::MatchExpr MatchExprT; typedef XML::QualifiedName QualifiedNameT; CompilationContext(StylesheetParserT& parser, CompiledStylesheetT& stylesheet) : parser_(parser), stylesheet_(stylesheet), autoNs_(1), current_allowed_(false), variables_allowed_(true), precedence_(Precedence::InitialPrecedence()) { xpath_.setNamespaceContext(*this); xpath_.setFunctionResolver(*this); xpath_.setVariableCompileTimeResolver(*this); } // CompilationContext ~CompilationContext() { // delete any left over - will only be the case if unwinding while(handlerStack_.size() > 1) { delete handlerStack_.top(); handlerStack_.pop(); } // while ... } // ~CompilationContext void root(DefaultHandlerT& root) { handlerStack_.push(&root); } // root StylesheetParserT& parser() const { return parser_; } XPathExpressionPtrT xpath_expression(const string_type& expr) const { return xpath_.compile_expr(expr); } XPathExpressionPtrT xpath_expression_no_variables(const string_type& expr) const { Disallow variables(variables_allowed_); return xpath_expression(expr); } // xpath_expression_no_variables std::vector xpath_match(const string_type& match) const { Disallow current(current_allowed_); return xpath_.compile_match(match); } // xpath_match std::vector > xpath_match_no_variables(const string_type& match) const { Disallow variables(variables_allowed_); return xpath_match(match); } // xpath_match_no_variables XPathExpressionPtrT xpath_attribute_value_template(const string_type& expr) const { return xpath_.compile_attribute_value_template(expr); } CompiledStylesheetT& stylesheet() const { return stylesheet_; } QualifiedNameT processElementQName(const string_type& qName) const { return parser_.processElementQName(qName); } // processElementQName QualifiedNameT processInternalQName(const string_type& qName) const { return parser_.processInternalQName(qName); } // processInternalQName string_type makeAbsolute(const string_type& href) const { return parser_.makeAbsolute(href); } // makeAbsolute string_type setBase(const string_type& href) const { return parser_.setBase(href); } // setBase string_type currentBase() const { return parser_.currentBase(); } // currentBase void push(ItemContainer* parent, DefaultHandlerT* newHandler, const string_type& namespaceURI, const string_type& localName, const string_type& qName, const AttributesT& atts) { parentStack_.push(parent); handlerStack_.push(newHandler); parser_.setContentHandler(*newHandler); newHandler->startElement(namespaceURI, localName, qName, atts); } // push void pop() { parentStack_.pop(); delete handlerStack_.top(); handlerStack_.pop(); parser_.setContentHandler(*handlerStack_.top()); } // pop ItemContainer& parentContainer() const { return *parentStack_.top(); } // parentContainer ContentHandlerT& parentHandler() const { parser_.setContentHandler(*handlerStack_.top()); return parser_.contentHandler(); } // parentHandler std::map inScopeNamespaces() const { return parser_.inScopeNamespaces(); } // inScopeNamespaces void addNamespaceAlias(const string_type& stylesheet_namespace, const string_type& result_prefix, const string_type& result_namespace) { namespaceRemap_[stylesheet_namespace] = std::make_pair(result_prefix, result_namespace); } // addNamespaceAlias bool isRemapped(const string_type& namespaceURI) const { return namespaceRemap_.find(namespaceURI) != namespaceRemap_.end(); } // isRemapped const std::pair& remappedNamespace(const string_type& namespaceURI) { return namespaceRemap_[namespaceURI]; } // remappedNamespace string_type autoNamespacePrefix() const { std::basic_ostringstream ss; ss << SC::auto_ns << autoNs_++; return string_adaptor::construct(ss.str()); } // autoNamespacePrefix void set_precedence(const Precedence& prec) { precedence_ = prec; } // set_precedence Precedence next_precedence() { return precedence_.next_generation(); } // next_precedence const Precedence& precedence() const { return precedence_; } // precedence private: virtual Arabica::XPath::XPathExpression_impl* compileVariable(const string_type& namespace_uri, const string_type& name) const { if(!variables_allowed_) return 0; return CTVariableResolverT::compileVariable(namespace_uri, name); } // compileVariable // FunctionResolver virtual Arabica::XPath::XPathFunction* resolveFunction( const string_type& namespace_uri, const string_type& name, const std::vector >& argExprs) const { if(!string_adaptor::empty(namespace_uri)) return new UndefinedFunction(namespace_uri, name, argExprs); // document if(name == DocumentFunction::name()) return new DocumentFunction(parser_.currentBase(), argExprs); // key if(name == KeyFunction::name()) return new KeyFunction(stylesheet_.keys(), parser_.inScopeNamespaces(), argExprs); // format-number // current if((name == CurrentFunction::name()) && (current_allowed_)) return new CurrentFunction(argExprs); // unparsed-entity-uri //if(name == UnparsedEntityUriFunction::name()) // return new UnparsedEntityUriFunction(argExprs); // generate-id if(name == GenerateIdFunction::name()) return new GenerateIdFunction(argExprs); if(name == SystemPropertyFunction::name()) return new SystemPropertyFunction(argExprs); // element-available if(name == ElementAvailableFunction::name()) { std::vector > dummy; return new ElementAvailableFunction(dummy, parser_.inScopeNamespaces(), argExprs); } // function-available if(name == FunctionAvailableFunction::name()) return new FunctionAvailableFunction(validNames(), parser_.inScopeNamespaces(), argExprs); return 0; } // resolveFunction virtual std::vector > validNames() const { static string_type functionNames[] = { DocumentFunction::name(), KeyFunction::name(), /* format-number, */ CurrentFunction::name(), UnparsedEntityUriFunction::name(), GenerateIdFunction::name(), SystemPropertyFunction::name(), ElementAvailableFunction::name(), FunctionAvailableFunction::name(), string_adaptor::empty_string() }; std::vector > names; for(int i = 0; functionNames[i] != string_adaptor::empty_string(); ++i) names.push_back(std::make_pair(string_adaptor::empty_string(), functionNames[i])); return names; } // validNames // NamespaceContext virtual string_type namespaceURI(const string_type& prefix) const { return parser_.namespaceURI(prefix); } // namespaceURI typedef std::pair Namespace; StylesheetParser& parser_; CompiledStylesheetT& stylesheet_; mutable int autoNs_; mutable bool current_allowed_; mutable bool variables_allowed_; Precedence precedence_; Arabica::XPath::XPath xpath_; std::stack*> handlerStack_; std::stack*> parentStack_; std::map namespaceRemap_; CompilationContext(const CompilationContext&); class Disallow { public: Disallow(bool& allow) : allow_(allow) { allow_ = false; } ~Disallow() { allow_ = true; } private: bool& allow_; }; // DisallowCurrent }; // class CompilationContext } // namespace XSLT } // namespace Arabica #endif // ARABICA_XSLT_COMPILATION_CONTEXT