arabica/include/XSLT/impl/xslt_compilation_context.hpp

253 lines
7.7 KiB
C++
Raw Normal View History

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>
#include "xslt_stylesheet_parser.hpp"
#include "xslt_functions.hpp"
2007-07-19 19:01:42 +02:00
namespace Arabica
{
namespace XSLT
{
class CompiledStylesheet;
2007-07-19 19:01:42 +02:00
class ItemContainer;
class CompilationContext :
private Arabica::XPath::FunctionResolver<std::string>,
private Arabica::XPath::NamespaceContext<std::string, Arabica::default_string_adaptor<std::string> >
2007-07-19 19:01:42 +02:00
{
public:
CompilationContext(StylesheetParser& parser,
CompiledStylesheet& stylesheet) :
2007-07-19 19:01:42 +02:00
parser_(parser),
stylesheet_(stylesheet),
autoNs_(1),
current_allowed_(false),
precedence_(Precedence::InitialPrecedence())
2007-07-19 19:01:42 +02:00
{
xpath_.setNamespaceContext(*this);
xpath_.setFunctionResolver(*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
void root(SAX::DefaultHandler<std::string>& root)
2007-07-19 19:01:42 +02:00
{
handlerStack_.push(&root);
} // root
StylesheetParser& parser() const { return parser_; }
Arabica::XPath::XPathExpressionPtr<std::string> xpath_expression(const std::string& expr) const { return xpath_.compile_expr(expr); }
std::vector<Arabica::XPath::MatchExpr<std::string> > xpath_match(const std::string& match) const
{
DisallowCurrent guard(current_allowed_);
return xpath_.compile_match(match);
} // xpath_match
Arabica::XPath::XPathExpressionPtr<std::string> xpath_attribute_value_template(const std::string& expr) const { return xpath_.compile_attribute_value_template(expr); }
CompiledStylesheet& stylesheet() const { return stylesheet_; }
2007-07-19 19:01:42 +02:00
XML::QualifiedName<std::string> processElementQName(const std::string& qName) const
{
return parser_.processElementQName(qName);
} // processElementQName
XML::QualifiedName<std::string> processInternalQName(const std::string& qName) const
2007-07-19 19:01:42 +02:00
{
return parser_.processInternalQName(qName);
} // processInternalQName
2007-07-19 19:01:42 +02:00
std::string makeAbsolute(const std::string& href) const
{
return parser_.makeAbsolute(href);
2007-07-19 19:01:42 +02:00
} // makeAbsolute
std::string setBase(const std::string& href) const
{
return parser_.setBase(href);
} // setBase
std::string currentBase() const
{
return parser_.currentBase();
} // currentBase
2007-07-19 19:01:42 +02:00
void push(ItemContainer* parent,
SAX::DefaultHandler<std::string>* newHandler,
2007-07-19 19:01:42 +02:00
const std::string& namespaceURI,
const std::string& localName,
const std::string& qName,
const SAX::Attributes<std::string>& atts)
2007-07-19 19:01:42 +02:00
{
parentStack_.push(parent);
handlerStack_.push(newHandler);
parser_.setContentHandler(*newHandler);
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
ItemContainer& parentContainer() const
{
return *parentStack_.top();
} // parentContainer
SAX::ContentHandler<std::string>& parentHandler() const
2007-07-19 19:01:42 +02:00
{
parser_.setContentHandler(*handlerStack_.top());
return parser_.contentHandler();
2007-07-19 19:01:42 +02:00
} // parentHandler
std::map<std::string, std::string> inScopeNamespaces() const
{
return parser_.inScopeNamespaces();
} // inScopeNamespaces
void addNamespaceAlias(const std::string& stylesheet_namespace,
const std::string& result_prefix,
const std::string& result_namespace)
{
namespaceRemap_[stylesheet_namespace] = std::make_pair(result_prefix, result_namespace);
} // addNamespaceAlias
bool isRemapped(const std::string& namespaceURI) const
{
return namespaceRemap_.find(namespaceURI) != namespaceRemap_.end();
} // isRemapped
const std::pair<std::string, std::string>& remappedNamespace(const std::string& namespaceURI)
{
return namespaceRemap_[namespaceURI];
} // remappedNamespace
std::string autoNamespacePrefix() const
{
std::ostringstream ss;
ss << "auto-ns" << autoNs_++;
return ss.str();
} // autoNamespacePrefix
void set_precedence(const Precedence& prec)
{
precedence_ = prec;
} // set_precedence
Precedence next_precedence()
{
return precedence_.next_generation();
} // next_precedence
const Precedence& precedence() const
{
return precedence_;
} // precedence
2007-07-19 19:01:42 +02:00
private:
// FunctionResolver
virtual Arabica::XPath::XPathFunction<std::string>* resolveFunction(
const std::string& namespace_uri,
const std::string& name,
const std::vector<Arabica::XPath::XPathExpression<std::string> >& argExprs) const
{
if(!namespace_uri.empty())
return new UndefinedFunction(namespace_uri, name, argExprs);
// document
if(name == "document")
return new DocumentFunction(parser_.currentBase(), argExprs);
// key
2009-02-18 09:37:16 +01:00
if(name == "key")
return new KeyFunction(stylesheet_.keys(), parser_.inScopeNamespaces(), argExprs);
// format-number
// current
if((name == "current") && (current_allowed_))
return new CurrentFunction(argExprs);
// unparsed-entity-uri
//if(name == "unparsed-entity-uri")
// return new UnparsedEntityUriFunction(argExprs);
// generate-id
2008-10-27 20:13:47 +01:00
if(name == "generate-id")
return new GenerateIdFunction(argExprs);
if(name == "system-property")
return new SystemPropertyFunction(argExprs);
2007-12-25 23:23:25 +01:00
// element-available
if(name == "element-available")
{
std::vector<std::pair<std::string, std::string> > dummy;
return new ElementAvailableFunction(dummy, parser_.inScopeNamespaces(), argExprs);
}
2007-12-25 23:23:25 +01:00
// function-available
if(name == "function-available")
return new FunctionAvailableFunction(validNames(), parser_.inScopeNamespaces(), argExprs);
return 0;
} // resolveFunction
virtual std::vector<std::pair<std::string, std::string> > validNames() const
{
static const char* functionNames[] = { "document", "key", /* format-number, */ "current",
/* unparsed-entity-uri, */ "generate-id", "system-property",
/* element-available, */ "function-available", 0 };
std::vector<std::pair<std::string,std::string> > names;
for(int i = 0; functionNames[i] != 0; ++i)
names.push_back(std::make_pair("", functionNames[i]));
return names;
} // validNames
// NamespaceContext
virtual std::string namespaceURI(const std::string& prefix) const
{
return parser_.namespaceURI(prefix);
} // namespaceURI
2007-07-19 19:01:42 +02:00
typedef std::pair<std::string, std::string> Namespace;
StylesheetParser& parser_;
CompiledStylesheet& stylesheet_;
2010-01-10 22:25:35 +01:00
mutable int autoNs_;
mutable bool current_allowed_;
Precedence precedence_;
Arabica::XPath::XPath<std::string> xpath_;
std::stack<SAX::DefaultHandler<std::string>*> handlerStack_;
2007-07-19 19:01:42 +02:00
std::stack<ItemContainer*> parentStack_;
std::map<std::string, Namespace> namespaceRemap_;
CompilationContext(const CompilationContext&);
class DisallowCurrent
{
public:
DisallowCurrent(bool& allow) : allow_(allow) { allow_ = false; }
~DisallowCurrent() { allow_ = true; }
private:
bool& allow_;
}; // DisallowCurrent
2007-07-19 19:01:42 +02:00
}; // class CompilationContext
} // namespace XSLT
} // namespace Arabica
#endif // ARABICA_XSLT_COMPILATION_CONTEXT