diff options
author | Bruce Momjian <bruce@momjian.us> | 2004-03-05 03:57:58 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2004-03-05 03:57:58 +0000 |
commit | 31f4b59a464808ab0fec0ffb2eaa723321ea1af7 (patch) | |
tree | 004f71d1eb77899fa9e16ac8047189dcde6576e5 /contrib/xml2/xslt_proc.c | |
parent | adca025c9ec4b3050411eb74a5b4f9c20a4ce2b5 (diff) | |
download | postgresql-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.c | 184 |
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; + } +} |