diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/function/base.h | 2 | ||||
-rw-r--r-- | src/function/generate.cc | 71 | ||||
-rw-r--r-- | src/function/generate.h | 32 | ||||
-rw-r--r-- | src/plattform_guard.cc | 7 | ||||
-rw-r--r-- | test/common/test.xsl (renamed from test/transform/test.xsl) | 0 | ||||
-rw-r--r-- | test/generate/reference.xml | 10 | ||||
-rw-r--r-- | test/generate/transformation.xsl | 58 | ||||
-rw-r--r-- | test/read_directory/reference.xml | 3 | ||||
-rw-r--r-- | test/transform/transformation.xsl | 2 |
11 files changed, 186 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9533c63..331aa2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ set( src/function/write_file.cc src/function/read_directory.cc src/function/transform.cc + src/function/generate.cc src/function/external_text_formatter.cc src/support/filesystem_context.cc src/support/xalan_string.cc @@ -11,6 +11,7 @@ Contrary to popular opinion I actually like XSLT as a content transformation lan - external `read-file` function for read-only access to both plain and xml files - external `read-directory` function for read-only directory traversal - external `transform` function for executing transformations inside transformations +- external `generate` function for executing transformations and committing the result directly to the filesystem - external `external-text-formatter` function for executing text formatters and capturing their XML output - external `write-file` function for writing files @@ -22,6 +23,7 @@ The `test` directory contains black-box test cases for every external function p - [`InputXSLT:read-file` (xml)](test/read_xml_file/transformation.xsl) - [`InputXSLT:read-directory`](test/read_directory/transformation.xsl) - [`InputXSLT:transform`](test/transform/transformation.xsl) +- [`InputXSLT:generate`](test/generate/transformation.xsl) - [`InputXSLT:external-text-formatter`](test/external_text_formatter/transformation.xsl) (requires [markdown.pl](http://daringfireball.net/projects/markdown/)) - [`InputXSLT:write-file`](test/write_file/transformation.xsl) diff --git a/src/function/base.h b/src/function/base.h index c3e1fb6..2d1e4c4 100644 --- a/src/function/base.h +++ b/src/function/base.h @@ -93,7 +93,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* locator, Sequence<Index...> ) const { XObjectValue valueGetter( diff --git a/src/function/generate.cc b/src/function/generate.cc new file mode 100644 index 0000000..4ece322 --- /dev/null +++ b/src/function/generate.cc @@ -0,0 +1,71 @@ +#include "generate.h" + +#include <xalanc/PlatformSupport/XalanOutputStreamPrintWriter.hpp> +#include <xalanc/PlatformSupport/XalanStdOutputStream.hpp> +#include <xalanc/XMLSupport/FormatterToXML.hpp> + +#include <boost/filesystem.hpp> +#include <boost/filesystem/fstream.hpp> + +#include "transformer_facade.h" +#include "support/xerces_string_guard.h" +#include "support/dom/result_node_facade.h" +#include "support/error/error_capacitor.h" + +namespace InputXSLT { + +DomDocumentCache::document_ptr FunctionGenerate::constructDocument( + xalan::XSLTInputSource inputSource, + xalan::XSLTInputSource transformationSource, + boost::filesystem::path targetPath +) const { + DomDocumentCache::document_ptr domDocument( + DomDocumentCache::createDocument("content") + ); + + ResultNodeFacade result(domDocument.get(), "generation"); + result.setAttribute("path", targetPath.string()); + + boost::filesystem::ofstream file(targetPath); + + if ( file.is_open() ) { + TransformerFacade transformer(this->include_resolver_); + + try { + xalan::XalanStdOutputStream output(file); + xalan::XalanOutputStreamPrintWriter writer(output); + xalan::FormatterToXML targetFormatter(writer); + + targetFormatter.setDoIndent(true); + + transformer.generate( + inputSource, + transformationSource, + targetFormatter + ); + + result.setAttribute("result", "success"); + } + catch (const ErrorCapacitor::exception& exception) { + result.setAttribute("result", "error"); + + for ( auto&& error : *exception ) { + result.setValueNode("error", error); + } + } + + WarningCapacitor::warning_cache_ptr warnings( + transformer.getCachedWarnings() + ); + + for ( auto&& warning : *warnings ) { + result.setValueNode("warning", warning); + } + } else { + result.setAttribute("result", "error"); + } + + return domDocument; +} + +} diff --git a/src/function/generate.h b/src/function/generate.h new file mode 100644 index 0000000..43f5da1 --- /dev/null +++ b/src/function/generate.h @@ -0,0 +1,32 @@ +#ifndef INPUTXSLT_SRC_FUNCTION_GENERATE_H_ +#define INPUTXSLT_SRC_FUNCTION_GENERATE_H_ + +#include <xalanc/XSLT/XSLTInputSource.hpp> + +#include "base.h" + +namespace InputXSLT { + +class FunctionGenerate : public FunctionBase< + FunctionGenerate, + xalan::XSLTInputSource, + xalan::XSLTInputSource, + boost::filesystem::path +> { + public: + using FunctionBase::FunctionBase; + + protected: + friend FunctionBase; + + DomDocumentCache::document_ptr constructDocument( + xalan::XSLTInputSource, + xalan::XSLTInputSource, + boost::filesystem::path + ) const; + +}; + +} + +#endif // INPUTXSLT_SRC_FUNCTION_GENERATE_H_ diff --git a/src/plattform_guard.cc b/src/plattform_guard.cc index cc3c9c0..5d19e32 100644 --- a/src/plattform_guard.cc +++ b/src/plattform_guard.cc @@ -10,6 +10,7 @@ #include "function/write_file.h" #include "function/read_directory.h" #include "function/transform.h" +#include "function/generate.h" #include "function/external_text_formatter.h" namespace InputXSLT { @@ -49,6 +50,12 @@ PlattformGuard::PlattformGuard(const std::vector<std::string>& path): xalan::XalanTransformer::installExternalFunctionGlobal( customNamespace, + xalan::XalanDOMString("generate"), + InputXSLT::FunctionGenerate(&this->include_resolver_) + ); + + xalan::XalanTransformer::installExternalFunctionGlobal( + customNamespace, xalan::XalanDOMString("external-text-formatter"), InputXSLT::FunctionExternalTextFormatter(&this->include_resolver_) ); diff --git a/test/transform/test.xsl b/test/common/test.xsl index a9f04a5..a9f04a5 100644 --- a/test/transform/test.xsl +++ b/test/common/test.xsl diff --git a/test/generate/reference.xml b/test/generate/reference.xml new file mode 100644 index 0000000..1c702e8 --- /dev/null +++ b/test/generate/reference.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<test_case> +<input_entries> +<entry>Hello 1</entry> +<entry>Hello 2</entry> +<entry>Hello 3</entry> +<entry>Hello 4</entry> +</input_entries> +<parameter_value>42</parameter_value> +</test_case> diff --git a/test/generate/transformation.xsl b/test/generate/transformation.xsl new file mode 100644 index 0000000..6e3d88b --- /dev/null +++ b/test/generate/transformation.xsl @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet + version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:dyn="http://exslt.org/dynamic" + xmlns:xalan="http://xml.apache.org/xalan" + xmlns:InputXSLT="function.inputxslt.application" + exclude-result-prefixes="dyn xalan InputXSLT" +> + +<xsl:import href="[testcase.xsl]"/> + +<xsl:template name="generator"> + <xsl:param name="input"/> + <xsl:param name="transformation"/> + <xsl:param name="target"/> + + <xsl:copy-of select="InputXSLT:generate( + $input, + string($transformation), + string($target) + )"/> +</xsl:template> + +<xsl:template name="implementation"> + <xsl:variable name="result"> + <xsl:call-template name="generator"> + <xsl:with-param name="input"> + <test> + <entries> + <entry>Hello 1</entry> + <entry>Hello 2</entry> + <entry>Hello 3</entry> + <entry>Hello 4</entry> + </entries> + <parameter> + <test>21</test> + </parameter> + </test> + </xsl:with-param> + <xsl:with-param name="transformation">[test.xsl]</xsl:with-param> + <xsl:with-param name="target">test_actual.xml</xsl:with-param> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="generation" select="xalan:nodeset($result)/generation"/> + + <xsl:choose> + <xsl:when test="$generation/@result = 'success'"> + <xsl:copy-of select="InputXSLT:read-file('test_actual.xml')/test_case/transform_test/*"/> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="$generation/*"/> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + +</xsl:stylesheet> diff --git a/test/read_directory/reference.xml b/test/read_directory/reference.xml index 7d63a85..d2d9d1b 100644 --- a/test/read_directory/reference.xml +++ b/test/read_directory/reference.xml @@ -14,6 +14,9 @@ <name>external_text_formatter</name> </item> <item type="directory"> +<name>generate</name> +</item> +<item type="directory"> <name>read_directory</name> </item> <item type="directory"> diff --git a/test/transform/transformation.xsl b/test/transform/transformation.xsl index 7cfb8f9..247a4c6 100644 --- a/test/transform/transformation.xsl +++ b/test/transform/transformation.xsl @@ -36,7 +36,7 @@ </parameter> </test> </xsl:with-param> - <xsl:with-param name="transformation">test.xsl</xsl:with-param> + <xsl:with-param name="transformation">[test.xsl]</xsl:with-param> </xsl:call-template> </xsl:variable> |