Browse Source

xslt: Some code for xslt support

Serj Kalichev 8 years ago
parent
commit
42cd18bc3b
5 changed files with 165 additions and 37 deletions
  1. 1 1
      bin/clish.c
  2. 1 2
      clish/shell.h
  3. 69 1
      clish/shell/shell_libxml2.c
  4. 61 33
      clish/shell/shell_xml.c
  5. 33 0
      clish/shell/xmlapi.h

+ 1 - 1
bin/clish.c

@@ -247,7 +247,7 @@ int main(int argc, char **argv)
 		goto end;
 	}
 	/* Load the XML files */
-	if (clish_shell_load_scheme(shell, xml_path))
+	if (clish_shell_load_scheme(shell, xml_path, NULL))
 		goto end;
 	/* Set communication to the konfd */
 	clish_shell__set_socket(shell, socket_path);

+ 1 - 2
clish/shell.h

@@ -99,7 +99,6 @@ clish_ptype_t *clish_shell_find_create_ptype(clish_shell_t * instance,
 	clish_ptype_preprocess_e preprocess);
 clish_ptype_t *clish_shell_find_ptype(clish_shell_t *instance,
 	const char *name);
-int clish_shell_xml_read(clish_shell_t * instance, const char *filename);
 void clish_shell_help(clish_shell_t * instance, const char *line);
 int clish_shell_exec_action(clish_context_t *context, char **out);
 int clish_shell_execute(clish_context_t *context, char **out);
@@ -147,7 +146,7 @@ FILE *clish_shell__get_ostream(const clish_shell_t * instance);
 void clish_shell__set_lockfile(clish_shell_t * instance, const char * path);
 char * clish_shell__get_lockfile(clish_shell_t * instance);
 int clish_shell__set_socket(clish_shell_t * instance, const char * path);
