#ifndef ARABICA_XSLT_NAMESPACE_STACK_HPP #define ARABICA_XSLT_NAMESPACE_STACK_HPP #include #include namespace Arabica { namespace XSLT { class NamespaceStack { public: typedef std::map Scope; NamespaceStack() : autoNs_(1) { prefixStack_.push_back(Scope()); uriStack_.push_back(Scope()); } // NamespaceStack void pushScope() { prefixStack_.push_back(Scope()); uriStack_.push_back(Scope()); } // pushScope void popScope() { prefixStack_.pop_back(); uriStack_.pop_back(); } // popScope void declareNamespace(const std::string& given_prefix, const std::string& namespaceURI, bool attr = false) { if(findPrefix(namespaceURI) != EMPTY_STRING) return; bool remap = (attr && given_prefix.empty()) || (given_prefix == "xmlns"); std::string prefix = !remap ? given_prefix : autoNamespacePrefix(); prefixStack_.back()[prefix] = namespaceURI; uriStack_.back()[namespaceURI] = prefix; } // declareNamespace const std::string& findURI(const std::string& prefix) const { return searchStack(prefixStack_, prefix); } // findURI const std::string& findPrefix(const std::string& uri) const { return searchStack(uriStack_, uri); } // findPrefix Scope::const_iterator begin() { return prefixStack_.back().begin(); } Scope::const_iterator end() { return prefixStack_.back().end(); } private: typedef std::vector ScopeStack; const std::string& searchStack(const ScopeStack& stack, const std::string& key) const { for(ScopeStack::const_reverse_iterator ss = stack.rbegin(), se = stack.rend(); ss != se; ss++) { Scope::const_iterator i = ss->find(key); if(i != ss->end()) return i->second; } return EMPTY_STRING; } // searchStack std::string autoNamespacePrefix() { std::ostringstream ss; ss << "auto-ns" << autoNs_++; return ss.str(); } // autoNamespacePrefix ScopeStack prefixStack_; ScopeStack uriStack_; std::string EMPTY_STRING; unsigned int autoNs_; }; // class NamespaceStack } // namespace XSLT } // namespace Arabica #endif // ARABICA_XSLT_NAMESPACE_STACK_HPP