2 * contrib/xml2/xslt_proc.c
4 * XSLT processing functions (requiring libxslt)
6 * John Gray, for Torchbox 2003-04-01
10 #include "executor/spi.h"
13 #include "miscadmin.h"
14 #include "utils/builtins.h"
15 #include "utils/xml.h"
21 #include <libxml/xpath.h>
22 #include <libxml/tree.h>
23 #include <libxml/xmlmemory.h>
25 /* libxslt includes */
27 #include <libxslt/xslt.h>
28 #include <libxslt/xsltInternals.h>
29 #include <libxslt/security.h>
30 #include <libxslt/transform.h>
31 #include <libxslt/xsltutils.h>
32 #endif /* USE_LIBXSLT */
37 /* declarations to come from xpath.c */
38 extern PgXmlErrorContext
*pgxml_parser_init(PgXmlStrictness strictness
);
41 static const char **parse_params(text
*paramstr
);
42 #endif /* USE_LIBXSLT */
45 PG_FUNCTION_INFO_V1(xslt_process
);
48 xslt_process(PG_FUNCTION_ARGS
)
52 text
*doct
= PG_GETARG_TEXT_PP(0);
53 text
*ssheet
= PG_GETARG_TEXT_PP(1);
57 PgXmlErrorContext
*xmlerrcxt
;
58 volatile xsltStylesheetPtr stylesheet
= NULL
;
59 volatile xmlDocPtr doctree
= NULL
;
60 volatile xmlDocPtr restree
= NULL
;
61 volatile xsltSecurityPrefsPtr xslt_sec_prefs
= NULL
;
62 volatile xsltTransformContextPtr xslt_ctxt
= NULL
;
63 volatile int resstat
= -1;
64 xmlChar
*resstr
= NULL
;
67 if (fcinfo
->nargs
== 3)
69 paramstr
= PG_GETARG_TEXT_PP(2);
70 params
= parse_params(paramstr
);
75 params
= (const char **) palloc(sizeof(char *));
80 xmlerrcxt
= pgxml_parser_init(PG_XML_STRICTNESS_LEGACY
);
85 bool xslt_sec_prefs_error
;
88 doctree
= xmlParseMemory((char *) VARDATA_ANY(doct
),
89 VARSIZE_ANY_EXHDR(doct
));
92 xml_ereport(xmlerrcxt
, ERROR
, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION
,
93 "error parsing XML document");
95 /* Same for stylesheet */
96 ssdoc
= xmlParseMemory((char *) VARDATA_ANY(ssheet
),
97 VARSIZE_ANY_EXHDR(ssheet
));
100 xml_ereport(xmlerrcxt
, ERROR
, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION
,
101 "error parsing stylesheet as XML document");
103 /* After this call we need not free ssdoc separately */
104 stylesheet
= xsltParseStylesheetDoc(ssdoc
);
106 if (stylesheet
== NULL
)
107 xml_ereport(xmlerrcxt
, ERROR
, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION
,
108 "failed to parse stylesheet");
110 xslt_ctxt
= xsltNewTransformContext(stylesheet
, doctree
);
112 xslt_sec_prefs_error
= false;
113 if ((xslt_sec_prefs
= xsltNewSecurityPrefs()) == NULL
)
114 xslt_sec_prefs_error
= true;
116 if (xsltSetSecurityPrefs(xslt_sec_prefs
, XSLT_SECPREF_READ_FILE
,
117 xsltSecurityForbid
) != 0)
118 xslt_sec_prefs_error
= true;
119 if (xsltSetSecurityPrefs(xslt_sec_prefs
, XSLT_SECPREF_WRITE_FILE
,
120 xsltSecurityForbid
) != 0)
121 xslt_sec_prefs_error
= true;
122 if (xsltSetSecurityPrefs(xslt_sec_prefs
, XSLT_SECPREF_CREATE_DIRECTORY
,
123 xsltSecurityForbid
) != 0)
124 xslt_sec_prefs_error
= true;
125 if (xsltSetSecurityPrefs(xslt_sec_prefs
, XSLT_SECPREF_READ_NETWORK
,
126 xsltSecurityForbid
) != 0)
127 xslt_sec_prefs_error
= true;
128 if (xsltSetSecurityPrefs(xslt_sec_prefs
, XSLT_SECPREF_WRITE_NETWORK
,
129 xsltSecurityForbid
) != 0)
130 xslt_sec_prefs_error
= true;
131 if (xsltSetCtxtSecurityPrefs(xslt_sec_prefs
, xslt_ctxt
) != 0)
132 xslt_sec_prefs_error
= true;
134 if (xslt_sec_prefs_error
)
136 (errmsg("could not set libxslt security preferences")));
138 restree
= xsltApplyStylesheetUser(stylesheet
, doctree
, params
,
139 NULL
, NULL
, xslt_ctxt
);
142 xml_ereport(xmlerrcxt
, ERROR
, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION
,
143 "failed to apply stylesheet");
145 resstat
= xsltSaveResultToString(&resstr
, &reslen
, restree
, stylesheet
);
151 if (xslt_ctxt
!= NULL
)
152 xsltFreeTransformContext(xslt_ctxt
);
153 if (xslt_sec_prefs
!= NULL
)
154 xsltFreeSecurityPrefs(xslt_sec_prefs
);
155 if (stylesheet
!= NULL
)
156 xsltFreeStylesheet(stylesheet
);
159 xsltCleanupGlobals();
161 pg_xml_done(xmlerrcxt
, true);
168 xsltFreeTransformContext(xslt_ctxt
);
169 xsltFreeSecurityPrefs(xslt_sec_prefs
);
170 xsltFreeStylesheet(stylesheet
);
172 xsltCleanupGlobals();
174 pg_xml_done(xmlerrcxt
, false);
176 /* XXX this is pretty dubious, really ought to throw error instead */
180 result
= cstring_to_text_with_len((char *) resstr
, reslen
);
185 PG_RETURN_TEXT_P(result
);
186 #else /* !USE_LIBXSLT */
189 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
190 errmsg("xslt_process() is not available without libxslt")));
192 #endif /* USE_LIBXSLT */
198 parse_params(text
*paramstr
)
208 pstr
= text_to_cstring(paramstr
);
210 max_params
= 20; /* must be even! */
211 params
= (const char **) palloc((max_params
+ 1) * sizeof(char *));
218 if (nparams
>= max_params
)
221 params
= (const char **) repalloc(params
,
222 (max_params
+ 1) * sizeof(char *));
224 params
[nparams
++] = pos
;
225 pos
= strstr(pos
, nvsep
);
233 /* No equal sign, so ignore this "parameter" */
238 /* since max_params is even, we still have nparams < max_params */
239 params
[nparams
++] = pos
;
240 pos
= strstr(pos
, itsep
);
250 /* Add the terminator marker; we left room for it in the palloc's */
251 params
[nparams
] = NULL
;
256 #endif /* USE_LIBXSLT */