aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerländer2014-05-29 13:26:37 +0200
committerAdrian Kummerländer2014-05-29 13:26:37 +0200
commit3bc793d95293d40dbab62c593ce4ceaa86fae25b (patch)
tree07a0f99d72a074a75955a593318cc8bcd394f4c2
parent52b60c1a8c23f11ab18fad06e0957490c7436e0a (diff)
downloadInputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.tar
InputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.tar.gz
InputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.tar.bz2
InputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.tar.lz
InputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.tar.xz
InputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.tar.zst
InputXSLT-3bc793d95293d40dbab62c593ce4ceaa86fae25b.zip
Improved TransformationFacade error handling
* ErrorHandler class created in 5859cb6 now caches all errors instead of pushing them to std::cerr ** cached errors are retrieved by TransformationFacade's "generate" member method * test frontend pushes all errors to std::cerr * FunctionTransform returns errors to the calling template as XML ** FunctionTransform test case demonstrates how one may test for successful transformation * "generate" member method returns std::string vector wrapped in a std::unique_ptr ** this is used as a kind of optional pointer, as the std::unique_ptr instance only wraps a vector if errors where actually generated
-rw-r--r--src/function/transform.cc15
-rw-r--r--src/support/error_handler.cc63
-rw-r--r--src/support/error_handler.h13
-rw-r--r--src/support/include_entity_resolver.cc4
-rw-r--r--src/transformation_facade.cc32
-rw-r--r--src/transformation_facade.h24
-rw-r--r--test.cc12
-rw-r--r--test/transform/transformation.xsl31
8 files changed, 126 insertions, 68 deletions
diff --git a/src/function/transform.cc b/src/function/transform.cc
index fd28b34..7e8a844 100644
--- a/src/function/transform.cc
+++ b/src/function/transform.cc
@@ -38,17 +38,22 @@ xercesc::DOMDocument* FunctionTransform::constructDocument(
domDocument->getDocumentElement()
);
+ ResultNodeFacade result(domDocument, rootNode, "result");
+ result.setAttribute("name", targetPath);
+
InputXSLT::TransformationFacade transformation(
transformationPath,
this->include_resolver_
);
- if ( transformation.generate(targetPath, parameterObject) == 0 ) {
- ResultNodeFacade result(domDocument, rootNode, "result");
+ InputXSLT::TransformationFacade::return_type errors(
+ transformation.generate(targetPath, parameterObject)
+ );
- result.setAttribute("name", targetPath);
- } else {
- ResultNodeFacade result(domDocument, rootNode, "error");
+ if ( errors ) {
+ for ( auto&& error : *errors ) {
+ result.setValueNode("error", error);
+ }
}
return domDocument;
diff --git a/src/support/error_handler.cc b/src/support/error_handler.cc
index 9a898a6..db54225 100644
--- a/src/support/error_handler.cc
+++ b/src/support/error_handler.cc
@@ -6,38 +6,55 @@
#include "support/xerces_string_guard.h"
+namespace {
+
+inline std::string getMessage(const xercesc::SAXParseException& exception) {
+ return std::string(
+ *InputXSLT::XercesStringGuard<char>(exception.getMessage())
+ );
+}
+
+}
+
namespace InputXSLT {
-ErrorHandler::ErrorHandler(const std::string& transformation):
- transformation_path_(transformation) { }
+ErrorHandler::ErrorHandler():
+ error_cache_{} { }
+
+void ErrorHandler::warning(const xercesc::SAXParseException& exception) {
+ this->constructErrorCache();
-void ErrorHandler::warning(const xercesc::SAXParseException& e) {
- std::cerr << "Warning in "
- << "'"
- << this->transformation_path_
- << "': "
- << *XercesStringGuard<char>(e.getMessage())
- << std::endl;
+ this->error_cache_->emplace_back(
+ "Warning: " + getMessage(exception)
+ );
}
-void ErrorHandler::error(const xercesc::SAXParseException& e) {
- std::cerr << "Error in "
- << "'"
- << this->transformation_path_
- << "': "
- << *XercesStringGuard<char>(e.getMessage())
- << std::endl;
+void ErrorHandler::error(const xercesc::SAXParseException& exception) {
+ this->constructErrorCache();
+
+ this->error_cache_->emplace_back(
+ "Error: " + getMessage(exception)
+ );
}
-void ErrorHandler::fatalError(const xercesc::SAXParseException& e) {
- std::cerr << "Fatal error in "
- << "'"
- << this->transformation_path_
- << "': "
- << *XercesStringGuard<char>(e.getMessage())
- << std::endl;
+void ErrorHandler::fatalError(const xercesc::SAXParseException& exception) {
+ this->constructErrorCache();
+
+ this->error_cache_->emplace_back(
+ "Fatal error: " + getMessage(exception)
+ );
}
void ErrorHandler::resetErrors() { }
+auto ErrorHandler::getCachedErrors() -> error_cache_ptr {
+ return error_cache_ptr(this->error_cache_.release());
+}
+
+void ErrorHandler::constructErrorCache() {
+ if ( !this->error_cache_ ) {
+ this->error_cache_.reset(new error_cache());
+ }
+}
+
}
diff --git a/src/support/error_handler.h b/src/support/error_handler.h
index 7835292..77a46d8 100644
--- a/src/support/error_handler.h
+++ b/src/support/error_handler.h
@@ -3,21 +3,30 @@
#include <xercesc/sax/ErrorHandler.hpp>
+#include <memory>
+#include <vector>
#include <string>
namespace InputXSLT {
class ErrorHandler : public xercesc::ErrorHandler {
public:
- ErrorHandler(const std::string&);
+ typedef std::vector<std::string> error_cache;
+ typedef std::unique_ptr<error_cache> error_cache_ptr;
+
+ ErrorHandler();
virtual void warning(const xercesc::SAXParseException&);
virtual void error(const xercesc::SAXParseException&);
virtual void fatalError(const xercesc::SAXParseException&);
virtual void resetErrors();
+ error_cache_ptr getCachedErrors();
+
private:
- const std::string& transformation_path_;
+ error_cache_ptr error_cache_;
+
+ void constructErrorCache();
};
diff --git a/src/support/include_entity_resolver.cc b/src/support/include_entity_resolver.cc
index 948a61b..e63a3c4 100644
--- a/src/support/include_entity_resolver.cc
+++ b/src/support/include_entity_resolver.cc
@@ -48,7 +48,9 @@ xercesc::InputSource* IncludeEntityResolver::resolveEntity(
*XercesStringGuard<XMLCh>((*resolvedPath).string())
);
} else {
- return nullptr;
+ return new xercesc::LocalFileInputSource(
+ *XercesStringGuard<XMLCh>(*filePath)
+ );
}
} else {
return nullptr;
diff --git a/src/transformation_facade.cc b/src/transformation_facade.cc
index fc7e1de..0f174d8 100644
--- a/src/transformation_facade.cc
+++ b/src/transformation_facade.cc
@@ -6,7 +6,6 @@
#include "boost/filesystem.hpp"
#include <sstream>
-#include <iostream>
namespace InputXSLT {
@@ -16,7 +15,7 @@ TransformationFacade::TransformationFacade(
):
transformation_{},
transformer_(),
- error_handler_(transformation) {
+ error_handler_() {
this->transformer_.setEntityResolver(resolver);
this->transformer_.setErrorHandler(&this->error_handler_);
@@ -32,10 +31,10 @@ TransformationFacade::~TransformationFacade() {
);
}
-int TransformationFacade::generate(
+auto TransformationFacade::generate(
const std::string& targetPath,
StylesheetParameterGuard& parameters
-) {
+) -> return_type {
const boost::filesystem::path targetPathHelper(
boost::filesystem::absolute(targetPath)
);
@@ -53,22 +52,22 @@ int TransformationFacade::generate(
);
}
-int TransformationFacade::generate(
+auto TransformationFacade::generate(
std::basic_ostream<char>& targetStream,
StylesheetParameterGuard& parameters
-) {
+) -> return_type {
return this->generate(
xalan::XSLTResultTarget(targetStream),
parameters
);
}
-int TransformationFacade::generate(
+auto TransformationFacade::generate(
xalan::XSLTResultTarget&& outputTarget,
StylesheetParameterGuard&
-) {
- std::stringstream emptyStream("<dummy/>");
- xalan::XSLTInputSource inputSource(emptyStream);
+) -> return_type {
+ std::stringstream emptyStream("<dummy/>");
+ xalan::XSLTInputSource inputSource(emptyStream);
const int resultCode = this->transformer_.transform(
inputSource,
@@ -76,11 +75,18 @@ int TransformationFacade::generate(
outputTarget
);
- if ( resultCode != 0 ) {
- std::cerr << this->transformer_.getLastError() << std::endl;
+ return_type errors(this->error_handler_.getCachedErrors());
+
+ if ( errors && resultCode != 0 ) {
+ errors->emplace_back(
+ "Transformation error with code " +
+ std::to_string(resultCode) +
+ ": " +
+ this->transformer_.getLastError()
+ );
}
- return resultCode;
+ return errors;
}
}
diff --git a/src/transformation_facade.h b/src/transformation_facade.h
index ab76cac..28d1895 100644
--- a/src/transformation_facade.h
+++ b/src/transformation_facade.h
@@ -14,17 +14,19 @@ namespace InputXSLT {
class TransformationFacade {
public:
+ typedef ErrorHandler::error_cache_ptr return_type;
+
TransformationFacade(const std::string&, IncludeEntityResolver*);
~TransformationFacade();
template <typename Target>
- int generate(Target&);
+ return_type generate(Target&);
template <typename Target>
- int generate(Target&, const StylesheetParameterGuard::map&);
+ return_type generate(Target&, const StylesheetParameterGuard::map&);
template <typename Target>
- int generate(Target&, const xalan::XObjectPtr&);
+ return_type generate(Target&, const xalan::XObjectPtr&);
private:
const xalan::XalanCompiledStylesheet* transformation_;
@@ -32,34 +34,34 @@ class TransformationFacade {
xalan::XalanTransformer transformer_;
ErrorHandler error_handler_;
- int generate(const std::string&, StylesheetParameterGuard&);
- int generate(std::basic_ostream<char>&, StylesheetParameterGuard&);
- int generate(xalan::XSLTResultTarget&&, StylesheetParameterGuard&);
+ return_type generate(const std::string&, StylesheetParameterGuard&);
+ return_type generate(std::basic_ostream<char>&, StylesheetParameterGuard&);
+ return_type generate(xalan::XSLTResultTarget&&, StylesheetParameterGuard&);
};
template <typename Target>
-int TransformationFacade::generate(Target& target) {
+auto TransformationFacade::generate(Target& target) -> return_type {
StylesheetParameterGuard guard(this->transformer_);
return this->generate(target, guard);
}
template <typename Target>
-int TransformationFacade::generate(
+auto TransformationFacade::generate(
Target& target,
const StylesheetParameterGuard::map& parameters
-) {
+) -> return_type {
StylesheetParameterGuard guard(this->transformer_, parameters);
return this->generate(target, guard);
}
template <typename Target>
-int TransformationFacade::generate(
+auto TransformationFacade::generate(
Target& target,
const xalan::XObjectPtr& parameter
-) {
+) -> return_type {
StylesheetParameterGuard guard(this->transformer_);
guard.set("parameters", parameter);
diff --git a/test.cc b/test.cc
index 9d1dd3a..0c5e4b2 100644
--- a/test.cc
+++ b/test.cc
@@ -48,12 +48,20 @@ int main(int ac, char** av) {
plattform.getEntityResolver()
);
+ InputXSLT::TransformationFacade::return_type errors{};
+
if ( variables.count("target") ) {
- return transformation.generate(
+ errors = transformation.generate(
variables["target"].as<std::string>()
);
} else {
- return transformation.generate(std::cout);
+ errors = transformation.generate(std::cout);
+ }
+
+ if ( errors ) {
+ for ( auto&& error : *errors ) {
+ std::cerr << error << std::endl;
+ }
}
} else {
std::cout << optionDescription << std::endl;
diff --git a/test/transform/transformation.xsl b/test/transform/transformation.xsl
index f2cc787..19c42ae 100644
--- a/test/transform/transformation.xsl
+++ b/test/transform/transformation.xsl
@@ -23,21 +23,30 @@
)
</xsl:variable>
- <xsl:variable name="result" select="dyn:evaluate($command)"/>
+ <xsl:copy-of select="dyn:evaluate($command)"/>
</xsl:template>
<xsl:template name="implementation">
- <xsl:call-template name="transformer">
- <xsl:with-param name="transformation">test.xsl</xsl:with-param>
- <xsl:with-param name="target">test_actual.xml</xsl:with-param>
- <xsl:with-param name="parameters">
- <test>21</test>
- </xsl:with-param>
- </xsl:call-template>
+ <xsl:variable name="result">
+ <xsl:call-template name="transformer">
+ <xsl:with-param name="transformation">test.xsl</xsl:with-param>
+ <xsl:with-param name="target">test_actual.xml</xsl:with-param>
+ <xsl:with-param name="parameters">
+ <test>21</test>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
- <xsl:copy-of select="
- InputXSLT:read-xml-file('test_actual.xml')/test_case/transform_test/*
- "/>
+ <xsl:choose>
+ <xsl:when test="xalan:nodeset($result)/result/error">
+ <xsl:copy-of select="xalan:nodeset($result)/result/error"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="
+ InputXSLT:read-xml-file('test_actual.xml')/test_case/transform_test/*
+ "/>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
</xsl:stylesheet>