arabica/include/XSLT/impl/handler/xslt_template_handler.hpp

130 lines
4 KiB
C++
Executable file

#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
{
class TemplateHandler : public ItemContainerHandler<Template>
{
public:
TemplateHandler(CompilationContext& context) :
ItemContainerHandler<Template>(context),
done_params_(false)
{
} // TemplateHandler
virtual void characters(const std::string& ch)
{
if(!done_params_)
{
for(std::string::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_)
ItemContainerHandler<Template>::characters(ch);
} // characters
protected:
virtual Template* createContainer(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName,
const SAX::Attributes<std::string>& atts)
{
static const ValueRule rules[] = { { "match", false, 0 },
{ "mode", false, 0 },
{ "name", false, 0 },
{ "priority", false, 0 },
{ 0, false, 0} };
std::map<std::string, std::string> attributes = gatherAttributes(qName, atts, rules);
const std::string& match = attributes["match"];
if((match == "") && (attributes["name"] == ""))
throw SAX::SAXException("xsl:template must have a match and/or a name attribute");
int index = atts.getIndex("mode");
if(index != -1)
{
const std::string& mode = attributes["mode"];
if(mode == "")
throw SAX::SAXException("xsl:template mode cannot be empty");
if(match == "")
throw SAX::SAXException("xsl:template may not have a mode without a match");
} // ...
const std::string& priority = attributes["priority"];
if((atts.getIndex("priority") != -1) && (priority == ""))
throw SAX::SAXException("xsl:template priority cannot be empty");
std::string name;
if(attributes["name"] != "")
name = context().processInternalQName(attributes["name"]).clarkName();
std::string mode;
if(attributes["mode"] != "")
mode = context().processInternalQName(attributes["mode"]).clarkName();
if(match == "")
return new Template(name,
mode,
priority,
context().precedence());
return new Template(context().xpath_match(match),
name,
mode,
priority,
context().precedence());
} // createContainer
virtual bool createChild(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName,
const SAX::Attributes<std::string>& atts)
{
if((namespaceURI == StylesheetConstant::NamespaceURI()) &&
(localName == "param"))
{
if(!done_params_)
{
context().push(container(),
new VariableHandler<Param>(context()),
namespaceURI,
qName,
localName,
atts);
return true;
}
else
throw SAX::SAXException("xsl:param must immediately follow xsl:template");
}
done_params_ = true;
return ItemContainerHandler<Template>::createChild(namespaceURI, localName, qName, atts);
} // createChild
public:
virtual void endElement(const std::string& namespaceURI,
const std::string& localName,
const std::string& qName)
{
context().stylesheet().add_template(container());
context().pop();
} // endElement
private:
bool done_params_;
}; // class TemplateHandler
} // namespace XSLT
} // namespace Arabica
#endif // ARABICA_XSLT_TEMPLATE_HANDLER_HPP