aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerländer2014-04-21 21:47:20 +0200
committerAdrian Kummerländer2014-04-21 21:47:20 +0200
commit7142544d43b431df44d34921b0f3012fa1e0137d (patch)
tree5fb5de3222d25f0e48f24a0dbdd0d18f5d917c89
parentcdf4ad3486debe75fe89b2f04bb62541f3ac8405 (diff)
downloadInputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.tar
InputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.tar.gz
InputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.tar.bz2
InputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.tar.lz
InputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.tar.xz
InputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.tar.zst
InputXSLT-7142544d43b431df44d34921b0f3012fa1e0137d.zip
Implemented basic external directory traversal function
* _read-directory_ lists all files in a given directory ** currently text-only output, xml planned * improved FilesystemContext path resolution (relative path is fully resolved by boost::filesystem)
-rw-r--r--CMakeLists.txt1
-rw-r--r--dummy/transform.xsl5
-rw-r--r--src/function/read_directory.cc49
-rw-r--r--src/function/read_directory.h41
-rw-r--r--src/support/filesystem_context.cc49
-rw-r--r--src/support/filesystem_context.h6
-rw-r--r--src/transformer_facade.cc10
7 files changed, 152 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 43b8e98..915a05d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,7 @@ add_executable(
src/transformer_facade.cc
src/function/read_file.cc
src/function/read_xml_file.cc
+ src/function/read_directory.cc
src/support/filesystem_context.cc
)
diff --git a/dummy/transform.xsl b/dummy/transform.xsl
index 803e0f6..c0437a0 100644
--- a/dummy/transform.xsl
+++ b/dummy/transform.xsl
@@ -18,11 +18,14 @@
<div id="raw">
<xsl:value-of select="external:read-file('test.txt')" />
</div>
- <ul>
+ <ul id="xml">
<xsl:for-each select="external:read-xml-file('test.txt')/tester/eintrag">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
+ <div id="filelist">
+ <xsl:value-of select="external:read-directory('.')" />
+ </div>
</body>
</html>
</xsl:template>
diff --git a/src/function/read_directory.cc b/src/function/read_directory.cc
new file mode 100644
index 0000000..7b73526
--- /dev/null
+++ b/src/function/read_directory.cc
@@ -0,0 +1,49 @@
+#include "read_directory.h"
+
+#include <iostream>
+
+namespace InputXSLT {
+
+FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context):
+ fs_context_(context) { }
+
+xalan::XObjectPtr FunctionReadDirectory::execute(
+ xalan::XPathExecutionContext& executionContext,
+ xalan::XalanNode* context,
+ const xalan::Function::XObjectArgVectorType& arguments,
+ const xalan::Locator* locator
+) const {
+ if ( arguments.size() != 1 ) {
+ xalan::XPathExecutionContext::GetAndReleaseCachedString guard(
+ executionContext
+ );
+
+ this->generalError(executionContext, context, locator);
+ }
+
+ std::string files;
+
+ this->fs_context_.iterate(
+ arguments[0]->str(),
+ [&files](const boost::filesystem::path& p) {
+ files += p.string() + "\n";
+ });
+
+ return executionContext.getXObjectFactory().createString(
+ xalan::XalanDOMString(files.data())
+ );
+}
+
+FunctionReadDirectory* FunctionReadDirectory::clone(
+ xalan::MemoryManager& manager) const {
+ return xalan::XalanCopyConstruct(manager, *this);
+}
+
+const xalan::XalanDOMString& FunctionReadDirectory::getError(
+ xalan::XalanDOMString& result) const {
+ result.assign("The read-directory() function expects one argument.");
+
+ return result;
+}
+
+}
diff --git a/src/function/read_directory.h b/src/function/read_directory.h
new file mode 100644
index 0000000..4a865f2
--- /dev/null
+++ b/src/function/read_directory.h
@@ -0,0 +1,41 @@
+#ifndef INPUTXSLT_SRC_FUNCTION_READ_DIRECTORY_H_
+#define INPUTXSLT_SRC_FUNCTION_READ_DIRECTORY_H_
+
+#include <xalanc/XalanTransformer/XalanTransformer.hpp>
+#include <xalanc/XPath/XObjectFactory.hpp>
+#include <xalanc/XPath/Function.hpp>
+#include <xalanc/XPath/XObject.hpp>
+
+#include <string>
+
+#include "common.h"
+#include "support/filesystem_context.h"
+
+namespace InputXSLT {
+
+class FunctionReadDirectory : public xalan::Function {
+ public:
+ FunctionReadDirectory(const FilesystemContext&);
+
+ virtual xalan::XObjectPtr execute(
+ xalan::XPathExecutionContext&,
+ xalan::XalanNode*,
+ const xalan::Function::XObjectArgVectorType&,
+ const xalan::Locator*
+ ) const;
+
+ virtual FunctionReadDirectory* clone(xalan::MemoryManager&) const;
+
+ FunctionReadDirectory& operator=(const FunctionReadDirectory&) = delete;
+ bool operator==(const FunctionReadDirectory&) const = delete;
+
+ private:
+ const FilesystemContext& fs_context_;
+
+ const xalan::XalanDOMString& getError(xalan::XalanDOMString&) const;
+
+};
+
+}
+
+#endif // INPUTXSLT_SRC_FUNCTION_READ_DIRECTORY_H_
diff --git a/src/support/filesystem_context.cc b/src/support/filesystem_context.cc
index d3f9614..d0813c2 100644
--- a/src/support/filesystem_context.cc
+++ b/src/support/filesystem_context.cc
@@ -1,24 +1,57 @@
#include "filesystem_context.h"
+namespace {
+
+inline std::string xalanToString(const xalan::XalanDOMString& text) {
+ xalan::CharVectorType castHelper;
+ text.transcode(castHelper);
+
+ return std::string(
+ castHelper.begin(),
+ castHelper.end() - 1
+ );
+}
+
+}
+
namespace InputXSLT {
FilesystemContext::FilesystemContext(const std::string& path):
- path_(path) { }
+ path_(canonical(boost::filesystem::path(path))) { }
boost::filesystem::path FilesystemContext::resolve(
const std::string& path) const {
- return boost::filesystem::path(this->path_ / path);
+ return canonical(this->path_ / path);
}
boost::filesystem::path FilesystemContext::resolve(
const xalan::XalanDOMString& path) const {
- xalan::CharVectorType castHelper;
- path.transcode(castHelper);
+ return this->resolve(xalanToString(path));
+}
- return this->resolve(std::string(
- castHelper.begin(),
- castHelper.end()
- ));
+void FilesystemContext::iterate(
+ const std::string& path,
+ std::function<void(const boost::filesystem::path&)> func
+) const {
+ const boost::filesystem::path directory(this->resolve(path));
+
+ if ( boost::filesystem::exists(directory) &&
+ boost::filesystem::is_directory(directory) ) {
+ for ( boost::filesystem::directory_iterator iter(directory);
+ iter != boost::filesystem::directory_iterator();
+ ++iter ) {
+ if ( boost::filesystem::is_regular_file(iter->status()) ) {
+ func(*iter);
+ }
+ }
+ }
+}
+
+void FilesystemContext::iterate(
+ const xalan::XalanDOMString& path,
+ std::function<void(const boost::filesystem::path&)> func
+) const {
+ this->iterate(xalanToString(path), func);
}
}
diff --git a/src/support/filesystem_context.h b/src/support/filesystem_context.h
index d5836f1..cb3edd4 100644
--- a/src/support/filesystem_context.h
+++ b/src/support/filesystem_context.h
@@ -6,6 +6,7 @@
#include "boost/filesystem.hpp"
#include <string>
+#include <functional>
#include "common.h"
@@ -18,6 +19,11 @@ class FilesystemContext {
boost::filesystem::path resolve(const std::string&) const;
boost::filesystem::path resolve(const xalan::XalanDOMString&) const;
+ void iterate(const std::string&,
+ std::function<void(const boost::filesystem::path&)>) const;
+ void iterate(const xalan::XalanDOMString&,
+ std::function<void(const boost::filesystem::path&)>) const;
+
private:
const boost::filesystem::path path_;
diff --git a/src/transformer_facade.cc b/src/transformer_facade.cc
index dfd51ef..055b1f3 100644
--- a/src/transformer_facade.cc
+++ b/src/transformer_facade.cc
@@ -11,8 +11,12 @@
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
+#include <iostream>
+
#include "function/read_file.h"
#include "function/read_xml_file.h"
+#include "function/read_directory.h"
+
namespace InputXSLT {
@@ -35,6 +39,12 @@ TransformerFacade::TransformerFacade(const std::string& path):
xalan::XalanDOMString("read-xml-file"),
InputXSLT::FunctionReadXmlFile(this->fs_context_)
);
+
+ this->transformer_.installExternalFunction(
+ customNamespace,
+ xalan::XalanDOMString("read-directory"),
+ InputXSLT::FunctionReadDirectory(this->fs_context_)
+ );
}
int TransformerFacade::execute(