aboutsummaryrefslogtreecommitdiff
path: root/contrib/xml2/xslt_proc.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2004-03-05 03:57:58 +0000
committerBruce Momjian <bruce@momjian.us>2004-03-05 03:57:58 +0000
commit31f4b59a464808ab0fec0ffb2eaa723321ea1af7 (patch)
tree004f71d1eb77899fa9e16ac8047189dcde6576e5 /contrib/xml2/xslt_proc.c
parentadca025c9ec4b3050411eb74a5b4f9c20a4ce2b5 (diff)
downloadpostgresql-31f4b59a464808ab0fec0ffb2eaa723321ea1af7.tar.gz
postgresql-31f4b59a464808ab0fec0ffb2eaa723321ea1af7.zip
Move new version of contrib/ xml into xml2, keep old version in /xml.
Diffstat (limited to 'contrib/xml2/xslt_proc.c')
-rw-r--r--contrib/xml2/xslt_proc.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
new file mode 100644
index 00000000000..64f97366226
--- /dev/null
+++ b/contrib/xml2/xslt_proc.c
@@ -0,0 +1,184 @@
+/* XSLT processing functions (requiring libxslt) */
+/* John Gray, for Torchbox 2003-04-01 */
+
+#include "postgres.h"
+#include "fmgr.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+
+/* libxml includes */
+
+#include <libxml/xpath.h>
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+
+/* libxslt includes */
+
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+
+/* declarations to come from xpath.c */
+
+extern void elog_error(int level, char *explain, int force);
+extern void pgxml_parser_init();
+extern xmlChar *pgxml_texttoxmlchar(text *textstring);
+
+#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
+
+/* local defs */
+static void parse_params(const char **params, text *paramstr);
+
+Datum xslt_process(PG_FUNCTION_ARGS);
+
+
+#define MAXPARAMS 20
+
+PG_FUNCTION_INFO_V1(xslt_process);
+
+Datum xslt_process(PG_FUNCTION_ARGS) {
+
+
+ const char *params[MAXPARAMS + 1]; /* +1 for the terminator */
+ xsltStylesheetPtr stylesheet = NULL;
+ xmlDocPtr doctree;
+ xmlDocPtr restree;
+ xmlDocPtr ssdoc = NULL;
+ xmlChar *resstr;
+ int resstat;
+ int reslen;
+
+ text *doct = PG_GETARG_TEXT_P(0);
+ text *ssheet = PG_GETARG_TEXT_P(1);
+ text *paramstr;
+ text *tres;
+
+
+ if (fcinfo->nargs == 3)
+ {
+ paramstr = PG_GETARG_TEXT_P(2);
+ parse_params(params,paramstr);
+ }
+ else /* No parameters */
+ {
+ params[0] = NULL;
+ }
+
+ /* Setup parser */
+ pgxml_parser_init();
+
+ /* Check to see if document is a file or a literal */
+
+ if (VARDATA(doct)[0] == '<')
+ {
+ doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct)-VARHDRSZ);
+ }
+ else
+ {
+ doctree = xmlParseFile(GET_STR(doct));
+ }
+
+ if (doctree == NULL)
+ {
+ xmlCleanupParser();
+ elog_error(ERROR,"Error parsing XML document",0);
+
+ PG_RETURN_NULL();
+ }
+
+ /* Same for stylesheet */
+ if (VARDATA(ssheet)[0] == '<')
+ {
+ ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
+ VARSIZE(ssheet)-VARHDRSZ);
+ if (ssdoc == NULL)
+ {
+ xmlFreeDoc(doctree);
+ xmlCleanupParser();
+ elog_error(ERROR,"Error parsing stylesheet as XML document",0);
+ PG_RETURN_NULL();
+ }
+
+ stylesheet = xsltParseStylesheetDoc(ssdoc);
+ }
+ else
+ {
+ stylesheet = xsltParseStylesheetFile(GET_STR(ssheet));
+ }
+
+
+ if (stylesheet == NULL)
+ {
+ xmlFreeDoc(doctree);
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+ elog_error(ERROR,"Failed to parse stylesheet",0);
+ PG_RETURN_NULL();
+ }
+
+ restree = xsltApplyStylesheet(stylesheet, doctree, params);
+ resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet);
+
+ xsltFreeStylesheet(stylesheet);
+ xmlFreeDoc(restree);
+ xmlFreeDoc(doctree);
+
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+
+ if (resstat < 0) {
+ PG_RETURN_NULL();
+ }
+
+ tres = palloc(reslen + VARHDRSZ);
+ memcpy(VARDATA(tres),resstr,reslen);
+ VARATT_SIZEP(tres) = reslen + VARHDRSZ;
+
+ PG_RETURN_TEXT_P(tres);
+}
+
+
+void parse_params(const char **params, text *paramstr)
+{
+ char *pos;
+ char *pstr;
+
+ int i;
+ char *nvsep="=";
+ char *itsep=",";
+
+ pstr = GET_STR(paramstr);
+
+ pos=pstr;
+
+ for (i=0; i < MAXPARAMS; i++)
+ {
+ params[i] = pos;
+ pos = strstr(pos,nvsep);
+ if (pos != NULL) {
+ *pos = '\0';
+ pos++;
+ } else {
+ params[i]=NULL;
+ break;
+ }
+ /* Value */
+ i++;
+ params[i]=pos;
+ pos = strstr(pos,itsep);
+ if (pos != NULL) {
+ *pos = '\0';
+ pos++;
+ } else {
+ break;
+ }
+
+ }
+ if (i < MAXPARAMS)
+ {
+ params[i+1]=NULL;
+ }
+}