-int clish_shell_load_scheme(clish_shell_t * instance, const char * xml_path);
+int clish_shell_load_scheme(clish_shell_t * instance, const char * xml_path, const char *xslt_path);
 int clish_shell_loop(clish_shell_t * instance);
 clish_shell_state_t clish_shell__get_state(const clish_shell_t * instance);
 void clish_shell__set_state(clish_shell_t * instance,

+ 69 - 1
clish/shell/shell_libxml2.c

@@ -19,6 +19,19 @@
 #include <libxml/tree.h>
 #include "xmlapi.h"
 
+#ifdef HAVE_LIB_LIBXSLT
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+extern int xmlLoadExtDtdDefaultValue;
+
+/* dummy stuff ; really a xsltStylesheet */
+struct clish_xslt_s {
+	int dummy;
+};
+#endif
+
 /* dummy stuff ; really a xmlDoc */
 struct clish_xmldoc_s {
 	int dummy;
@@ -54,10 +67,12 @@ static inline clish_xmlnode_t *node_to_xmlnode(xmlNode *node)
  */
 clish_xmldoc_t *clish_xmldoc_read(const char *filename)
 {
-	xmlDoc *doc = xmlReadFile(filename, NULL, 0);
+	xmlDoc *doc;
+	doc = xmlReadFile(filename, NULL, 0);
 	return doc_to_xmldoc(doc);
 }
 
+
 void clish_xmldoc_release(clish_xmldoc_t *doc)
 {
 	if (doc) {
@@ -275,5 +290,58 @@ void clish_xml_release(void *p)
 	/* do we allocate memory? not yet. */
 }
 
+#ifdef HAVE_LIB_LIBXSLT
+
+static inline xsltStylesheet *xslt_to_xsltStylesheet(clish_xslt_t *xslt)
+{
+	return (xsltStylesheet*)doc;
+}
+
+static inline clish_xslt_t *xsltStylesheet_to_xslt(xsltStylesheet *xslt)
+{
+	return (clish_xslt_t*)xslt;
+}
+
+int clish_xslt_is_valid(clish_xslt_t *stylesheet)
+{
+	return stylesheet != NULL;
+}
+
+clish_xmldoc_t *clish_xslt_apply(clish_xmldoc_t *xmldoc, clish_xslt_t *stylesheet)
+{
+	xmlDoc *doc = xmldoc_to_doc(xmldoc);
+	xsltStylesheetPtr cur = xslt_to_xsltStylesheet(stylesheet);
+	xmlDoc *res;
+
+	if (!doc || !cur)
+		return doc_to_xmldoc(NULL);
+	res = xsltApplyStylesheet(cur, doc, NULL);
+
+	return doc_to_xmldoc(res);
+}
+
+clish_xslt_t *clish_xslt_read(const char *filename)
+{
+	xsltStylesheet* cur = NULL;
+
+	xmlSubstituteEntitiesDefault(1);
+	xmlLoadExtDtdDefaultValue = 1;
+	cur = xsltParseStylesheetFile((const xmlChar *)filename);
+
+	return xsltStylesheet_to_xslt(cur);
+}
+
+void clish_xslt_release(clish_xslt_t *stylesheet)
+{
+	xsltStylesheet* cur = xslt_to_xsltStylesheet(stylesheet);
+
+	if (!cur)
+		return;
+	xsltFreeStylesheet(cur);
+	xsltCleanupGlobals();
+}
+
+#endif /* HAVE_LIB_LIBXSLT */
+
 #endif /* HAVE_LIB_LIBXML2 */
 

+ 61 - 33
clish/shell/shell_xml.c

@@ -72,14 +72,31 @@ static clish_xml_cb_t xml_elements[] = {
  */
 const char *default_path = "/etc/clish;~/.clish";
 
+static int process_node(clish_shell_t *shell, clish_xmlnode_t *node,
+	void *parent);
+
 /*-------------------------------------------------------- */
-int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path)
+int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path, const char *xslt_path)
 {
 	const char *path = xml_path;
 	char *buffer;
 	char *dirname;
 	char *saveptr = NULL;
 	int res = 0;
+	clish_xmldoc_t *doc;
+
+#ifdef HAVE_LIB_LIBXSLT
+	clish_xslt_t *xslt;
+
+	if (xslt_path) {
+		xslt = clish_xslt_read(xslt_path);
+		if (!clish_xslt_is_valid(xslt)) {
+			fprintf(stderr, CLISH_XML_ERROR_STR"Can't load XSLT file %s\n",
+				xslt_path);
+			return -1;
+		}
+	}
+#endif
 
 	/* use the default path */
 	if (!path)
@@ -118,8 +135,41 @@ int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path)
 #ifdef DEBUG
 				fprintf(stderr, "Parse XML-file: %s\n", filename);
 #endif
-				/* load this file */
-				res = clish_shell_xml_read(this, filename);
+				/* Load this XML file */
+				doc = clish_xmldoc_read(filename);
+				if (clish_xmldoc_is_valid(doc)) {
+					clish_xmlnode_t *root;
+#ifdef HAVEL_LIB_LIBXSLT
+					if (xslt_path) {
+						xmlDoc *tmp;
+						tmp = clish_xslt_apply(doc, xslt);
+						if (!clish_xmldoc_is_valid(tmp)) {
+							fprintf(stderr, CLISH_XML_ERROR_STR"Can't load XSLT file %s\n", xslt_path);
+							res = -1;
+						} else {
+							clish_xmldoc_release(doc);
+							doc = tmp;
+						}
+					}
+#endif
+					if (!res) {
+						root = clish_xmldoc_get_root(doc);
+						res = process_node(this, root, NULL);
+					}
+				} else {
+					int errcaps = clish_xmldoc_error_caps(doc);
+					printf("Unable to open file '%s'", filename);
+					if ((errcaps & CLISH_XMLERR_LINE) == CLISH_XMLERR_LINE)
+							printf(", at line %d", clish_xmldoc_get_err_line(doc));
+						if ((errcaps & CLISH_XMLERR_COL) == CLISH_XMLERR_COL)
+						printf(", at column %d", clish_xmldoc_get_err_col(doc));
+					if ((errcaps & CLISH_XMLERR_DESC) == CLISH_XMLERR_DESC)
+						printf(", message is %s", clish_xmldoc_get_err_msg(doc));
+					printf("\n");
+					res = -1;
+				}
+				clish_xmldoc_release(doc);
+
 				/* Error message */
 				if (res)
 					fprintf(stderr, CLISH_XML_ERROR_STR"File %s\n",
@@ -128,14 +178,20 @@ int clish_shell_load_scheme(clish_shell_t *this, const char *xml_path)
 				lub_string_free(filename);
 			}
 			if (res)
-				break;
+				goto error;
 		}
 		/* all done for this directory */
 		closedir(dir);
 		if (res)
-			break;
+			goto error;
 	}
