#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 { class CompiledStylesheet; class ItemContainer; class CompilationContext : private Arabica::XPath::FunctionResolver, private Arabica::XPath::NamespaceContext > { public: CompilationContext(StylesheetParser& parser, CompiledStylesheet& stylesheet) : parser_(parser), stylesheet_(stylesheet), autoNs_(1), current_allowed_(false) { xpath_.setNamespaceContext(*this); xpath_.setFunctionResolver(*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(SAX::DefaultHandler& root) { handlerStack_.push(&root); } // root StylesheetParser& parser() const { return parser_; } Arabica::XPath::XPathExpressionPtr xpath_expression(const std::string& expr) const { return xpath_.compile_expr(expr); } std::vector > xpath_match(const std::string& match) const { DisallowCurrent guard(current_allowed_); return xpath_.compile_match(match); } // xpath_match Arabica::XPath::XPathExpressionPtr xpath_attribute_value_template(const std::string& expr) const { return xpath_.compile_attribute_value_template(expr); } CompiledStylesheet& stylesheet() const { return stylesheet_; } std::pair processInternalQName(const std::string& qName) const { if(!Arabica::XML::is_qname(qName)) throw SAX::SAXException("Bad name : " + qName); // 2.4 The default namespace is not used for unprefixed names. if(qName.find(':') == std::string::npos) return std::make_pair("", qName); return parser_.processQName(qName); } // processInternalQName std::string makeAbsolute(const std::string& href) const { return parser_.makeAbsolute(href); } // makeAbsolute std::string setBase(const std::string& href) const { return parser_.setBase(href); } // setBase void push(ItemContainer* parent, SAX::DefaultHandler* newHandler, const std::string& namespaceURI, const std::string& localName, const std::string& qName, const SAX::Attributes& atts) { parentStack_.push(parent); handlerStack_.push(newHandler); parser_.setContentHandler(*newHandler); newHandler->startElement(namespaceURI, qName, localName, atts); } // push void pop() { parentStack_.pop(); delete handlerStack_.top(); handlerStack_.pop(); parser_.setContentHandler(*handlerStack_.top()); } // pop ItemContainer& parentContainer() const { return *parentStack_.top(); } // parentContainer SAX::ContentHandler& parentHandler() const { parser_.setContentHandler(*handlerStack_.top()); return parser_.contentHandler(); } // parentHandler std::map inScopeNamespaces() const { return parser_.inScopeNamespaces(); } // inScopeNamespaces void addNamespaceAlias(const std::string& stylesheet_namespace, const std::string& result_prefix, const std::string& result_namespace) { namespaceRemap_[stylesheet_namespace] = std::make_pair(result_prefix, result_namespace); } // addNamespaceAlias bool isRemapped(const std::string& namespaceURI) const { return namespaceRemap_.find(namespaceURI) != namespaceRemap_.end(); } // isRemapped const std::pair& remappedNamespace(const std::string& namespaceURI) { return namespaceRemap_[namespaceURI]; } // remappedNamespace std::string autoNamespacePrefix() const { std::ostringstream ss; ss << "auto-ns" << autoNs_++; return ss.str(); } // autoNamespacePrefix void push_import_precedence() { precedenceStack_.push(); } // push_import_precedence void pop_import_precedence() { precedenceStack_.pop(); } // pop_import_precedence const Precedence& precedence() const { return precedenceStack_.top(); } // precedence private: // FunctionResolver virtual Arabica::XPath::XPathFunction* resolveFunction( const std::string& namespace_uri, const std::string& name, const std::vector >& argExprs) const { if(!namespace_uri.empty()) return 0; // document if(name == "document") return new DocumentFunction(parser_.currentBase(), argExprs); // key // format-number if((name == "current") && (current_allowed_)) return new CurrentFunction(argExprs); // unparsed-entity-uri //if(name == "unparsed-entity-uri") // return new UnparsedEntityUriFunction(argExprs); // generate-id if(name == "generate-id") return new GenerateIdFunction(argExprs); if(name == "system-property") return new SystemPropertyFunction(argExprs); // element-available // function-available return 0; } // resolveFunction // NamespaceContext virtual std::string namespaceURI(const std::string& prefix) const { return parser_.namespaceURI(prefix); } // namespaceURI typedef std::pair Namespace; StylesheetParser& parser_; Arabica::XPath::XPath xpath_; CompiledStylesheet& stylesheet_; std::stack*> handlerStack_; std::stack parentStack_; std::map namespaceRemap_; PrecedenceStack precedenceStack_; CompilationContext(const CompilationContext&); mutable int autoNs_; mutable bool current_allowed_; class DisallowCurrent { public: DisallowCurrent(bool& allow) : allow_(allow) { allow_ = false; } ~DisallowCurrent() { allow_ = true; } private: bool& allow_; }; // DisallowCurrent }; // class CompilationContext } // namespace XSLT } // namespace Arabica #endif // ARABICA_XSLT_COMPILATION_CONTEXT