diff options
author | Adrian Kummerlaender | 2014-10-26 22:23:02 +0100 |
---|---|---|
committer | Adrian Kummerlaender | 2014-10-26 22:23:02 +0100 |
commit | 1276ea17e58f886d34423eefae92e0b0aa477b9a (patch) | |
tree | 67c39d89da8e4192c48b63439c1d7491b7ecc1cf /src | |
parent | bc48696d7f463d0a230193f2173ec8516a2ca4b0 (diff) | |
download | InputXSLT-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.h | 2 | ||||
-rw-r--r-- | 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 <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"); |