+
+error:
 	lub_string_free(buffer);
+#ifdef HAVE_LIB_LIBXSLT
+	if (xslt_path)
+		clish_xslt_release(xslt);
+#endif
 
 	return res;
 }
@@ -224,34 +280,6 @@ static int process_children(clish_shell_t *shell,
 	return 0;
 }
 
-/* ------------------------------------------------------ */
-int clish_shell_xml_read(clish_shell_t *shell, const char *filename)
-{
-	int ret = -1;
-	clish_xmldoc_t *doc;
-
-	doc = clish_xmldoc_read(filename);
-
-	if (clish_xmldoc_is_valid(doc)) {
-		clish_xmlnode_t *root = clish_xmldoc_get_root(doc);
-		ret = process_node(shell, root, NULL);
-	} else {
-		int errcaps = clish_xmldoc_error_caps(doc);
-		printf("Unable to open file '%s'", filename);
-		if ((errcaps & CLISH_XMLERR_LINE) == CLISH_XMLERR_LINE)
-			printf(", at line %d", clish_xmldoc_get_err_line(doc));
-		if ((errcaps & CLISH_XMLERR_COL) == CLISH_XMLERR_COL)
-			printf(", at column %d", clish_xmldoc_get_err_col(doc));
-		if ((errcaps & CLISH_XMLERR_DESC) == CLISH_XMLERR_DESC)
-			printf(", message is %s", clish_xmldoc_get_err_msg(doc));
-		printf("\n");
-	}
-
-	clish_xmldoc_release(doc);
-
-	return ret;
-}
-
 /* ------------------------------------------------------ */
 static int process_clish_module(clish_shell_t *shell, clish_xmlnode_t *element,
 	void *parent)

+ 33 - 0
clish/shell/xmlapi.h

@@ -7,6 +7,10 @@
 #ifndef clish_xmlapi_included_h
 #define clish_xmlapi_included_h
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <errno.h>
 #include <stdio.h> /* need for FILE */
@@ -193,5 +197,34 @@ void clish_xml_release(void *p);
  */
 void clish_xmlnode_print(clish_xmlnode_t *node, FILE *out);
 
+#ifdef HAVE_LIB_XSLT
+
+/*
+ * XSLT stylesheet (opaque type)
+ * The real type is defined by the selected external API
+ */
+typedef struct clish_xslt_s clish_xslt_t;
+
+/*
+ * Load an XSLT stylesheet
+ */
+clish_xslt_t *clish_xslt_read(const char *filename);
+
+
+/* Apply XSLT stylesheet */
+clish_xmldoc_t *clish_xslt_apply(clish_xmldoc_t *xmldoc, clish_xslt_t *stylesheet);
+
+/*
+ * Release a previously opened XSLT stylesheet
+ */
+void clish_xslt_release(clish_xslt_t *stylesheet);
+
+/*
+ * Check if a stylesheet is valid (i.e. it loaded successfully)
+ */
+int clish_xslt_is_valid(clish_xslt_t *stylesheet);
+
+#endif /* HAVE_LIB_LIBXSLT */
+
 #endif /* clish_xmlapi_included_h */