#ifndef ARABICA_XSLT_TEMPLATE_HANDLER_HPP #define ARABICA_XSLT_TEMPLATE_HANDLER_HPP #include "../xslt_template.hpp" #include "xslt_item_container_handler.hpp" namespace Arabica { namespace XSLT { template class TemplateHandler : public ItemContainerHandler > { typedef ItemContainerHandler > baseT; typedef StylesheetConstant SC; typedef AttributeValidators AV; public: TemplateHandler(CompilationContext& context) : baseT(context), done_params_(false) { } // TemplateHandler virtual void characters(const string_type& ch) { if(!done_params_) { for(typename string_type::const_iterator i = ch.begin(), e = ch.end(); i != e; ++i) if(!Arabica::XML::is_space(*i)) { done_params_ = true; break; } // if ... } // if(!done_params_) baseT::characters(ch); } // characters protected: virtual Template* createContainer(const string_type& /* namespaceURI */, const string_type& /* localName */, const string_type& qName, const SAX::Attributes& atts) { static const AV rules = AV::rule(SC::match, false) .rule(SC::mode, false) .rule(SC::name, false) .rule(SC::priority, false); std::map attributes = rules.gather(qName, atts); const string_type& match = attributes[SC::match]; if((match == string_adaptor::empty_string()) && (attributes[SC::name] == string_adaptor::empty_string())) throw SAX::SAXException("xsl:template must have a match and/or a name attribute"); int index = atts.getIndex(SC::mode); if(index != -1) { const string_type& mode = attributes[SC::mode]; if(mode == string_adaptor::empty_string()) throw SAX::SAXException("xsl:template mode cannot be empty"); if(match == string_adaptor::empty_string()) throw SAX::SAXException("xsl:template may not have a mode without a match"); } // ... const string_type& priority = attributes[SC::priority]; if((atts.getIndex(SC::priority) != -1) && (priority == string_adaptor::empty_string())) throw SAX::SAXException("xsl:template priority cannot be empty"); string_type name; if(attributes[SC::name] != string_adaptor::empty_string()) name = baseT::context().processInternalQName(attributes[SC::name]).clarkName(); string_type mode; if(attributes[SC::mode] != string_adaptor::empty_string()) mode = baseT::context().processInternalQName(attributes[SC::mode]).clarkName(); if(match == string_adaptor::empty_string()) return new Template(name, mode, priority, baseT::context().precedence()); return new Template(baseT::context().xpath_match(match), name, mode, priority, baseT::context().precedence()); } // createContainer virtual bool createChild(const string_type& namespaceURI, const string_type& localName, const string_type& qName, const SAX::Attributes& atts) { if((namespaceURI == SC::NamespaceURI) && (localName == SC::param)) { if(!done_params_) { baseT::context().push(baseT::container(), new VariableHandler >(baseT::context()), namespaceURI, localName, qName, atts); return true; } else throw SAX::SAXException("xsl:param must immediately follow xsl:template"); } done_params_ = true; return baseT::createChild(namespaceURI, localName, qName, atts); } // createChild public: virtual void endElement(const string_type& /* namespaceURI */, const string_type& /* localName */, const string_type& /* qName */) { baseT::context().stylesheet().add_template(baseT::container()); baseT::context().pop(); } // endElement private: bool done_params_; }; // class TemplateHandler } // namespace XSLT } // namespace Arabica #endif // ARABICA_XSLT_TEMPLATE_HANDLER_HPP