aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdrian Kummerlaender2014-10-26 22:23:02 +0100
committerAdrian Kummerlaender2014-10-26 22:23:02 +0100
commit1276ea17e58f886d34423eefae92e0b0aa477b9a (patch)
tree67c39d89da8e4192c48b63439c1d7491b7ecc1cf /src
parentbc48696d7f463d0a230193f2173ec8516a2ca4b0 (diff)
downloadInputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.tar
InputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.tar.gz
InputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.tar.bz2
InputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.tar.lz
InputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.tar.xz
InputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.tar.zst
InputXSLT-1276ea17e58f886d34423eefae92e0b0aa477b9a.zip
Fixed XML declaration handling in FunctionExternalCommand
* `FunctionExternalCommand` failed to offer correct output handling when provided with a valid XML document which included a XML declaration ** `xerces::XercesDOMParser` generated the appropriate errors but they were not handled by `FunctionExternalCommand` ** wrapping is not necessary for full XML documents but is required for invalid XML as returned by e.g. common _Markdown_ processors *** if wrapping is applied to full XML documents which include a XML declaration the parser and subsequently the complete external function fails * added error parser handling by making the compilation unit local `importDocumentElement` method return value optional * added XML declaration detection and handling to `readOutput` ** if XML declaration is detected no wrapping is applied * added wrapping detection in `FunctionExternalCommand::constructDocument` ** if no wrapping is detected the whole tree is returned as content instead of just returning its child nodes
Diffstat (limited to 'src')
-rw-r--r--src/function/base.h2
-rw-r--r--src/function/external_command.cc69
2 files changed, 54 insertions, 17 deletions
diff --git a/src/function/base.h b/src/function/base.h
index 34f0a77..5c2d317 100644
--- a/src/function/base.h
+++ b/src/function/base.h
@@ -117,7 +117,7 @@ class FunctionBase : public xalan::Function {
template <std::size_t... Index>
inline xalan::XalanDocument* callConstructDocument(
const XObjectArgVectorType& parameters,
- const xalan::Locator* locator,
+ const xalan::Locator*,
Sequence<Index...>
) const {
const FilesystemContext context;
diff --git a/src/function/external_command.cc b/src/function/external_command.cc
index 40b02b9..7fbc1d9 100644
--- a/src/function/external_command.cc
+++ b/src/function/external_command.cc
@@ -5,6 +5,7 @@
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <boost/process.hpp>
+#include <boost/optional.hpp>
#include <sstream>
@@ -15,27 +16,54 @@ namespace {
using InputXSLT::XercesStringGuard;
+inline std::string wrapOutput(const std::string& rawOutput) {
+ return std::string(
+ "<inputxslt_wrapper>" + rawOutput + "</inputxslt_wrapper>"
+ );
+}
+
+inline bool isWrappedOutput(const XMLCh* nodeName) {
+ return xercesc::XMLString::equals(
+ nodeName,
+ *XercesStringGuard<XMLCh>("inputxslt_wrapper")
+ );
+}
+
inline std::unique_ptr<std::stringstream> readOutput(
boost::process::pistream& outputStream) {
- return std::make_unique<std::stringstream>(
- "<output>" + std::string(
- (std::istreambuf_iterator<char>(outputStream)),
- (std::istreambuf_iterator<char>())
- ) + "</output>"
+ const std::string rawOutput(
+ (std::istreambuf_iterator<char>(outputStream)),
+ (std::istreambuf_iterator<char>())
);
+
+ if ( rawOutput.substr(0, 5) == "<?xml" ) {
+ return std::make_unique<std::stringstream>(
+ rawOutput
+ );
+ } else {
+ return std::make_unique<std::stringstream>(
+ wrapOutput(rawOutput)
+ );
+ }
}
-inline xercesc::DOMNode* importDocumentElement(
+inline boost::optional<xercesc::DOMNode*> importDocumentElement(
std::stringstream* const outputStream,
xercesc::DOMDocument* const domDocument
) {
xercesc::XercesDOMParser parser;
parser.parse(xalan::XSLTInputSource(*outputStream));
- return domDocument->importNode(
- parser.getDocument()->getDocumentElement(),
- true
- );
+ if ( parser.getErrorCount() == 0 ) {
+ return boost::make_optional(
+ domDocument->importNode(
+ parser.getDocument()->getDocumentElement(),
+ true
+ )
+ );
+ } else {
+ return boost::optional<xercesc::DOMNode*>();
+ }
}
}
@@ -72,7 +100,6 @@ DomDocumentCache::document_ptr FunctionExternalCommand::constructDocument(
std::unique_ptr<std::stringstream> outputStream{
readOutput(commandProcess.get_stdout())
};
-
boost::process::status status = commandProcess.wait();
ResultNodeFacade result(domDocument.get(), "command");
@@ -81,14 +108,24 @@ DomDocumentCache::document_ptr FunctionExternalCommand::constructDocument(
if ( status.exited() ) {
try {
- result.setContent(
+ if ( boost::optional<xercesc::DOMNode*> documentElement{
importDocumentElement(
outputStream.get(),
domDocument.get()
- )->getChildNodes()
- );
-
- result.setAttribute("result", "success");
+ )
+ } ) {
+ if ( isWrappedOutput((*documentElement)->getNodeName()) ) {
+ result.setContent(
+ (*documentElement)->getChildNodes()
+ );
+ } else {
+ result.setContent(*documentElement);
+ }
+
+ result.setAttribute("result", "success");
+ } else {
+ result.setAttribute("result", "error");
+ }
}
catch ( const xercesc::DOMException& exception ) {
result.setAttribute("result", "error");