2007-07-19 19:01:42 +02:00
|
|
|
#ifndef ARABICA_XSLT_COMPILATION_CONTEXT
|
|
|
|
#define ARABICA_XSLT_COMPILATION_CONTEXT
|
|
|
|
|
2007-09-05 00:55:47 +02:00
|
|
|
#include <SAX/XMLReader.hpp>
|
|
|
|
#include <SAX/helpers/DefaultHandler.hpp>
|
2008-08-01 20:20:28 +02:00
|
|
|
#include <XML/strings.hpp>
|
2007-07-19 19:01:42 +02:00
|
|
|
#include <XPath/XPath.hpp>
|
|
|
|
#include <stack>
|
|
|
|
|
2007-08-22 14:38:20 +02:00
|
|
|
#include "xslt_stylesheet_parser.hpp"
|
2007-11-22 20:24:18 +01:00
|
|
|
#include "xslt_functions.hpp"
|
2007-08-22 14:38:20 +02:00
|
|
|
|
2007-07-19 19:01:42 +02:00
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XSLT
|
|
|
|
{
|
2012-11-06 21:03:15 +01:00
|
|
|
template<class string_type, class string_adaptor> class CompiledStylesheet;
|
2012-11-08 17:18:49 +01:00
|
|
|
template<class string_type, class string_adaptor> class ItemContainer;
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
|
2007-11-22 20:24:18 +01:00
|
|
|
class CompilationContext :
|
2012-11-02 22:01:15 +01:00
|
|
|
private Arabica::XPath::FunctionResolver<string_type, string_adaptor>,
|
|
|
|
private Arabica::XPath::NamespaceContext<string_type, string_adaptor>,
|
|
|
|
private Arabica::XPath::DefaultVariableCompileTimeResolver<string_type, string_adaptor>
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2010-10-10 00:10:35 +02:00
|
|
|
private:
|
2012-11-02 22:01:15 +01:00
|
|
|
typedef Arabica::XPath::DefaultVariableCompileTimeResolver<string_type, string_adaptor> CTVariableResolverT;
|
2012-11-12 22:46:08 +01:00
|
|
|
typedef StylesheetConstant<string_type, string_adaptor> SC;
|
2010-10-10 00:10:35 +02:00
|
|
|
|
2007-07-19 19:01:42 +02:00
|
|
|
public:
|
2012-11-02 22:01:15 +01:00
|
|
|
typedef StylesheetParser<string_type, string_adaptor> StylesheetParserT;
|
2012-11-06 21:03:15 +01:00
|
|
|
typedef CompiledStylesheet<string_type, string_adaptor> CompiledStylesheetT;
|
2012-11-02 22:01:15 +01:00
|
|
|
typedef SAX::DefaultHandler<string_type, string_adaptor> DefaultHandlerT;
|
|
|
|
typedef SAX::ContentHandler<string_type, string_adaptor> ContentHandlerT;
|
|
|
|
typedef SAX::Attributes<string_type, string_adaptor> AttributesT;
|
|
|
|
typedef Arabica::XPath::XPathExpressionPtr<string_type, string_adaptor> XPathExpressionPtrT;
|
|
|
|
typedef Arabica::XPath::MatchExpr<string_type, string_adaptor> MatchExprT;
|
|
|
|
typedef XML::QualifiedName<string_type, string_adaptor> QualifiedNameT;
|
|
|
|
|
|
|
|
|
|
|
|
CompilationContext(StylesheetParserT& parser,
|
2012-11-06 21:03:15 +01:00
|
|
|
CompiledStylesheetT& stylesheet) :
|
2007-07-19 19:01:42 +02:00
|
|
|
parser_(parser),
|
|
|
|
stylesheet_(stylesheet),
|
2007-11-22 20:24:18 +01:00
|
|
|
autoNs_(1),
|
2008-11-25 13:27:33 +01:00
|
|
|
current_allowed_(false),
|
2010-10-10 00:10:35 +02:00
|
|
|
variables_allowed_(true),
|
2008-11-25 13:27:33 +01:00
|
|
|
precedence_(Precedence::InitialPrecedence())
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2007-11-22 20:24:18 +01:00
|
|
|
xpath_.setNamespaceContext(*this);
|
|
|
|
xpath_.setFunctionResolver(*this);
|
2010-10-10 00:10:35 +02:00
|
|
|
xpath_.setVariableCompileTimeResolver(*this);
|
2007-07-19 19:01:42 +02:00
|
|
|
} // CompilationContext
|
|
|
|
|
|
|
|
~CompilationContext()
|
|
|
|
{
|
|
|
|
// delete any left over - will only be the case if unwinding
|
|
|
|
while(handlerStack_.size() > 1)
|
|
|
|
{
|
|
|
|
delete handlerStack_.top();
|
|
|
|
handlerStack_.pop();
|
|
|
|
} // while ...
|
|
|
|
} // ~CompilationContext
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
void root(DefaultHandlerT& root)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
handlerStack_.push(&root);
|
|
|
|
} // root
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
StylesheetParserT& parser() const { return parser_; }
|
|
|
|
XPathExpressionPtrT xpath_expression(const string_type& expr) const { return xpath_.compile_expr(expr); }
|
|
|
|
XPathExpressionPtrT xpath_expression_no_variables(const string_type& expr) const
|
2010-10-10 00:10:35 +02:00
|
|
|
{
|
|
|
|
Disallow variables(variables_allowed_);
|
|
|
|
return xpath_expression(expr);
|
|
|
|
} // xpath_expression_no_variables
|
2012-11-02 22:01:15 +01:00
|
|
|
std::vector<MatchExprT> xpath_match(const string_type& match) const
|
2007-11-22 20:24:18 +01:00
|
|
|
{
|
2010-10-10 00:10:35 +02:00
|
|
|
Disallow current(current_allowed_);
|
2007-11-22 20:24:18 +01:00
|
|
|
return xpath_.compile_match(match);
|
|
|
|
} // xpath_match
|
2012-11-21 12:12:35 +01:00
|
|
|
std::vector<Arabica::XPath::MatchExpr<string_type, string_adaptor> > xpath_match_no_variables(const string_type& match) const
|
2010-10-10 00:10:35 +02:00
|
|
|
{
|
|
|
|
Disallow variables(variables_allowed_);
|
|
|
|
return xpath_match(match);
|
|
|
|
} // xpath_match_no_variables
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
XPathExpressionPtrT xpath_attribute_value_template(const string_type& expr) const { return xpath_.compile_attribute_value_template(expr); }
|
2012-11-06 21:03:15 +01:00
|
|
|
CompiledStylesheetT& stylesheet() const { return stylesheet_; }
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
QualifiedNameT processElementQName(const string_type& qName) const
|
2009-04-07 14:39:31 +02:00
|
|
|
{
|
|
|
|
return parser_.processElementQName(qName);
|
|
|
|
} // processElementQName
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
QualifiedNameT processInternalQName(const string_type& qName) const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2009-02-24 13:21:35 +01:00
|
|
|
return parser_.processInternalQName(qName);
|
2008-08-05 23:03:33 +02:00
|
|
|
} // processInternalQName
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
string_type makeAbsolute(const string_type& href) const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2007-08-22 14:38:20 +02:00
|
|
|
return parser_.makeAbsolute(href);
|
2007-07-19 19:01:42 +02:00
|
|
|
} // makeAbsolute
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
string_type setBase(const string_type& href) const
|
2007-08-24 14:37:32 +02:00
|
|
|
{
|
|
|
|
return parser_.setBase(href);
|
|
|
|
} // setBase
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
string_type currentBase() const
|
2008-12-29 23:29:04 +01:00
|
|
|
{
|
|
|
|
return parser_.currentBase();
|
|
|
|
} // currentBase
|
|
|
|
|
2012-11-08 17:18:49 +01:00
|
|
|
void push(ItemContainer<string_type, string_adaptor>* parent,
|
2012-11-02 22:01:15 +01:00
|
|
|
DefaultHandlerT* newHandler,
|
|
|
|
const string_type& namespaceURI,
|
|
|
|
const string_type& localName,
|
|
|
|
const string_type& qName,
|
|
|
|
const AttributesT& atts)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
parentStack_.push(parent);
|
|
|
|
handlerStack_.push(newHandler);
|
|
|
|
parser_.setContentHandler(*newHandler);
|
2009-04-24 20:02:14 +02:00
|
|
|
newHandler->startElement(namespaceURI, localName, qName, atts);
|
2007-07-19 19:01:42 +02:00
|
|
|
} // push
|
|
|
|
|
|
|
|
void pop()
|
|
|
|
{
|
|
|
|
parentStack_.pop();
|
|
|
|
delete handlerStack_.top();
|
|
|
|
handlerStack_.pop();
|
|
|
|
parser_.setContentHandler(*handlerStack_.top());
|
|
|
|
} // pop
|
|
|
|
|
2012-11-08 17:18:49 +01:00
|
|
|
ItemContainer<string_type, string_adaptor>& parentContainer() const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
return *parentStack_.top();
|
|
|
|
} // parentContainer
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
ContentHandlerT& parentHandler() const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2007-08-24 14:37:32 +02:00
|
|
|
parser_.setContentHandler(*handlerStack_.top());
|
|
|
|
return parser_.contentHandler();
|
2007-07-19 19:01:42 +02:00
|
|
|
} // parentHandler
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
std::map<string_type, string_type> inScopeNamespaces() const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
return parser_.inScopeNamespaces();
|
|
|
|
} // inScopeNamespaces
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
void addNamespaceAlias(const string_type& stylesheet_namespace,
|
|
|
|
const string_type& result_prefix,
|
|
|
|
const string_type& result_namespace)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
namespaceRemap_[stylesheet_namespace] = std::make_pair(result_prefix, result_namespace);
|
|
|
|
} // addNamespaceAlias
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
bool isRemapped(const string_type& namespaceURI) const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
return namespaceRemap_.find(namespaceURI) != namespaceRemap_.end();
|
|
|
|
} // isRemapped
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
const std::pair<string_type, string_type>& remappedNamespace(const string_type& namespaceURI)
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
|
|
|
return namespaceRemap_[namespaceURI];
|
|
|
|
} // remappedNamespace
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
string_type autoNamespacePrefix() const
|
2007-07-19 19:01:42 +02:00
|
|
|
{
|
2012-11-12 22:46:08 +01:00
|
|
|
std::basic_ostringstream<typename string_adaptor::value_type> ss;
|
|
|
|
ss << SC::auto_ns << autoNs_++;
|
2012-11-21 07:59:40 +01:00
|
|
|
return string_adaptor::construct(ss.str());
|
2007-07-19 19:01:42 +02:00
|
|
|
} // autoNamespacePrefix
|
|
|
|
|
2008-11-25 13:27:33 +01:00
|
|
|
void set_precedence(const Precedence& prec)
|
2008-11-19 18:26:07 +01:00
|
|
|
{
|
2008-11-25 13:27:33 +01:00
|
|
|
precedence_ = prec;
|
|
|
|
} // set_precedence
|
2008-11-19 18:26:07 +01:00
|
|
|
|
2008-11-25 13:27:33 +01:00
|
|
|
Precedence next_precedence()
|
2008-11-19 18:26:07 +01:00
|
|
|
{
|
2008-11-25 13:27:33 +01:00
|
|
|
return precedence_.next_generation();
|
|
|
|
} // next_precedence
|
2008-11-25 00:11:22 +01:00
|
|
|
|
2008-11-19 18:26:07 +01:00
|
|
|
const Precedence& precedence() const
|
|
|
|
{
|
2008-11-25 13:27:33 +01:00
|
|
|
return precedence_;
|
2008-11-19 18:26:07 +01:00
|
|
|
} // precedence
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
private:
|
2012-11-21 12:12:35 +01:00
|
|
|
virtual Arabica::XPath::XPathExpression_impl<string_type, string_adaptor>*
|
2012-11-02 22:01:15 +01:00
|
|
|
compileVariable(const string_type& namespace_uri, const string_type& name) const
|
2010-10-10 00:10:35 +02:00
|
|
|
{
|
|
|
|
if(!variables_allowed_)
|
|
|
|
return 0;
|
|
|
|
return CTVariableResolverT::compileVariable(namespace_uri, name);
|
|
|
|
} // compileVariable
|
|
|
|
|
2007-11-22 20:24:18 +01:00
|
|
|
// FunctionResolver
|
2012-11-21 12:12:35 +01:00
|
|
|
virtual Arabica::XPath::XPathFunction<string_type, string_adaptor>* resolveFunction(
|
2012-11-02 22:01:15 +01:00
|
|
|
const string_type& namespace_uri,
|
|
|
|
const string_type& name,
|
2012-11-21 12:12:35 +01:00
|
|
|
const std::vector<Arabica::XPath::XPathExpression<string_type, string_adaptor> >& argExprs) const
|
2007-11-22 20:24:18 +01:00
|
|
|
{
|
2012-11-21 07:59:40 +01:00
|
|
|
if(!string_adaptor::empty(namespace_uri))
|
2012-11-08 22:48:35 +01:00
|
|
|
return new UndefinedFunction<string_type, string_adaptor>(namespace_uri, name, argExprs);
|
2007-11-22 20:24:18 +01:00
|
|
|
|
|
|
|
// document
|
2012-11-12 22:46:08 +01:00
|
|
|
if(name == DocumentFunction<string_type, string_adaptor>::name())
|
2012-11-08 22:48:35 +01:00
|
|
|
return new DocumentFunction<string_type, string_adaptor>(parser_.currentBase(), argExprs);
|
2007-11-22 20:24:18 +01:00
|
|
|
// key
|
2012-11-12 22:46:08 +01:00
|
|
|
if(name == KeyFunction<string_type, string_adaptor>::name())
|
2012-11-08 22:48:35 +01:00
|
|
|
return new KeyFunction<string_type, string_adaptor>(stylesheet_.keys(), parser_.inScopeNamespaces(), argExprs);
|
2007-11-22 20:24:18 +01:00
|
|
|
// format-number
|
2010-02-20 22:56:47 +01:00
|
|
|
// current
|
2012-11-12 22:46:08 +01:00
|
|
|
if((name == CurrentFunction<string_type, string_adaptor>::name()) && (current_allowed_))
|
2012-11-08 22:48:35 +01:00
|
|
|
return new CurrentFunction<string_type, string_adaptor>(argExprs);
|
2007-11-22 20:24:18 +01:00
|
|
|
// unparsed-entity-uri
|
2012-11-16 10:17:39 +01:00
|
|
|
//if(name == UnparsedEntityUriFunction<string_type, string_adaptor>::name())
|
|
|
|
// return new UnparsedEntityUriFunction<string_type, string_adaptor>(argExprs);
|
2007-11-22 20:24:18 +01:00
|
|
|
// generate-id
|
2012-11-12 22:46:08 +01:00
|
|
|
if(name == GenerateIdFunction<string_type, string_adaptor>::name())
|
2012-11-08 22:48:35 +01:00
|
|
|
return new GenerateIdFunction<string_type, string_adaptor>(argExprs);
|
2012-11-12 22:46:08 +01:00
|
|
|
if(name == SystemPropertyFunction<string_type, string_adaptor>::name())
|
2012-11-08 22:48:35 +01:00
|
|
|
return new SystemPropertyFunction<string_type, string_adaptor>(argExprs);
|
2007-12-25 23:23:25 +01:00
|
|
|
// element-available
|
2012-11-12 22:46:08 +01:00
|
|
|
if(name == ElementAvailableFunction<string_type, string_adaptor>::name())
|
2010-02-21 19:35:58 +01:00
|
|
|
{
|
2012-11-02 22:01:15 +01:00
|
|
|
std::vector<std::pair<string_type, string_type> > dummy;
|
2012-11-08 22:48:35 +01:00
|
|
|
return new ElementAvailableFunction<string_type, string_adaptor>(dummy, parser_.inScopeNamespaces(), argExprs);
|
2010-02-21 19:35:58 +01:00
|
|
|
}
|
2007-12-25 23:23:25 +01:00
|
|
|
// function-available
|
2012-11-12 22:46:08 +01:00
|
|
|
if(name == FunctionAvailableFunction<string_type, string_adaptor>::name())
|
2012-11-08 22:48:35 +01:00
|
|
|
return new FunctionAvailableFunction<string_type, string_adaptor>(validNames(), parser_.inScopeNamespaces(), argExprs);
|
2010-02-20 22:56:47 +01:00
|
|
|
|
2007-11-22 20:24:18 +01:00
|
|
|
return 0;
|
|
|
|
} // resolveFunction
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
virtual std::vector<std::pair<string_type, string_type> > validNames() const
|
2010-02-20 14:03:22 +01:00
|
|
|
{
|
2012-11-12 22:46:08 +01:00
|
|
|
static string_type functionNames[] = { DocumentFunction<string_type, string_adaptor>::name(),
|
|
|
|
KeyFunction<string_type, string_adaptor>::name(),
|
|
|
|
/* format-number, */
|
|
|
|
CurrentFunction<string_type, string_adaptor>::name(),
|
|
|
|
UnparsedEntityUriFunction<string_type, string_adaptor>::name(),
|
|
|
|
GenerateIdFunction<string_type, string_adaptor>::name(),
|
|
|
|
SystemPropertyFunction<string_type, string_adaptor>::name(),
|
|
|
|
ElementAvailableFunction<string_type, string_adaptor>::name(),
|
|
|
|
FunctionAvailableFunction<string_type, string_adaptor>::name(),
|
|
|
|
string_adaptor::empty_string() };
|
2010-02-20 22:56:47 +01:00
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
std::vector<std::pair<string_type,string_type> > names;
|
2010-02-20 22:56:47 +01:00
|
|
|
|
2012-11-12 22:46:08 +01:00
|
|
|
for(int i = 0; functionNames[i] != string_adaptor::empty_string(); ++i)
|
|
|
|
names.push_back(std::make_pair(string_adaptor::empty_string(), functionNames[i]));
|
2010-02-20 22:56:47 +01:00
|
|
|
|
|
|
|
return names;
|
|
|
|
} // validNames
|
2010-02-20 14:03:22 +01:00
|
|
|
|
2007-11-22 20:24:18 +01:00
|
|
|
// NamespaceContext
|
2012-11-02 22:01:15 +01:00
|
|
|
virtual string_type namespaceURI(const string_type& prefix) const
|
2007-11-22 20:24:18 +01:00
|
|
|
{
|
|
|
|
return parser_.namespaceURI(prefix);
|
|
|
|
} // namespaceURI
|
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
typedef std::pair<string_type, string_type> Namespace;
|
2007-07-19 19:01:42 +02:00
|
|
|
|
2012-11-02 22:01:15 +01:00
|
|
|
StylesheetParser<string_type, string_adaptor>& parser_;
|
2012-11-06 21:03:15 +01:00
|
|
|
CompiledStylesheetT& stylesheet_;
|
2010-01-10 22:25:35 +01:00
|
|
|
mutable int autoNs_;
|
|
|
|
mutable bool current_allowed_;
|
2010-10-10 00:10:35 +02:00
|
|
|
mutable bool variables_allowed_;
|
2010-01-10 22:25:35 +01:00
|
|
|
Precedence precedence_;
|
2012-11-21 12:12:35 +01:00
|
|
|
Arabica::XPath::XPath<string_type, string_adaptor> xpath_;
|
|
|
|
std::stack<SAX::DefaultHandler<string_type, string_adaptor>*> handlerStack_;
|
2012-11-08 17:18:49 +01:00
|
|
|
std::stack<ItemContainer<string_type, string_adaptor>*> parentStack_;
|
2012-11-02 22:01:15 +01:00
|
|
|
std::map<string_type, Namespace> namespaceRemap_;
|
2007-07-19 19:01:42 +02:00
|
|
|
|
|
|
|
CompilationContext(const CompilationContext&);
|
2007-11-22 20:24:18 +01:00
|
|
|
|
2010-10-10 00:10:35 +02:00
|
|
|
class Disallow
|
2007-11-22 20:24:18 +01:00
|
|
|
{
|
|
|
|
public:
|
2010-10-10 00:10:35 +02:00
|
|
|
Disallow(bool& allow) : allow_(allow) { allow_ = false; }
|
|
|
|
~Disallow() { allow_ = true; }
|
2007-11-22 20:24:18 +01:00
|
|
|
private:
|
|
|
|
bool& allow_;
|
|
|
|
}; // DisallowCurrent
|
2007-07-19 19:01:42 +02:00
|
|
|
}; // class CompilationContext
|
|
|
|
|
|
|
|
} // namespace XSLT
|
|
|
|
} // namespace Arabica
|
|
|
|
|
|
|
|
#endif // ARABICA_XSLT_COMPILATION_CONTEXT
|
|
|
|
|