This commit is contained in:
Jez Higgins 2012-11-06 19:29:22 +00:00
parent 3d0806460d
commit efcb81b80c
8 changed files with 110 additions and 101 deletions

View file

@ -57,9 +57,12 @@ public:
} // characters
private:
Output::CDATAElements extractCDATAElements(const string_type& cdata_section_elements) const
typedef typename Output<string_type, string_adaptor>::CDATAElements CDATAElements;
typedef typename Output<string_type, string_adaptor>::Settings Settings;
CDATAElements extractCDATAElements(const string_type& cdata_section_elements) const
{
Output::CDATAElements elements;
CDATAElements elements;
if(cdata_section_elements.empty())
return elements;
@ -78,8 +81,8 @@ private:
} // extractCDATAElements
CompilationContext<string_type, string_adaptor>& context_;
Output::Settings settings_;
Output::CDATAElements cdataElements_;
Settings settings_;
CDATAElements cdataElements_;
}; // class OutputHandler
} // namespace XSLT

View file

@ -25,7 +25,7 @@ class CompiledStylesheet : public Stylesheet
public:
CompiledStylesheet() :
output_(new StreamSink(std::cout)),
output_(new StreamSink<std::string>(std::cout)),
error_output_(&std::cerr)
{
} // CompiledStylesheet
@ -58,7 +58,7 @@ public:
set_parameter(name, Value(new StringValue(value)));
} // set_parameter
virtual void set_output(Sink& sink)
virtual void set_output(Sink<std::string>& sink)
{
output_.reset(sink);
} // set_output
@ -135,7 +135,8 @@ public:
keys_.add(name, key);
} // add_key
void output_settings(const Output::Settings& settings, const Output::CDATAElements& cdata_elements)
void output_settings(const Output<std::string, Arabica::default_string_adaptor<std::string> >::Settings& settings,
const Output<std::string, Arabica::default_string_adaptor<std::string> >::CDATAElements& cdata_elements)
{
output_settings_ = settings;
output_cdata_elements_.insert(cdata_elements.begin(), cdata_elements.end());
@ -328,9 +329,9 @@ private:
mutable std::string current_mode_;
mutable Precedence current_generation_;
Output::Settings output_settings_;
Output::CDATAElements output_cdata_elements_;
SinkHolder output_;
Output<std::string, Arabica::default_string_adaptor<std::string> >::Settings output_settings_;
Output<std::string, Arabica::default_string_adaptor<std::string> >::CDATAElements output_cdata_elements_;
SinkHolder<std::string, Arabica::default_string_adaptor<std::string> > output_;
mutable std::ostream* error_output_;
}; // class CompiledStylesheet

View file

@ -22,7 +22,7 @@ public:
virtual const std::string& name() const = 0;
virtual Arabica::XPath::XPathValue<std::string> value(const DOM::Node<std::string>& node,
ExecutionContext& context,
DOMSink& sink) const = 0;
DOMSink<std::string>& sink) const = 0;
virtual const Precedence& precedence() const = 0;
private:
@ -35,7 +35,7 @@ class ExecutionContext
{
public:
ExecutionContext(const CompiledStylesheet& stylesheet,
Sink& output,
Sink<std::string>& output,
std::ostream& error_output) :
stylesheet_(stylesheet),
sink_(output.asOutput()),
@ -47,7 +47,7 @@ public:
message_sink_.asOutput().set_warning_sink(message_sink_.asOutput());
} // ExecutionContext
ExecutionContext(Sink& output,
ExecutionContext(Sink<std::string>& output,
ExecutionContext& rhs) :
stylesheet_(rhs.stylesheet_),
stack_(rhs.stack_),
@ -63,7 +63,7 @@ public:
const CompiledStylesheet& stylesheet() const { return stylesheet_; }
Output& sink()
Output<std::string, Arabica::default_string_adaptor<std::string> >& sink()
{
return !to_msg_ ? sink_ : message_sink_.asOutput();
} // sink
@ -103,8 +103,8 @@ private:
const CompiledStylesheet& stylesheet_;
VariableStack stack_;
Arabica::XPath::ExecutionContext<std::string> xpathContext_;
Output& sink_;
StreamSink message_sink_;
Output<std::string, Arabica::default_string_adaptor<std::string> >& sink_;
StreamSink<std::string> message_sink_;
int to_msg_;
friend class StackFrame;
@ -149,7 +149,7 @@ private:
} // VariableClosure
const Variable_declaration& var_;
mutable DOMSink sink_;
mutable DOMSink<std::string> sink_;
const DOM::Node<std::string> node_;
mutable ExecutionContext context_;
mutable Arabica::XPath::XPathValue<std::string> value_;

