2007-07-19 19:01:42 +02:00
|
|
|
#ifndef ARABICA_XSLT_STYLESHEETCONSTANT_HPP
|
|
|
|
#define ARABICA_XSLT_STYLESHEETCONSTANT_HPP
|
|
|
|
|
2007-09-05 00:55:47 +02:00
|
|
|
#include <XML/XMLCharacterClasses.hpp>
|
2007-08-23 15:55:06 +02:00
|
|
|
#include <XPath/impl/xpath_namespace_context.hpp>
|
2007-07-19 19:01:42 +02:00
|
|
|
#include <memory>
|
|
|
|
|
2007-08-22 14:38:20 +02:00
|
|
|
#include "xslt_stylesheet_parser.hpp"
|
2008-11-05 02:33:28 +01:00
|
|
|
#include "xslt_compiled_stylesheet.hpp"
|
2007-07-19 19:01:42 +02:00
|
|
|
#include "xslt_compilation_context.hpp"
|
2010-05-19 21:22:22 +02:00
|
|
|
#include "handler/xslt_value_validation.hpp"
|
2007-07-19 19:01:42 +02:00
|
|
|
#include "handler/xslt_template_handler.hpp"
|
|
|
|
#include "handler/xslt_include_handler.hpp"
|
|
|
|
#include "handler/xslt_output_handler.hpp"
|
|
|
|
#include "handler/xslt_namespace_alias_handler.hpp"
|
2009-02-16 23:10:00 +01:00
|
|
|
#include "handler/xslt_key_handler.hpp"
|
2009-04-24 20:02:14 +02:00
|
|
|
#include "handler/xslt_foreign_element_handler.hpp"
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XSLT
|
|
|
|
{
|
|
|
|
|
2007-09-05 14:57:07 +02:00
|
|
|
class StylesheetHandler : public SAX::DefaultHandler<std::string>
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
StylesheetHandler(CompilationContext& context) :
|
|
|
|
context_(context),
|
2009-04-28 10:00:05 +02:00
|
|
|
top_(false)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
context_.root(*this);
|
|
|
|
includer_.context(context_, this);
|
|
|
|
} // StylesheetHandler
|
|
|
|
|
2007-11-21 23:34:15 +01:00
|
|
|
virtual void startDocument()
|
|
|
|
{
|
|
|
|
top_ = true;
|
|
|
|
} // startDocument
|
|
|
|
|
2007-07-19 19:01:42 +02:00
|
|
|
virtual void startElement(const std::string& namespaceURI,
|
|
|
|
const std::string& localName,
|
|
|
|
const std::string& qName,
|
2007-09-05 14:57:07 +02:00
|
|
|
const SAX::Attributes<std::string>& atts)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
if(top_)
|
|
|
|
{
|
2009-04-28 09:57:14 +02:00
|
|
|
top_ = false;
|
|
|
|
if(namespaceURI == StylesheetConstant::NamespaceURI())
|
2009-04-28 21:59:52 +02:00
|
|
|
startStylesheet(namespaceURI, localName, qName, atts);
|
2009-04-28 09:57:14 +02:00
|
|
|
else
|
2009-04-28 21:59:52 +02:00
|
|
|
startLREAsStylesheet(namespaceURI, localName, qName, atts);
|
2007-07-19 19:01:42 +02:00
|
|
|
return;
|
2007-11-21 23:34:15 +01:00
|
|
|
} // if(top_)
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2007-11-21 00:12:08 +01:00
|
|
|
if(namespaceURI == StylesheetConstant::NamespaceURI())
|
2009-04-24 16:54:13 +02:00
|
|
|
startXSLTElement(namespaceURI, localName, qName, atts);
|
2007-11-23 01:07:08 +01:00
|
|
|
else if(!namespaceURI.empty())
|
2009-04-24 20:02:14 +02:00
|
|
|
startForeignElement(namespaceURI, localName, qName, atts);
|
2009-04-24 16:54:13 +02:00
|
|
|
else
|
|
|
|
oops(qName);
|
2007-07-19 19:01:42 +02:00
|
|
|
} // startElement
|
|
|
|
|
2010-01-11 10:02:17 +01:00
|
|
|
virtual void endElement(const std::string& /* namespaceURI */,
|
|
|
|
const std::string& /* localName */,
|
|
|
|
const std::string& /* qName */)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
} // endElement
|
|
|
|
|
|
|
|
virtual void characters(const std::string& ch)
|
|
|
|
{
|
2010-05-19 21:22:22 +02:00
|
|
|
verifyNoCharacterData(ch, "xsl:stylesheet/xsl:transform");
|
2007-07-19 19:01:42 +02:00
|
|
|
} // characters
|
|
|
|
|
|
|
|
virtual void endDocument()
|
|
|
|
{
|
|
|
|
includer_.unwind_imports();
|
|
|
|
context_.stylesheet().prepare();
|
|
|
|
} // endDocument
|
|
|
|
|
|
|
|
private:
|
2010-01-11 10:02:17 +01:00
|
|
|
void startStylesheet(const std::string& /* namespaceURI */,
|
2009-04-24 16:54:13 +02:00
|
|
|
const std::string& localName,
|
|
|
|
const std::string& qName,
|
|
|
|
const SAX::Attributes<std::string>& atts)
|
|
|
|
{
|
|
|
|
if(localName != "stylesheet" && localName != "transform")
|
|
|
|
throw SAX::SAXException("Top-level element must be 'stylesheet' or 'transform'.");
|
|
|
|
|
2010-01-11 10:02:17 +01:00
|
|
|
static const ValueRule rules[] = { { "version", true, 0, 0 },
|
|
|
|
{ "extension-element-prefixes", false, 0, 0 },
|
|
|
|
{ "exclude-result-prefixes", false, 0, 0 },
|
|
|
|
{ "id", false, 0, 0 },
|
|
|
|
{ 0, false, 0, 0 } };
|
2009-04-24 16:54:13 +02:00
|
|
|
std::map<std::string, std::string> attributes = gatherAttributes(qName, atts, rules);
|
|
|
|
if(attributes["version"] != StylesheetConstant::Version())
|
|
|
|
throw SAX::SAXException("I'm only a poor version 1.0 XSLT Transformer.");
|
|
|
|
if(!attributes["extension-element-prefixes"].empty())
|
|
|
|
throw SAX::SAXException("Haven't implemented extension-element-prefixes yet");
|
|
|
|
} // startStylesheet
|
|
|
|
|
2009-04-28 09:57:14 +02:00
|
|
|
void startLREAsStylesheet(const std::string& namespaceURI,
|
2009-04-28 21:59:52 +02:00
|
|
|
const std::string& localName,
|
|
|
|
const std::string& qName,
|
|
|
|
const SAX::Attributes<std::string>& atts)
|
2009-04-28 09:57:14 +02:00
|
|
|
{
|
|
|
|
std::string version;
|
|
|
|
for(int a = 0; a != atts.getLength(); ++a)
|
|
|
|
if((StylesheetConstant::NamespaceURI() == atts.getURI(a)) &&
|
2009-04-28 21:59:52 +02:00
|
|
|
("version" == atts.getLocalName(a)))
|
2009-04-28 09:57:14 +02:00
|
|
|
{
|
2009-04-28 21:59:52 +02:00
|
|
|
version = atts.getValue(a);
|
|
|
|
break;
|
2009-04-28 09:57:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(version.empty())
|
|
|
|
throw SAX::SAXException("The source file does not look like a stylesheet.");
|
|
|
|
if(version != StylesheetConstant::Version())
|
|
|
|
throw SAX::SAXException("I'm only a poor version 1.0 XSLT Transformer.");
|
2009-04-28 21:59:52 +02:00
|
|
|
|
|
|
|
Template* lreStylesheet = new Template(context_.xpath_match("/"), "", "", "", context_.precedence());
|
|
|
|
context_.push(lreStylesheet,
|
|
|
|
new LREStylesheetHandler(context_, lreStylesheet),
|
|
|
|
namespaceURI,
|
|
|
|
localName,
|
|
|
|
qName,
|
|
|
|
atts);
|
2009-04-28 09:57:14 +02:00
|
|
|
} // startLREAsStylesheet
|
|
|
|
|
2009-04-24 16:54:13 +02:00
|
|
|
void startXSLTElement(const std::string& namespaceURI,
|
|
|
|
const std::string& localName,
|
|
|
|
const std::string& qName,
|
|
|
|
const SAX::Attributes<std::string>& atts)
|
|
|
|
{
|
|
|
|
if((localName == "import") || (localName == "include"))
|
|
|
|
{
|
|
|
|
include_stylesheet(namespaceURI, localName, qName, atts);
|
|
|
|
return;
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
for(const ChildElement* c = allowedChildren; c->name != 0; ++c)
|
|
|
|
if(c->name == localName)
|
|
|
|
{
|
|
|
|
context_.push(0,
|
|
|
|
c->createHandler(context_),
|
|
|
|
namespaceURI,
|
|
|
|
localName,
|
2009-04-24 20:02:14 +02:00
|
|
|
qName,
|
2009-04-24 16:54:13 +02:00
|
|
|
atts);
|
|
|
|
return;
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
oops(qName);
|
|
|
|
} // startXSLTElement
|
|
|
|
|
2009-04-24 20:02:14 +02:00
|
|
|
void startForeignElement(const std::string& namespaceURI,
|
|
|
|
const std::string& localName,
|
|
|
|
const std::string& qName,
|
|
|
|
const SAX::Attributes<std::string>& atts)
|
|
|
|
{
|
|
|
|
context_.push(0,
|
|
|
|
new ForeignElementHandler(context_),
|
|
|
|
namespaceURI,
|
|
|
|
localName,
|
|
|
|
qName,
|
|
|
|
atts);
|
|
|
|
} // startForeignElement
|
|
|
|
|
2007-07-19 19:01:42 +02:00
|
|
|
void include_stylesheet(const std::string& namespaceURI,
|
|
|
|
const std::string& localName,
|
|
|
|
const std::string& qName,
|
2007-09-05 14:57:07 +02:00
|
|
|
const SAX::Attributes<std::string>& atts)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
includer_.start_include(namespaceURI, localName, qName, atts);
|
|
|
|
} // include_stylesheet
|
|
|
|
|
2009-04-24 16:54:13 +02:00
|
|
|
void oops(const std::string& qName) const
|
|
|
|
{
|
|
|
|
throw SAX::SAXException("xsl:stylesheet does not allow " + qName + " here.");
|
|
|
|
} // oops
|
|
|
|
|
2007-07-19 19:01:42 +02:00
|
|
|
CompilationContext& context_;
|
2007-09-05 14:57:07 +02:00
|
|
|
SAX::DefaultHandler<std::string>* child_;
|
2007-07-19 19:01:42 +02:00
|
|
|
IncludeHandler includer_;
|
|
|
|
bool top_;
|
|
|
|
|
|
|
|
static const ChildElement allowedChildren[];
|
|
|
|
}; // class StylesheetHandler
|
|
|
|
|
|
|
|
const ChildElement StylesheetHandler::allowedChildren[] =
|
|
|
|
{
|
|
|
|
{ "attribute-set", CreateHandler<NotImplementedYetHandler>},
|
|
|
|
{ "decimal-format", CreateHandler<NotImplementedYetHandler>},
|
|
|
|
//"import"
|
|
|
|
//"include"
|
2009-02-16 23:10:00 +01:00
|
|
|
{ "key", CreateHandler<KeyHandler>},
|
2007-07-19 19:01:42 +02:00
|
|
|
{ "namespace-alias", CreateHandler<NamespaceAliasHandler>},
|
|
|
|
{ "output", CreateHandler<OutputHandler>},
|
2009-12-15 00:55:56 +01:00
|
|
|
{ "param", CreateHandler<TopLevelVariableHandler<Param> >},
|
2007-07-19 19:01:42 +02:00
|
|
|
{ "preserve-space", CreateHandler<NotImplementedYetHandler>},
|
|
|
|
{ "strip-space", CreateHandler<NotImplementedYetHandler>},
|
|
|
|
{ "template", CreateHandler<TemplateHandler> },
|
2009-12-15 00:55:56 +01:00
|
|
|
{ "variable", CreateHandler<TopLevelVariableHandler<Variable> > },
|
2007-07-19 19:01:42 +02:00
|
|
|
{ 0, 0 }
|
|
|
|
}; // StylesheetHandler::allowedChildren
|
|
|
|
|
2007-11-22 20:24:18 +01:00
|
|
|
class StylesheetCompiler
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
public:
|
2007-08-23 15:55:06 +02:00
|
|
|
StylesheetCompiler()
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
} // StylesheetCompiler
|
|
|
|
|
|
|
|
~StylesheetCompiler()
|
|
|
|
{
|
|
|
|
} // ~StylesheetCompiler
|
|
|
|
|
2007-09-05 14:57:07 +02:00
|
|
|
std::auto_ptr<Stylesheet> compile(SAX::InputSource<std::string>& source)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
error_ = "";
|
|
|
|
|
2008-11-05 02:33:28 +01:00
|
|
|
std::auto_ptr<CompiledStylesheet> stylesheet(new CompiledStylesheet());
|
2007-08-23 15:55:06 +02:00
|
|
|
|
2008-11-05 02:33:28 +01:00
|
|
|
StylesheetParser parser;
|
|
|
|
CompilationContext context(parser, *stylesheet.get());
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
StylesheetHandler stylesheetHandler(context);
|
2008-11-05 02:33:28 +01:00
|
|
|
parser.setContentHandler(stylesheetHandler);
|
|
|
|
//parser.setErrorHandler(*this);
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
//if(entityResolver_)
|
2008-11-05 02:33:28 +01:00
|
|
|
// parser.setEntityResolver(*entityResolver_);
|
2007-07-19 19:01:42 +02:00
|
|
|
try {
|
2008-11-05 02:33:28 +01:00
|
|
|
parser.parse(source);
|
2007-07-19 19:01:42 +02:00
|
|
|
} // try
|
|
|
|
catch(std::exception& ex)
|
|
|
|
{
|
|
|
|
error_ = ex.what();
|
|
|
|
//std::cerr << "Compilation Failed : " << ex.what() << std::endl;
|
2007-08-23 15:55:06 +02:00
|
|
|
stylesheet.reset();
|
2007-07-19 19:01:42 +02:00
|
|
|
} // catch
|
|
|
|
|
2008-11-05 02:33:28 +01:00
|
|
|
return std::auto_ptr<Stylesheet>(stylesheet.release());
|
2007-07-19 19:01:42 +02:00
|
|
|
} // compile
|
|
|
|
|
|
|
|
const std::string& error() const
|
|
|
|
{
|
|
|
|
return error_;
|
|
|
|
} // error
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string error_;
|
|
|
|
}; // class StylesheetCompiler
|
|
|
|
|
|
|
|
} // namespace XSLT
|
|
|
|
} // namespace Arabica
|
|
|
|
|
|
|
|
#endif // ARABICA_XSLT_STYLESHEETCOMPILER_HPP
|
|
|
|
|