redirect to DOMSink when evaluating variables. This wasn't being done for ResolvedVariables and so everything was exploding.

This commit is contained in:
jez 2009-12-14 14:20:12 +00:00
parent 8890b8e450
commit 17e93705ae
6 changed files with 221 additions and 196 deletions

View file

@ -21,8 +21,7 @@ protected:
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;
ExecutionContext& context) const = 0;
virtual const Precedence& precedence() const = 0;
private:
@ -38,20 +37,19 @@ public:
Sink& output,
std::ostream& error_output) :
stylesheet_(stylesheet),
sink_(output.asOutput()),
sink_(&output.asOutput()),
message_sink_(error_output),
to_msg_(0)
{
xpathContext_.setVariableResolver(stack_);
sink_.set_warning_sink(message_sink_.asOutput());
sink_->set_warning_sink(message_sink_.asOutput());
message_sink_.asOutput().set_warning_sink(message_sink_.asOutput());
} // ExecutionContext
ExecutionContext(Sink& output,
ExecutionContext& rhs) :
ExecutionContext(ExecutionContext& rhs) :
stylesheet_(rhs.stylesheet_),
stack_(rhs.stack_),
sink_(output.asOutput()),
sink_(rhs.sink_),
message_sink_(rhs.message_sink_),
to_msg_(false)
{
@ -65,10 +63,16 @@ public:
Output& sink()
{
return !to_msg_ ? sink_ : message_sink_.asOutput();
return !to_msg_ ? *sink_ : message_sink_.asOutput();
} // sink
void redirectToMessageSink() { ++to_msg_; }
void revertFromMessageSink() { --to_msg_; }
Output& redirectToSink(Output& newoutput)
{
Output& current = *sink_;
sink_ = &newoutput;
return current;
} // redirectToSink
const Arabica::XPath::ExecutionContext<std::string>& xpathContext() const { return xpathContext_; }
@ -103,7 +107,7 @@ private:
const CompiledStylesheet& stylesheet_;
VariableStack stack_;
Arabica::XPath::ExecutionContext<std::string> xpathContext_;
Output& sink_;
Output* sink_;
StreamSink message_sink_;
int to_msg_;
@ -111,6 +115,23 @@ private:
friend class ChainStackFrame;
}; // class ExecutionContext
class RedirectOutputFrame
{
public:
RedirectOutputFrame(ExecutionContext& context, Sink& output) :
context_(context),
previous_(context.redirectToSink(output.asOutput())) { }
~RedirectOutputFrame() { context_.redirectToSink(previous_); }
private:
ExecutionContext& context_;
Output& previous_;
RedirectOutputFrame();
RedirectOutputFrame(const RedirectOutputFrame&);
bool operator=(const RedirectOutputFrame&);
}; // RedirectOutputFrame
///////////////////////////
class ResolvedVariable : public Variable_instance
{
@ -120,8 +141,7 @@ public:
ExecutionContext& context) :
var_(var)
{
DOMSink sink;
value_ = var_.value(node, context, sink);
value_ = var_.value(node, context);
} // ResolvedVariable
virtual const std::string& name() const { return var_.name(); }
@ -162,7 +182,7 @@ public:
virtual Arabica::XPath::XPathValue<std::string> value() const
{
if(!value_)
value_ = var_.value(node_, context_, sink_);
value_ = var_.value(node_, context_);
return value_;
} // value
@ -176,14 +196,12 @@ private:
const DOM::Node<std::string>& node,
ExecutionContext& context) :
var_(var),
sink_(),
node_(node),
context_(sink_, context)
context_(context)
{
} // VariableClosure
const Variable_declaration& var_;
mutable DOMSink sink_;
const DOM::Node<std::string> node_;
mutable ExecutionContext context_;
mutable Arabica::XPath::XPathValue<std::string> value_;

View file

@ -20,7 +20,7 @@ public:
virtual void execute(const DOM::Node<std::string>& node, ExecutionContext& context) const
{
RedirectionFrame toMessageSink(context);
MessageRedirectionFrame toMessageSink(context);
execute_children(node, context);
if(terminate_)
@ -30,22 +30,19 @@ public:
private:
bool terminate_;
class RedirectionFrame
class MessageRedirectionFrame
{
public:
RedirectionFrame(ExecutionContext& context) : context_(context) { context_.redirectToMessageSink(); }
~RedirectionFrame() { context_.revertFromMessageSink(); }
MessageRedirectionFrame(ExecutionContext& context) : context_(context) { context_.redirectToMessageSink(); }
~MessageRedirectionFrame() { context_.revertFromMessageSink(); }
private:
ExecutionContext& context_;
RedirectionFrame();
RedirectionFrame(const RedirectionFrame&);
bool operator=(const RedirectionFrame&);
}; // class RedirectionFrame
MessageRedirectionFrame();
MessageRedirectionFrame(const MessageRedirectionFrame&);
bool operator=(const MessageRedirectionFrame&);
}; // class MessageRedirectionFrame
}; // class Message
} // namespace XSLT

View file

@ -328,6 +328,14 @@ public:
virtual Output& asOutput() { return *this; }
DOM::Node<std::string> node() const { return documentFrag_; }
void reset()
{
current_ = DOM::Node<std::string>();
documentFrag_ = DOM::DocumentFragment<std::string>();
document_ = DOM::Document<std::string>();
indent_ = -1;
out_again_ = false;
} // reset
protected:
void do_start_document(const Settings& settings)

View file

@ -28,8 +28,7 @@ public:
virtual const std::string& namespace_uri() const { return namespace_uri_; }
virtual const std::string& name() const { return name_; }
virtual Arabica::XPath::XPathValue<std::string> value(const DOM::Node<std::string>& node,
ExecutionContext& context,
DOMSink& sink) const
ExecutionContext& context) const
{
return value_;
} // value

View file

@ -29,13 +29,16 @@ public:
virtual const std::string& name() const { return name_; }
virtual Arabica::XPath::XPathValue<std::string> value(const DOM::Node<std::string>& node,
ExecutionContext& context,
DOMSink& sink) const
ExecutionContext& context) const
{
if(select_)
return select_->evaluate(node, context.xpathContext());
DOMSink sink;
{
RedirectOutputFrame redirect(context, sink);
execute_children(node, context);
} //
if(sink.node() == 0)
return Arabica::XPath::StringValue<std::string, Arabica::default_string_adaptor<std::string> >::createValue("");