View file

@ -12,10 +12,11 @@ namespace Arabica
namespace XSLT
{
template<class string_type, class string_adaptor>
class Output
{
public:
typedef std::map<std::string, std::string> Settings;
typedef std::map<string_type, string_type> Settings;
typedef std::set<QName> CDATAElements;
protected:
@ -49,13 +50,13 @@ public:
do_end_document();
} // end_document
bool start_element(const std::string& qName, const std::string& namespaceURI)
bool start_element(const string_type& qName, const string_type& namespaceURI)
{
QName en = QName::create(qName, namespaceURI);
return start_element(en.prefix, en.localName, en.namespaceURI);
} // start_element
bool start_element(const std::string& prefix, const std::string& localName, const std::string& namespaceURI)
bool start_element(const string_type& prefix, const string_type& localName, const string_type& namespaceURI)
{
if(is_buffering())
return false;
@ -66,7 +67,7 @@ public:
if(!namespaceURI.empty())
namespaceStack_.declareNamespace(prefix, namespaceURI);
std::string mapped_prefix = namespaceStack_.findPrefix(namespaceURI);
string_type mapped_prefix = namespaceStack_.findPrefix(namespaceURI);
element_stack_.push(QName(mapped_prefix, localName, namespaceURI));
@ -77,13 +78,13 @@ public:
return true;
} // start_element
void end_element(const std::string& qName, const std::string& namespaceURI)
void end_element(const string_type& qName, const string_type& namespaceURI)
{
QName en = QName::create(qName, namespaceURI);
end_element(en.prefix, en.localName, en.namespaceURI);
} // end_element
void end_element(const std::string& /* prefix */, const std::string& localName, const std::string& namespaceURI)
void end_element(const string_type& /* prefix */, const string_type& localName, const string_type& namespaceURI)
{
if(pop_if_buffering())
return;
@ -92,7 +93,7 @@ public:
if(!text_mode_)
{
std::string mapped_prefix = namespaceStack_.findPrefix(namespaceURI);
string_type mapped_prefix = namespaceStack_.findPrefix(namespaceURI);
do_end_element((!mapped_prefix.empty()) ? mapped_prefix + ':' + localName : localName, namespaceURI);
element_stack_.pop();
} // end_element
@ -100,13 +101,13 @@ public:
namespaceStack_.popScope();
} // end_element
void start_attribute(const std::string& qName, const std::string& namespaceURI)
void start_attribute(const string_type& qName, const string_type& namespaceURI)
{
QName qn = QName::create(qName, namespaceURI);
start_attribute(qn.prefix, qn.localName, qn.namespaceURI);
} // start_attribute
void start_attribute(const std::string& prefix, const std::string& localName, const std::string& namespaceURI)
void start_attribute(const string_type& prefix, const string_type& localName, const string_type& namespaceURI)
{
if(push_buffering())
return;
@ -120,8 +121,8 @@ public:
if(!namespaceURI.empty())
namespaceStack_.declareNamespace(prefix, namespaceURI, true);
std::string mapped_prefix = namespaceStack_.findPrefix(namespaceURI);
std::string qName = (!mapped_prefix.empty()) ? mapped_prefix + ':' + localName : localName;
string_type mapped_prefix = namespaceStack_.findPrefix(namespaceURI);
string_type qName = (!mapped_prefix.empty()) ? mapped_prefix + ':' + localName : localName;
atts_.addOrReplaceAttribute(namespaceURI,
localName,
@ -144,10 +145,10 @@ public:
pending_attribute_ = -1;
} // end_attribute
void add_attribute(const std::string& uri,
const std::string& localName,
const std::string& qName,
const std::string& value)
void add_attribute(const string_type& uri,
const string_type& localName,
const string_type& qName,
const string_type& value)
{
if(!pending_element_)
{
@ -158,7 +159,7 @@ public:
atts_.addAttribute(uri, localName, qName, "", value);
} // add_attribute
void characters(const std::string& ch)
void characters(const string_type& ch)
{
if(buffering_)
{
@ -202,14 +203,14 @@ public:
if(!text_mode_)
{
std::string comment = escape(buffer_.str(), "--", "- -");
string_type comment = escape(buffer_.str(), "--", "- -");
if(comment.length() && *(comment.rbegin()) == '-')
comment.append(" ");
do_comment(comment);
} // if ...
} // end_comment
void start_processing_instruction(const std::string& target)
void start_processing_instruction(const string_type& target)
{
if(push_buffering())
return;
@ -226,7 +227,7 @@ public:
if(!text_mode_)
{
std::string data = escape(buffer_.str(), "?>", "? >");
string_type data = escape(buffer_.str(), "?>", "? >");
do_processing_instruction(target_, data);
} // if ...
} // end_processing_instruction
@ -245,21 +246,21 @@ public:
protected:
virtual void do_start_document(const Settings& settings) = 0;
virtual void do_end_document() = 0;
virtual void do_start_element(const std::string& qName, const std::string& namespaceURI, const SAX::Attributes<std::string>& atts) = 0;
virtual void do_end_element(const std::string& qName, const std::string& namespaceURI) = 0;
virtual void do_characters(const std::string& ch) = 0;
virtual void do_start_element(const string_type& qName, const string_type& namespaceURI, const SAX::Attributes<string_type, string_adaptor>& atts) = 0;
virtual void do_end_element(const string_type& qName, const string_type& namespaceURI) = 0;
virtual void do_characters(const string_type& ch) = 0;
virtual void do_start_CDATA() = 0;
virtual void do_end_CDATA() = 0;
virtual void do_comment(const std::string& ch) = 0;
virtual void do_processing_instruction(const std::string& target, const std::string& data) = 0;
virtual void do_comment(const string_type& ch) = 0;
virtual void do_processing_instruction(const string_type& target, const string_type& data) = 0;
virtual void do_disableOutputEscaping(bool disable) = 0;
virtual bool want_namespace_declarations() const = 0;
private:
std::string escape(std::string str, const std::string& t, const std::string& r) const
string_type escape(string_type str, const string_type& t, const string_type& r) const
{
std::string::size_type naughty = str.find(t);
while(naughty != std::string::npos)
string_type::size_type naughty = str.find(t);
while(naughty != string_type::npos)
{
str.replace(naughty, t.length(), r, 0, r.length());
naughty = str.find(t, naughty);
@ -347,7 +348,7 @@ private:
if(n->first == "xml")
continue;
std::string qName = (n->first.empty()) ? "xmlns" : "xmlns:" + n->first;
string_type qName = (n->first.empty()) ? "xmlns" : "xmlns:" + n->first;
atts_.addAttribute("http://www.w3.org/2000/xmlns",
n->first,
qName,
@ -356,7 +357,7 @@ private:
}
} // addNamespaceDeclarations
void warning(const std::string& warning_message)
void warning(const string_type& warning_message)
{
warning_sink_->characters(warning_message);
warning_sink_->characters("\n");
@ -370,8 +371,8 @@ private:
Output* warning_sink_;
CDATAElements cdataElements_;
std::stack<QName> element_stack_;
std::string target_;
SAX::AttributesImpl<std::string, Arabica::default_string_adaptor<std::string> > atts_;
string_type target_;
SAX::AttributesImpl<string_type, string_adaptor> atts_;
std::stringstream buffer_;
NamespaceStack namespaceStack_;
}; // class Output

View file

@ -15,24 +15,26 @@ namespace Arabica
namespace XSLT
{
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
class Sink
{
public:
virtual ~Sink() { }
virtual Output& asOutput() = 0;
virtual Output<string_type, string_adaptor>& asOutput() = 0;
}; // class Sink
template<class string_type, class string_adaptor>
class SinkHolder
{
public:
SinkHolder(Sink* sink) :
SinkHolder(Sink<string_type, string_adaptor>* sink) :
sink_(sink),
owned_(true)
{
} // SinkHolder
SinkHolder(Sink& sink) :
SinkHolder(Sink<string_type, string_adaptor>& sink) :
sink_(&sink),
owned_(false)
{
@ -43,21 +45,21 @@ public:
clear();
} // ~SinkHolder
void reset(Sink* sink)
void reset(Sink<string_type, string_adaptor>* sink)
{
clear();
sink_ = sink;
owned_ = true;
} // assign
void reset(Sink& sink)
void reset(Sink<string_type, string_adaptor>& sink)
{
clear();
sink_ = &sink;
owned_ = false;
} // reset
Sink& get() const
Sink<string_type, string_adaptor>& get() const
{
return *sink_;
} // get
@ -69,7 +71,7 @@ private:
delete sink_;
} // clear
Sink* sink_;
Sink<string_type, string_adaptor>* sink_;
bool owned_;
SinkHolder(const SinkHolder&);
@ -77,7 +79,8 @@ private:
SinkHolder& operator=(const SinkHolder&);
}; // class SinkHolder
class StreamSink : public Sink, private Output
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
class StreamSink : public Sink<string_type, string_adaptor>, private Output<string_type, string_adaptor>
{
public:
StreamSink(std::ostream& stream) :
@ -108,7 +111,7 @@ public:
stream_.flush();
} // ~StreamSink
virtual Output& asOutput() { return *this; }
virtual Output<string_type, string_adaptor>& asOutput() { return *this; }
protected:
void do_start_document(const Settings& settings)
@ -123,9 +126,9 @@ protected:
{
} // do_end_document
void do_start_element(const std::string& qName,
const std::string& /* namespaceURI */,
const SAX::Attributes<std::string>& atts)
void do_start_element(const string_type& qName,
const string_type& /* namespaceURI */,
const SAX::Attributes<string_type, string_adaptor>& atts)
{
if(!seen_root_)
do_decl(qName);
@ -138,15 +141,15 @@ protected:
for(int a = 0; a < atts.getLength(); ++a)
{
stream_ << ' ' << atts.getQName(a) << '=' << '\"';
std::string ch = atts.getValue(a);
string_type ch = atts.getValue(a);
std::for_each(ch.begin(), ch.end(), Arabica::XML::attribute_escaper<char>(stream_));
stream_ << '\"';
}
empty_ = true;
} // do_start_element
void do_end_element(const std::string& qName,
const std::string& /* namespaceURI */)
void do_end_element(const string_type& qName,
const string_type& /* namespaceURI */)
{
if(!seen_root_)
do_decl("");
@ -163,7 +166,7 @@ protected:
empty_ = false;
} // do_end_element
void do_characters(const std::string& ch)
void do_characters(const string_type& ch)
{
close_element_if_empty();
@ -172,7 +175,7 @@ protected:
else if(in_cdata_)
{
size_t breakAt = ch.find("]]>");
if(breakAt == std::string::npos)
if(breakAt == string_type::npos)
{
stream_ << ch;
return;
@ -187,7 +190,7 @@ protected:
do_start_CDATA();
breakAt = ch.find("]]>", breakAt);
}
while(breakAt != std::string::npos);
while(breakAt != string_type::npos);
stream_ << ch.substr(start);
}
else
@ -208,7 +211,7 @@ protected:
stream_ << "]]>";
} // do_end_CDATA
void do_comment(const std::string& ch)
void do_comment(const string_type& ch)
{
close_element_if_empty();
@ -217,8 +220,8 @@ protected:
<< "-->";
} // do_comment
void do_processing_instruction(const std::string& target,
const std::string& data)
void do_processing_instruction(const string_type& target,
const string_type& data)
{
close_element_if_empty();
@ -280,19 +283,19 @@ private:
out_again_ = true;
} // outdent
void do_decl(const std::string& qName)
void do_decl(const string_type& qName)
{
if((setting("method") == "text") || (setting("omit-xml-declaration") == "yes"))
return;
{
std::string version = setting("version");
string_type version = setting("version");
if(version.empty())
version = "1.0";
stream_ << "<?xml version=\"" << version << "\"";
}
{
std::string s = setting("standalone");
string_type s = setting("standalone");
if(!s.empty())
stream_ << " standalone=\"" << s << "\"";
}
@ -300,8 +303,8 @@ private:
if(!qName.empty())
{
std::string pub = setting("doctype-public");
std::string sys = setting("doctype-system");
string_type pub = setting("doctype-public");
string_type sys = setting("doctype-system");
if(!sys.empty())
{
@ -315,7 +318,7 @@ private:
seen_root_ = true;
} // do_decl
std::string setting(const std::string& name)
string_type setting(const string_type& name)
{
Settings::const_iterator i = settings_.find(name);
if(i == settings_.end())
@ -336,7 +339,8 @@ private:
StreamSink& operator=(const StreamSink&);
}; // class StreamSink
class DOMSink : public Sink, private Output
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
class DOMSink : public Sink<string_type, string_adaptor>, private Output<string_type, string_adaptor>
{
public:
DOMSink() :
@ -350,7 +354,7 @@ public:
} // ~DOMSink
virtual Output& asOutput() { return *this; }
DOM::Node<std::string> node() const { return documentFrag_; }
DOM::Node<string_type, string_adaptor> node() const { return documentFrag_; }
protected:
void do_start_document(const Settings& settings)
@ -365,9 +369,9 @@ protected:
{
} // do_end_document
void do_characters(const std::string& ch)
void do_characters(const string_type& ch)
{
DOM::Node<std::string> lc = current().getLastChild();
DOM::Node<string_type> lc = current().getLastChild();
if(lc == 0 || lc.getNodeType() != DOM::Node_base::TEXT_NODE)
current().appendChild(document().createTextNode(ch));
else
@ -380,18 +384,18 @@ protected:
void do_end_CDATA()
{
DOM::Node<std::string> lc = current().getLastChild();
DOM::Node<string_type> lc = current().getLastChild();
if(lc.getNodeType() == DOM::Node_base::TEXT_NODE)
current().replaceChild(document().createCDATASection(lc.getNodeValue()), lc);
} // do_end_CDATA
void do_comment(const std::string& ch)
void do_comment(const string_type& ch)
{
current().appendChild(document().createComment(ch));
} // do_comment
void do_processing_instruction(const std::string& target,
const std::string& data)
void do_processing_instruction(const string_type& target,
const string_type& data)
{
current().appendChild(document().createProcessingInstruction(target, data));
} // do_processing_instruction
@ -400,12 +404,12 @@ protected:
bool want_namespace_declarations() const { return false; }
void do_start_element(const std::string& qName,
const std::string& namespaceURI,
const SAX::Attributes<std::string>& atts)
void do_start_element(const string_type& qName,
const string_type& namespaceURI,
const SAX::Attributes<string_type, string_adaptor>& atts)
{
indent();
DOM::Element<std::string> elem = document().createElementNS(namespaceURI, qName);
DOM::Element<string_type, string_adaptor> elem = document().createElementNS(namespaceURI, qName);
current().appendChild(elem);
// attributes here
@ -415,25 +419,25 @@ protected:
current_ = elem;
} // do_start_element
void do_end_element(const std::string& /* qName */,
const std::string& /* namespaceURI */)
void do_end_element(const string_type& /* qName */,
const string_type& /* namespaceURI */)
{
outdent();
current_ = current_.getParentNode();
} // do_end_element
private:
DOM::Document<std::string>& document()
DOM::Document<string_type>& document()
{
if(document_ != 0)
return document_;
DOM::DOMImplementation<std::string> di = SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
DOM::DOMImplementation<string_type, string_adaptor> di = SimpleDOM::DOMImplementation<string_type, string_adaptor>::getDOMImplementation();
document_ = di.createDocument("", "", 0);
return document_;
} // document
DOM::Node<std::string>& current()
DOM::Node<string_type>& current()
{
if(current_ != 0)
return current_;
@ -448,11 +452,11 @@ private:
if(indent_ == -1)
return;
std::string sps;
string_type sps;
if(indent_ != 0)
{
sps += '\n';
std::fill_n(std::back_inserter<std::string>(sps), indent_, ' ');
std::fill_n(std::back_inserter<string_type>(sps), indent_, ' ');
do_characters(sps);
} // if ...
@ -473,9 +477,9 @@ private:
out_again_ = true;
} // outdent
DOM::Document<std::string> document_;
DOM::DocumentFragment<std::string> documentFrag_;
DOM::Node<std::string> current_;
DOM::Document<string_type, string_adaptor> document_;
DOM::DocumentFragment<string_type, string_adaptor> documentFrag_;
DOM::Node<string_type, string_adaptor> current_;
int indent_;
bool out_again_;

View file

@ -9,7 +9,7 @@ namespace XSLT
#include <string>
#include <iostream>
#include <DOM/Node.hpp>
class Sink;
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> > class Sink;
class Stylesheet
{
@ -21,7 +21,7 @@ public:
virtual void set_parameter(const std::string& name, const char* value) = 0;
virtual void set_parameter(const std::string& name, const std::string& value) = 0;
virtual void set_output(Sink& sink) = 0;
virtual void set_output(Sink<std::string>& sink) = 0;
virtual void set_error_output(std::ostream& os) = 0;

View file

@ -30,7 +30,7 @@ public:
virtual const string_type& name() const { return name_; }
virtual Arabica::XPath::XPathValue<string_type, string_adaptor> value(const DOM::Node<string_type, string_adaptor>& /* node */,
ExecutionContext& /* context */,
DOMSink& /* sink */) const
DOMSink<string_type, string_adaptor>& /* sink */) const
{
return value_;
} // value

View file

@ -30,7 +30,7 @@ public:
virtual Arabica::XPath::XPathValue<std::string> value(const DOM::Node<std::string>& node,
ExecutionContext& context,
DOMSink& sink) const
DOMSink<std::string>& sink) const
{
if(select_)
return select_->evaluate(node, context.xpathContext());