From 1276ea17e58f886d34423eefae92e0b0aa477b9a Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sun, 26 Oct 2014 22:23:02 +0100 Subject: 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 --- src/function/base.h | 2 +- src/function/external_command.cc | 69 ++++++++++++++++++++++++++++++---------- 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 inline xalan::XalanDocument* callConstructDocument( const XObjectArgVectorType& parameters, - const xalan::Locator* locator, + const xalan::Locator*, Sequence ) 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 #include +#include #include @@ -15,27 +16,54 @@ namespace { using InputXSLT::XercesStringGuard; +inline std::string wrapOutput(const std::string& rawOutput) { + return std::string( + "" + rawOutput + "" + ); +} + +inline bool isWrappedOutput(const XMLCh* nodeName) { + return xercesc::XMLString::equals( + nodeName, + *XercesStringGuard("inputxslt_wrapper") + ); +} + inline std::unique_ptr readOutput( boost::process::pistream& outputStream) { - return std::make_unique( - "" + std::string( - (std::istreambuf_iterator(outputStream)), - (std::istreambuf_iterator()) - ) + "" + const std::string rawOutput( + (std::istreambuf_iterator(outputStream)), + (std::istreambuf_iterator()) ); + + if ( rawOutput.substr(0, 5) == "( + rawOutput + ); + } else { + return std::make_unique( + wrapOutput(rawOutput) + ); + } } -inline xercesc::DOMNode* importDocumentElement( +inline boost::optional 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(); + } } } @@ -72,7 +100,6 @@ DomDocumentCache::document_ptr FunctionExternalCommand::constructDocument( std::unique_ptr 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 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"); -- cgit v1.2.3