From 38d2783be3cb26b2238b5abd200d88fa016bb6f8 Mon Sep 17 00:00:00 2001 From: jez Date: Tue, 25 Nov 2008 12:27:33 +0000 Subject: [PATCH] Finally! Determining import precedence for templates is properly correct. --- .../impl/handler/xslt_include_handler.hpp | 27 ++--- .../XSLT/impl/xslt_compilation_context.hpp | 23 ++-- .../XSLT/impl/xslt_compiled_stylesheet.hpp | 12 +-- include/XSLT/impl/xslt_precedence.hpp | 101 ++++++++---------- 4 files changed, 74 insertions(+), 89 deletions(-) diff --git a/include/XSLT/impl/handler/xslt_include_handler.hpp b/include/XSLT/impl/handler/xslt_include_handler.hpp index 51af9bb5..52cb1f8b 100644 --- a/include/XSLT/impl/handler/xslt_include_handler.hpp +++ b/include/XSLT/impl/handler/xslt_include_handler.hpp @@ -54,8 +54,8 @@ public: if(localName == "import") { std::string href = validate_href(qName, atts); - check_for_loops(import_stack_, href); - import_stack_.push_back(href); + //check_for_loops(import_stack_, href); + import_stack_.push_back(std::make_pair(href, context_->next_precedence())); return; } // if(localName == "import") if(localName == "include") @@ -87,7 +87,7 @@ public: no_content_ = false; if(localName == "include") { - include_stylesheet(href_.back()); + include_stylesheet(href_.back(), context_->precedence()); href_.pop_back(); } // if ... if(href_.empty()) @@ -111,11 +111,9 @@ public: { while(!import_stack_.empty()) { - std::vector::iterator import = import_stack_.end()-1; + ImportStack::iterator import = import_stack_.end()-1; size_t index = import_stack_.size() - 1; - context_->push_import_precedence(); - include_stylesheet(import_stack_.back()); - context_->pop_import_precedence(); + include_stylesheet(import_stack_.back().first, import_stack_.back().second); import_stack_.erase(import_stack_.begin() + index); } // while ... } // unwind_imports @@ -130,9 +128,9 @@ private: return context_->makeAbsolute(href); } // validate_href - void check_for_loops(const std::vector& stack, const std::string& href) +/* void check_for_loops(const ImportStack& stack, const std::string& href) { - if(std::find(stack.begin(), stack.end(), href) != stack.end()) + if(std::find(stack.begin(), stack.end(), candidate) != stack.end()) { std::string error = "Stylesheet '" + href + "' includes/imports itself "; for(std::vector::const_iterator i = stack.begin(), ie = stack.end(); i != ie; ++i) @@ -140,13 +138,14 @@ private: throw std::runtime_error(error); } // if ... } // check_for_loops - - void include_stylesheet(const std::string& href) +*/ + void include_stylesheet(const std::string& href, const Precedence& precedence) { - check_for_loops(current_includes_, href); + //check_for_loops(current_includes_, href); current_includes_.push_back(href); std::string prev = context_->setBase(href); + context_->set_precedence(precedence); SAX::InputSource source(href); SAX::XMLReader include_parser; @@ -168,7 +167,9 @@ private: SAX::DefaultHandler* compiler_; CompilationContext* context_; bool no_content_; - std::vector import_stack_; + + typedef std::vector > ImportStack; + ImportStack import_stack_; std::vector current_includes_; std::vector href_; diff --git a/include/XSLT/impl/xslt_compilation_context.hpp b/include/XSLT/impl/xslt_compilation_context.hpp index 380de094..bfa1e662 100755 --- a/include/XSLT/impl/xslt_compilation_context.hpp +++ b/include/XSLT/impl/xslt_compilation_context.hpp @@ -27,7 +27,8 @@ public: parser_(parser), stylesheet_(stylesheet), autoNs_(1), - current_allowed_(false) + current_allowed_(false), + precedence_(Precedence::InitialPrecedence()) { xpath_.setNamespaceContext(*this); xpath_.setFunctionResolver(*this); @@ -139,23 +140,19 @@ public: return ss.str(); } // autoNamespacePrefix - void push_import_precedence() + void set_precedence(const Precedence& prec) { - precedenceStack_.push(); - } // push_import_precedence + precedence_ = prec; + } // set_precedence - void pop_import_precedence() + Precedence next_precedence() { - precedenceStack_.pop(); - } // pop_import_precedence - - // void set_precedence(const Prcedence& prec) - - // const Precedence& next_precedence() + return precedence_.next_generation(); + } // next_precedence const Precedence& precedence() const { - return precedenceStack_.top(); + return precedence_; } // precedence private: @@ -203,7 +200,7 @@ private: std::stack*> handlerStack_; std::stack parentStack_; std::map namespaceRemap_; - PrecedenceStack precedenceStack_; + Precedence precedence_; CompilationContext(const CompilationContext&); mutable int autoNs_; diff --git a/include/XSLT/impl/xslt_compiled_stylesheet.hpp b/include/XSLT/impl/xslt_compiled_stylesheet.hpp index 79756c71..7559e388 100755 --- a/include/XSLT/impl/xslt_compiled_stylesheet.hpp +++ b/include/XSLT/impl/xslt_compiled_stylesheet.hpp @@ -195,19 +195,19 @@ private: void doApplyTemplates(const DOM::Node& node, ExecutionContext& context, const std::pair& mode, - Precedence generation) const + const Precedence& generation) const { StackFrame frame(context); - std::vector higher_precedences; + std::vector lower_precedences; for(TemplateStack::const_iterator ts = templates_.begin(), tse = templates_.end(); ts != tse; ++ts) - if(ts->first > generation) - higher_precedences.push_back(ts->first); - std::sort(higher_precedences.begin(), higher_precedences.end()); + if(generation.is_descendant(ts->first)) + lower_precedences.push_back(ts->first); + std::sort(lower_precedences.rbegin(), lower_precedences.rend()); current_mode_ = mode; - for(std::vector::const_iterator p = higher_precedences.begin(), pe = higher_precedences.end(); p != pe; ++p) + for(std::vector::const_iterator p = lower_precedences.begin(), pe = lower_precedences.end(); p != pe; ++p) { current_generation_ = *p; ModeTemplates ts = templates_.find(current_generation_)->second; diff --git a/include/XSLT/impl/xslt_precedence.hpp b/include/XSLT/impl/xslt_precedence.hpp index 3256f71c..f3fb167f 100755 --- a/include/XSLT/impl/xslt_precedence.hpp +++ b/include/XSLT/impl/xslt_precedence.hpp @@ -12,29 +12,33 @@ public: static const Precedence& FrozenPrecedence() { - static Precedence frozen_(-1); + static Precedence frozen_; return frozen_; } // Precedence Precedence() : - precedence_() + precedence_(), + children_(0) { //precedence_.push_back(0); } // Precedence Precedence(const Precedence& rhs) : - precedence_(rhs.precedence_) + precedence_(rhs.precedence_), + children_(rhs.children_) { } // Precedence private: Precedence(const std::vector precedence) : - precedence_(precedence) + precedence_(precedence), + children_(0) { } // Precedence Precedence(int precedence) : - precedence_() + precedence_(), + children_(0) { precedence_.push_back(precedence); } // Precedence @@ -47,80 +51,63 @@ public: return precedence_ == rhs.precedence_; } // operator== - bool operator>(const Precedence& rhs) const - { - return precedence_ > rhs.precedence_; - } // operator> - Precedence& operator=(const Precedence& rhs) { std::vector other(rhs.precedence_); precedence_.swap(other); + children_ = rhs.children_; return *this; } // operator= - Precedence nextGeneration(int p) const + bool is_descendant(const Precedence& other) const + { + if(other.precedence_.size() <= precedence_.size()) + return false; + + for(int i = 0, ie = precedence_.size(); i != ie; ++i) + if(other.precedence_[i] != precedence_[i]) + return false; + + return true; + } // is_descendant + + + Precedence next_generation() { Precedence next(precedence_); - next.precedence_.push_back(p); + next.precedence_.push_back(++children_); return next; } // nextGeneration private: std::vector precedence_; + int children_; friend bool operator<(const Precedence& lhs, const Precedence& rhs); - friend std::ostream& operator<<(std::ostream& os, const Precedence& prec); }; // class Precedence bool operator<(const Precedence& lhs, const Precedence& rhs) { - return lhs.precedence_.back() < rhs.precedence_.back(); -} // PrecedenceCompare + if(lhs.precedence_ == rhs.precedence_) + return false; -std::ostream& operator<<(std::ostream& os, const Precedence& prec) -{ - os << "("; - for(std::vector::const_iterator p = prec.precedence_.begin(), pe = prec.precedence_.end(); p != pe; ++p) + int len = std::min(lhs.precedence_.size(), rhs.precedence_.size()); + for(int c = 0; c < len; ++c) { - if(p != prec.precedence_.begin()) - os << ","; - os << *p; - } // for .. - os << ")"; -} // operator<< - -class PrecedenceStack -{ -public: - PrecedenceStack() : - stack_(), - count_(1) - { - stack_.push(Precedence::InitialPrecedence()); - } // PrecedenceStack - - PrecedenceStack(const PrecedenceStack& rhs) : - stack_(rhs.stack_) - { - } // PrecedenceStack - - const Precedence& top() const { return stack_.top(); } - void push() - { - stack_.push(top().nextGeneration(count_++)); - std::cout << "Pushed " << top() << std::endl; + if(lhs.precedence_[c] < rhs.precedence_[c]) + return true; + if(lhs.precedence_[c] > rhs.precedence_[c]) + return false; } - void pop() { stack_.pop(); } - void freeze() - { - while(!stack_.empty()) - stack_.pop(); - stack_.push(Precedence::FrozenPrecedence()); - } // freeze + if(lhs.precedence_.size() < rhs.precedence_.size()) + return false; -private: - std::stack stack_; - int count_; -}; // class PrecedenceStack + return true; +} // operator> + +bool operator>(const Precedence& lhs, const Precedence& rhs) +{ + return !(lhs == rhs) && !(lhs < rhs); +} // operator> + #endif