1 | /*
|
---|
2 | libxslt.c: this modules implements the main part of the glue of the
|
---|
3 | * libxslt library and the Python interpreter. It provides the
|
---|
4 | * entry points where an automatically generated stub is either
|
---|
5 | * unpractical or would not match cleanly the Python model.
|
---|
6 | *
|
---|
7 | * If compiled with MERGED_MODULES, the entry point will be used to
|
---|
8 | * initialize both the libxml2 and the libxslt wrappers
|
---|
9 | *
|
---|
10 | * See Copyright for the status of this software.
|
---|
11 | *
|
---|
12 | * [email protected]
|
---|
13 | */
|
---|
14 | #include <Python.h>
|
---|
15 | /* #include "config.h" */
|
---|
16 | #include <libxml/xmlmemory.h>
|
---|
17 | #include <libxml/tree.h>
|
---|
18 | #include <libxml/xpath.h>
|
---|
19 | #include "libexslt/exslt.h"
|
---|
20 | #include "libxslt_wrap.h"
|
---|
21 | #include "libxslt-py.h"
|
---|
22 |
|
---|
23 | #include <stdio.h>
|
---|
24 |
|
---|
25 | #if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(vsnprintf)
|
---|
26 | #define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
|
---|
27 | #elif defined(XSLT_NEED_TRIO)
|
---|
28 | #include "trio.h"
|
---|
29 | #define vsnprintf trio_vsnprintf
|
---|
30 | #endif
|
---|
31 |
|
---|
32 | /* #define DEBUG */
|
---|
33 | /* #define DEBUG_XPATH */
|
---|
34 | /* #define DEBUG_ERROR */
|
---|
35 | /* #define DEBUG_MEMORY */
|
---|
36 | /* #define DEBUG_EXTENSIONS */
|
---|
37 | /* #define DEBUG_EXTENSIONS */
|
---|
38 |
|
---|
39 | void initlibxsltmod(void);
|
---|
40 |
|
---|
41 | /************************************************************************
|
---|
42 | * *
|
---|
43 | * Per type specific glue *
|
---|
44 | * *
|
---|
45 | ************************************************************************/
|
---|
46 |
|
---|
47 | PyObject *
|
---|
48 | libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr style) {
|
---|
49 | PyObject *ret;
|
---|
50 |
|
---|
51 | #ifdef DEBUG
|
---|
52 | printf("libxslt_xsltStylesheetPtrWrap: style = %p\n", style);
|
---|
53 | #endif
|
---|
54 | if (style == NULL) {
|
---|
55 | Py_INCREF(Py_None);
|
---|
56 | return(Py_None);
|
---|
57 | }
|
---|
58 | ret = PyCObject_FromVoidPtrAndDesc((void *) style,
|
---|
59 | (char *)"xsltStylesheetPtr", NULL);
|
---|
60 |
|
---|
61 | return(ret);
|
---|
62 | }
|
---|
63 |
|
---|
64 | PyObject *
|
---|
65 | libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) {
|
---|
66 | PyObject *ret;
|
---|
67 |
|
---|
68 | #ifdef DEBUG
|
---|
69 | printf("libxslt_xsltTransformContextPtrWrap: ctxt = %p\n", ctxt);
|
---|
70 | #endif
|
---|
71 | if (ctxt == NULL) {
|
---|
72 | Py_INCREF(Py_None);
|
---|
73 | return(Py_None);
|
---|
74 | }
|
---|
75 | ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt,
|
---|
76 | (char *)"xsltTransformContextPtr", NULL);
|
---|
77 | return(ret);
|
---|
78 | }
|
---|
79 |
|
---|
80 | PyObject *
|
---|
81 | libxslt_xsltElemPreCompPtrWrap(xsltElemPreCompPtr ctxt) {
|
---|
82 | PyObject *ret;
|
---|
83 |
|
---|
84 | #ifdef DEBUG
|
---|
85 | printf("libxslt_xsltElemPreCompPtrWrap: ctxt = %p\n", ctxt);
|
---|
86 | #endif
|
---|
87 | if (ctxt == NULL) {
|
---|
88 | Py_INCREF(Py_None);
|
---|
89 | return(Py_None);
|
---|
90 | }
|
---|
91 | ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt,
|
---|
92 | (char *)"xsltElemPreCompPtr", NULL);
|
---|
93 | return(ret);
|
---|
94 | }
|
---|
95 |
|
---|
96 | PyObject *
|
---|
97 | libxslt_xsltGetTransformContextHashCode(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
98 | PyObject *py_tctxt;
|
---|
99 | PyObject *ret;
|
---|
100 | long hash_code;
|
---|
101 | xsltTransformContextPtr tctxt;
|
---|
102 |
|
---|
103 | if (!PyArg_ParseTuple(args, (char *)"O:getTransformContextHashCode",
|
---|
104 | &py_tctxt))
|
---|
105 | return NULL;
|
---|
106 |
|
---|
107 | tctxt = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt);
|
---|
108 | hash_code = (long) tctxt;
|
---|
109 |
|
---|
110 | ret = PyInt_FromLong(hash_code);
|
---|
111 | return ret;
|
---|
112 | }
|
---|
113 |
|
---|
114 | PyObject *
|
---|
115 | libxslt_xsltCompareTransformContextsEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
116 |
|
---|
117 | PyObject *py_tctxt1, *py_tctxt2;
|
---|
118 | xsltTransformContextPtr tctxt1, tctxt2;
|
---|
119 |
|
---|
120 | if (!PyArg_ParseTuple(args, (char *)"OO:compareTransformContextsEqual",
|
---|
121 | &py_tctxt1, &py_tctxt2))
|
---|
122 | return NULL;
|
---|
123 |
|
---|
124 | tctxt1 = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt1);
|
---|
125 | tctxt2 = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt2);
|
---|
126 |
|
---|
127 | if ( tctxt1 == tctxt2 )
|
---|
128 | return Py_BuildValue((char *)"i", 1);
|
---|
129 | else
|
---|
130 | return Py_BuildValue((char *)"i", 0);
|
---|
131 | }
|
---|
132 |
|
---|
133 | PyObject *
|
---|
134 | libxslt_xsltGetStylesheetHashCode(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
135 | PyObject *py_style;
|
---|
136 | PyObject *ret;
|
---|
137 | long hash_code;
|
---|
138 | xsltStylesheetPtr style;
|
---|
139 |
|
---|
140 | if (!PyArg_ParseTuple(args, (char *)"O:getStylesheetHashCode",
|
---|
141 | &py_style))
|
---|
142 | return NULL;
|
---|
143 |
|
---|
144 | style = (xsltStylesheetPtr) Pystylesheet_Get(py_style);
|
---|
145 | hash_code = (long) style;
|
---|
146 |
|
---|
147 | ret = PyInt_FromLong(hash_code);
|
---|
148 | return ret;
|
---|
149 | }
|
---|
150 |
|
---|
151 |
|
---|
152 | PyObject *
|
---|
153 | libxslt_xsltCompareStylesheetsEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
154 |
|
---|
155 | PyObject *py_style1, *py_style2;
|
---|
156 | xsltStylesheetPtr style1, style2;
|
---|
157 |
|
---|
158 | if (!PyArg_ParseTuple(args, (char *)"OO:compareStylesheetsEqual",
|
---|
159 | &py_style1, &py_style2))
|
---|
160 | return NULL;
|
---|
161 |
|
---|
162 | style1 = (xsltStylesheetPtr) Pystylesheet_Get(py_style1);
|
---|
163 | style2 = (xsltStylesheetPtr) Pystylesheet_Get(py_style2);
|
---|
164 |
|
---|
165 | if ( style1 == style2 )
|
---|
166 | return Py_BuildValue((char *)"i", 1);
|
---|
167 | else
|
---|
168 | return Py_BuildValue((char *)"i", 0);
|
---|
169 | }
|
---|
170 |
|
---|
171 | /************************************************************************
|
---|
172 | * *
|
---|
173 | * Extending the API *
|
---|
174 | * *
|
---|
175 | ************************************************************************/
|
---|
176 |
|
---|
177 | static xmlHashTablePtr libxslt_extModuleFunctions = NULL;
|
---|
178 | static xmlHashTablePtr libxslt_extModuleElements = NULL;
|
---|
179 | static xmlHashTablePtr libxslt_extModuleElementPreComp = NULL;
|
---|
180 |
|
---|
181 | static void
|
---|
182 | deallocateCallback(void *payload, xmlChar *name ATTRIBUTE_UNUSED) {
|
---|
183 | PyObject *function = (PyObject *) payload;
|
---|
184 |
|
---|
185 | #ifdef DEBUG_EXTENSIONS
|
---|
186 | printf("deallocateCallback(%s) called\n", name);
|
---|
187 | #endif
|
---|
188 |
|
---|
189 | Py_XDECREF(function);
|
---|
190 | }
|
---|
191 |
|
---|
192 | static void
|
---|
193 | deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) {
|
---|
194 | PyObject *class = (PyObject *) payload;
|
---|
195 |
|
---|
196 | #ifdef DEBUG_EXTENSIONS
|
---|
197 | printf("deallocateClasse(%s) called\n", name);
|
---|
198 | #endif
|
---|
199 |
|
---|
200 | Py_XDECREF(class);
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 | /**
|
---|
205 | * libxslt_xsltElementPreCompCallback
|
---|
206 | * @style: the stylesheet
|
---|
207 | * @inst: the instruction in the stylesheet
|
---|
208 | *
|
---|
209 | * Callback for preprocessing of a custom element
|
---|
210 | */
|
---|
211 | static xsltElemPreCompPtr
|
---|
212 | libxslt_xsltElementPreCompCallback(xsltStylesheetPtr style, xmlNodePtr inst,
|
---|
213 | xsltTransformFunction function) {
|
---|
214 | xsltElemPreCompPtr ret;
|
---|
215 | const xmlChar *name;
|
---|
216 | PyObject *args;
|
---|
217 | PyObject *result;
|
---|
218 | PyObject *pyobj_element_f;
|
---|
219 | PyObject *pyobj_precomp_f;
|
---|
220 |
|
---|
221 | const xmlChar *ns_uri;
|
---|
222 |
|
---|
223 |
|
---|
224 | #ifdef DEBUG_EXTENSIONS
|
---|
225 | printf("libxslt_xsltElementPreCompCallback called\n");
|
---|
226 | #endif
|
---|
227 |
|
---|
228 | if (style == NULL) {
|
---|
229 | xsltTransformError(NULL, NULL, inst,
|
---|
230 | "libxslt_xsltElementPreCompCallback: no transformation context\n");
|
---|
231 | return (NULL);
|
---|
232 | }
|
---|
233 |
|
---|
234 | if (inst == NULL) {
|
---|
235 | xsltTransformError(NULL, style, inst,
|
---|
236 | "libxslt_xsltElementPreCompCallback: no instruction\n");
|
---|
237 | if (style != NULL) style->errors++;
|
---|
238 | return (NULL);
|
---|
239 | }
|
---|
240 |
|
---|
241 | if (style == NULL)
|
---|
242 | return (NULL);
|
---|
243 |
|
---|
244 | if (inst != NULL && inst->ns != NULL) {
|
---|
245 | name = inst->name;
|
---|
246 | ns_uri = inst->ns->href;
|
---|
247 | } else {
|
---|
248 | xsltTransformError(NULL, style, inst,
|
---|
249 | "libxslt_xsltElementPreCompCallback: internal error bad parameter\n");
|
---|
250 | printf("libxslt_xsltElementPreCompCallback: internal error bad parameter\n");
|
---|
251 | if (style != NULL) style->errors++;
|
---|
252 | return (NULL);
|
---|
253 | }
|
---|
254 |
|
---|
255 | /*
|
---|
256 | * Find the functions, they should be there it was there at lookup
|
---|
257 | */
|
---|
258 | pyobj_precomp_f = xmlHashLookup2(libxslt_extModuleElementPreComp,
|
---|
259 | name, ns_uri);
|
---|
260 | if (pyobj_precomp_f == NULL) {
|
---|
261 | xsltTransformError(NULL, style, inst,
|
---|
262 | "libxslt_xsltElementPreCompCallback: internal error, could not find precompile python function!\n");
|
---|
263 | if (style != NULL) style->errors++;
|
---|
264 | return (NULL);
|
---|
265 | }
|
---|
266 |
|
---|
267 | pyobj_element_f = xmlHashLookup2(libxslt_extModuleElements,
|
---|
268 | name, ns_uri);
|
---|
269 | if (pyobj_element_f == NULL) {
|
---|
270 | xsltTransformError(NULL, style, inst,
|
---|
271 | "libxslt_xsltElementPreCompCallback: internal error, could not find element python function!\n");
|
---|
272 | if (style != NULL) style->errors++;
|
---|
273 | return (NULL);
|
---|
274 | }
|
---|
275 |
|
---|
276 | args = Py_BuildValue((char *)"(OOO)",
|
---|
277 | libxslt_xsltStylesheetPtrWrap(style),
|
---|
278 | libxml_xmlNodePtrWrap(inst),
|
---|
279 | pyobj_element_f);
|
---|
280 |
|
---|
281 | Py_INCREF(pyobj_precomp_f); /* Protect refcount against reentrant manipulation of callback hash */
|
---|
282 | result = PyEval_CallObject(pyobj_precomp_f, args);
|
---|
283 | Py_DECREF(pyobj_precomp_f);
|
---|
284 | Py_DECREF(args);
|
---|
285 |
|
---|
286 | /* FIXME allow callbacks to return meaningful information to modify compile process */
|
---|
287 | /* If error, do we need to check the result and throw exception? */
|
---|
288 |
|
---|
289 | Py_XDECREF(result);
|
---|
290 |
|
---|
291 | ret = xsltNewElemPreComp (style, inst, function);
|
---|
292 | return (ret);
|
---|
293 | }
|
---|
294 |
|
---|
295 |
|
---|
296 | static void
|
---|
297 | libxslt_xsltElementTransformCallback(xsltTransformContextPtr ctxt,
|
---|
298 | xmlNodePtr node,
|
---|
299 | xmlNodePtr inst,
|
---|
300 | xsltElemPreCompPtr comp)
|
---|
301 | {
|
---|
302 | PyObject *args, *result;
|
---|
303 | PyObject *func = NULL;
|
---|
304 | const xmlChar *name;
|
---|
305 | const xmlChar *ns_uri;
|
---|
306 |
|
---|
307 | if (ctxt == NULL)
|
---|
308 | return;
|
---|
309 |
|
---|
310 | if (inst != NULL && inst->name != NULL && inst->ns != NULL && inst->ns->href != NULL) {
|
---|
311 | name = inst->name;
|
---|
312 | ns_uri = inst->ns->href;
|
---|
313 | } else {
|
---|
314 | printf("libxslt_xsltElementTransformCallback: internal error bad parameter\n");
|
---|
315 | return;
|
---|
316 | }
|
---|
317 |
|
---|
318 | #ifdef DEBUG_EXTENSIONS
|
---|
319 | printf("libxslt_xsltElementTransformCallback called name %s URI %s\n", name, ns_uri);
|
---|
320 | #endif
|
---|
321 |
|
---|
322 | /*
|
---|
323 | * Find the function, it should be there it was there at lookup
|
---|
324 | */
|
---|
325 | func = xmlHashLookup2(libxslt_extModuleElements,
|
---|
326 | name, ns_uri);
|
---|
327 | if (func == NULL) {
|
---|
328 | printf("libxslt_xsltElementTransformCallback: internal error %s not found !\n",
|
---|
329 | name);
|
---|
330 | return;
|
---|
331 | }
|
---|
332 |
|
---|
333 | args = Py_BuildValue((char *)"OOOO",
|
---|
334 | libxslt_xsltTransformContextPtrWrap(ctxt),
|
---|
335 | libxml_xmlNodePtrWrap(node),
|
---|
336 | libxml_xmlNodePtrWrap(inst),
|
---|
337 | libxslt_xsltElemPreCompPtrWrap(comp));
|
---|
338 |
|
---|
339 | Py_INCREF(func); /* Protect refcount against reentrant manipulation of callback hash */
|
---|
340 | result = PyEval_CallObject(func, args);
|
---|
341 | Py_DECREF(func);
|
---|
342 | Py_DECREF(args);
|
---|
343 |
|
---|
344 | /* FIXME Check result of callobject and set exception if fail */
|
---|
345 |
|
---|
346 | Py_XDECREF(result);
|
---|
347 | }
|
---|
348 |
|
---|
349 | PyObject *
|
---|
350 | libxslt_xsltRegisterExtModuleElement(PyObject *self ATTRIBUTE_UNUSED,
|
---|
351 | PyObject *args) {
|
---|
352 | PyObject *py_retval;
|
---|
353 | int ret = 0;
|
---|
354 | xmlChar *name;
|
---|
355 | xmlChar *ns_uri;
|
---|
356 | PyObject *pyobj_element_f;
|
---|
357 | PyObject *pyobj_precomp_f;
|
---|
358 |
|
---|
359 | #ifdef DEBUG_EXTENSIONS
|
---|
360 | printf("libxslt_xsltRegisterExtModuleElement called\n",
|
---|
361 | name, ns_uri);
|
---|
362 | #endif
|
---|
363 |
|
---|
364 | if (!PyArg_ParseTuple(args, (char *)"szOO:registerExtModuleElement",
|
---|
365 | &name, &ns_uri, &pyobj_precomp_f, &pyobj_element_f))
|
---|
366 | return(NULL);
|
---|
367 |
|
---|
368 | if ((name == NULL) || (pyobj_element_f == NULL) || (pyobj_precomp_f == NULL)) {
|
---|
369 | py_retval = libxml_intWrap(-1);
|
---|
370 | return(py_retval);
|
---|
371 | }
|
---|
372 |
|
---|
373 | #ifdef DEBUG_EXTENSIONS
|
---|
374 | printf("libxslt_xsltRegisterExtModuleElement(%s, %s) called\n",
|
---|
375 | name, ns_uri);
|
---|
376 | #endif
|
---|
377 |
|
---|
378 | if (libxslt_extModuleElements == NULL)
|
---|
379 | libxslt_extModuleElements = xmlHashCreate(10);
|
---|
380 |
|
---|
381 | if (libxslt_extModuleElementPreComp == NULL)
|
---|
382 | libxslt_extModuleElementPreComp = xmlHashCreate(10);
|
---|
383 |
|
---|
384 | if (libxslt_extModuleElements == NULL || libxslt_extModuleElementPreComp == NULL) {
|
---|
385 | py_retval = libxml_intWrap(-1);
|
---|
386 | return(py_retval);
|
---|
387 | }
|
---|
388 |
|
---|
389 | ret = xmlHashAddEntry2(libxslt_extModuleElements, name, ns_uri, pyobj_element_f);
|
---|
390 | if (ret != 0) {
|
---|
391 | py_retval = libxml_intWrap(-1);
|
---|
392 | return(py_retval);
|
---|
393 | }
|
---|
394 | Py_XINCREF(pyobj_element_f);
|
---|
395 |
|
---|
396 | ret = xmlHashAddEntry2(libxslt_extModuleElementPreComp, name, ns_uri, pyobj_precomp_f);
|
---|
397 | if (ret != 0) {
|
---|
398 | xmlHashRemoveEntry2(libxslt_extModuleElements, name, ns_uri, deallocateCallback);
|
---|
399 | py_retval = libxml_intWrap(-1);
|
---|
400 | return(py_retval);
|
---|
401 | }
|
---|
402 | Py_XINCREF(pyobj_precomp_f);
|
---|
403 |
|
---|
404 | ret = xsltRegisterExtModuleElement(name, ns_uri,
|
---|
405 | libxslt_xsltElementPreCompCallback,
|
---|
406 | libxslt_xsltElementTransformCallback);
|
---|
407 | py_retval = libxml_intWrap((int) ret);
|
---|
408 | return(py_retval);
|
---|
409 | }
|
---|
410 | static void
|
---|
411 | libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) {
|
---|
412 | PyObject *list, *cur, *result;
|
---|
413 | xmlXPathObjectPtr obj;
|
---|
414 | xmlXPathContextPtr rctxt;
|
---|
415 | PyObject *current_function = NULL;
|
---|
416 | const xmlChar *name;
|
---|
417 | const xmlChar *ns_uri;
|
---|
418 | int i;
|
---|
419 |
|
---|
420 | if (ctxt == NULL)
|
---|
421 | return;
|
---|
422 | rctxt = ctxt->context;
|
---|
423 | if (rctxt == NULL)
|
---|
424 | return;
|
---|
425 | name = rctxt->function;
|
---|
426 | ns_uri = rctxt->functionURI;
|
---|
427 | #ifdef DEBUG_XPATH
|
---|
428 | printf("libxslt_xmlXPathFuncCallback called name %s URI %s\n", name, ns_uri);
|
---|
429 | #endif
|
---|
430 |
|
---|
431 | /*
|
---|
432 | * Find the function, it should be there it was there at lookup
|
---|
433 | */
|
---|
434 | current_function = xmlHashLookup2(libxslt_extModuleFunctions,
|
---|
435 | name, ns_uri);
|
---|
436 | if (current_function == NULL) {
|
---|
437 | printf("libxslt_xmlXPathFuncCallback: internal error %s not found !\n",
|
---|
438 | name);
|
---|
439 | return;
|
---|
440 | }
|
---|
441 |
|
---|
442 | list = PyTuple_New(nargs + 1);
|
---|
443 | PyTuple_SetItem(list, 0, libxml_xmlXPathParserContextPtrWrap(ctxt));
|
---|
444 | for (i = nargs - 1;i >= 0;i--) {
|
---|
445 | obj = valuePop(ctxt);
|
---|
446 | cur = libxml_xmlXPathObjectPtrWrap(obj);
|
---|
447 | PyTuple_SetItem(list, i + 1, cur);
|
---|
448 | }
|
---|
449 |
|
---|
450 | Py_INCREF(current_function);
|
---|
451 | result = PyEval_CallObject(current_function, list);
|
---|
452 | Py_DECREF(current_function);
|
---|
453 | Py_DECREF(list);
|
---|
454 |
|
---|
455 | /* Check for null in case of exception */
|
---|
456 | if (result != NULL) {
|
---|
457 | obj = libxml_xmlXPathObjectPtrConvert(result);
|
---|
458 | valuePush(ctxt, obj);
|
---|
459 | }
|
---|
460 | }
|
---|
461 |
|
---|
462 | PyObject *
|
---|
463 | libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED,
|
---|
464 | PyObject *args) {
|
---|
465 | PyObject *py_retval;
|
---|
466 | int ret = 0;
|
---|
467 | xmlChar *name;
|
---|
468 | xmlChar *ns_uri;
|
---|
469 | PyObject *pyobj_f;
|
---|
470 |
|
---|
471 | if (!PyArg_ParseTuple(args, (char *)"szO:registerExtModuleFunction",
|
---|
472 | &name, &ns_uri, &pyobj_f))
|
---|
473 | return(NULL);
|
---|
474 |
|
---|
475 | if ((name == NULL) || (pyobj_f == NULL)) {
|
---|
476 | py_retval = libxml_intWrap(-1);
|
---|
477 | return(py_retval);
|
---|
478 | }
|
---|
479 |
|
---|
480 | #ifdef DEBUG_XPATH
|
---|
481 | printf("libxslt_xsltRegisterExtModuleFunction(%s, %s) called\n",
|
---|
482 | name, ns_uri);
|
---|
483 | #endif
|
---|
484 |
|
---|
485 | if (libxslt_extModuleFunctions == NULL)
|
---|
486 | libxslt_extModuleFunctions = xmlHashCreate(10);
|
---|
487 | if (libxslt_extModuleFunctions == NULL) {
|
---|
488 | py_retval = libxml_intWrap(-1);
|
---|
489 | return(py_retval);
|
---|
490 | }
|
---|
491 | ret = xmlHashAddEntry2(libxslt_extModuleFunctions, name, ns_uri, pyobj_f);
|
---|
492 | if (ret != 0) {
|
---|
493 | py_retval = libxml_intWrap(-1);
|
---|
494 | return(py_retval);
|
---|
495 | }
|
---|
496 | Py_XINCREF(pyobj_f);
|
---|
497 |
|
---|
498 | ret = xsltRegisterExtModuleFunction(name, ns_uri,
|
---|
499 | libxslt_xmlXPathFuncCallback);
|
---|
500 | py_retval = libxml_intWrap((int) ret);
|
---|
501 | return(py_retval);
|
---|
502 | }
|
---|
503 |
|
---|
504 |
|
---|
505 | /************************************************************************
|
---|
506 | * *
|
---|
507 | * Document loading front-ends *
|
---|
508 | * *
|
---|
509 | ************************************************************************/
|
---|
510 |
|
---|
511 | static PyObject *pythonDocLoaderObject = NULL;
|
---|
512 |
|
---|
513 | static xmlDocPtr
|
---|
514 | pythonDocLoaderFuncWrapper(const xmlChar * URI, xmlDictPtr dict, int options,
|
---|
515 | void *ctxt ATTRIBUTE_UNUSED,
|
---|
516 | xsltLoadType type ATTRIBUTE_UNUSED)
|
---|
517 | {
|
---|
518 | xmlParserCtxtPtr pctxt;
|
---|
519 | xmlDocPtr doc=NULL;
|
---|
520 |
|
---|
521 | pctxt = xmlNewParserCtxt();
|
---|
522 | if (pctxt == NULL)
|
---|
523 | return(NULL);
|
---|
524 | if ((dict != NULL) && (pctxt->dict != NULL)) {
|
---|
525 | xmlDictFree(pctxt->dict);
|
---|
526 | pctxt->dict = NULL;
|
---|
527 | }
|
---|
528 | if (dict != NULL) {
|
---|
529 | pctxt->dict = dict;
|
---|
530 | xmlDictReference(pctxt->dict);
|
---|
531 | #ifdef WITH_XSLT_DEBUG
|
---|
532 | xsltGenericDebug(xsltGenericDebugContext,
|
---|
533 | "Reusing dictionary for document\n");
|
---|
534 | #endif
|
---|
535 | }
|
---|
536 | xmlCtxtUseOptions(pctxt, options);
|
---|
537 |
|
---|
538 | /*
|
---|
539 | * Now pass to python the URI, the xsltParserContext and the context
|
---|
540 | * (either a transformContext or a stylesheet) and get back an xmlDocPtr
|
---|
541 | */
|
---|
542 | if (pythonDocLoaderObject != NULL) {
|
---|
543 | PyObject *ctxtobj, *pctxtobj, *result;
|
---|
544 | pctxtobj = libxml_xmlParserCtxtPtrWrap(pctxt);
|
---|
545 |
|
---|
546 | if (type == XSLT_LOAD_DOCUMENT) {
|
---|
547 | ctxtobj = libxslt_xsltTransformContextPtrWrap(ctxt);
|
---|
548 | result = PyObject_CallFunction(pythonDocLoaderObject,
|
---|
549 | (char *) "(sOOi)", URI, pctxtobj, ctxtobj, 0);
|
---|
550 | }
|
---|
551 | else {
|
---|
552 | ctxtobj = libxslt_xsltStylesheetPtrWrap(ctxt);
|
---|
553 | result = PyObject_CallFunction(pythonDocLoaderObject,
|
---|
554 | (char *) "(sOOi)", URI, pctxtobj, ctxtobj, 1);
|
---|
555 | }
|
---|
556 |
|
---|
557 | Py_XDECREF(pctxtobj);
|
---|
558 |
|
---|
559 | if (result != NULL) {
|
---|
560 | /*
|
---|
561 | * The return value should be the document
|
---|
562 | * Should we test it somehow before getting the C object from it?
|
---|
563 | */
|
---|
564 | PyObject *py_doc = PyObject_GetAttrString(result, (char *) "_o");
|
---|
565 | doc = (xmlDocPtr) PyxmlNode_Get(py_doc);
|
---|
566 | /* do we have to DECCREF the result?? */
|
---|
567 | }
|
---|
568 | }
|
---|
569 |
|
---|
570 | if (! pctxt->wellFormed) {
|
---|
571 | if (doc != NULL) {
|
---|
572 | xmlFreeDoc(doc);
|
---|
573 | doc = NULL;
|
---|
574 | }
|
---|
575 | if (pctxt->myDoc != NULL) {
|
---|
576 | xmlFreeDoc(pctxt->myDoc);
|
---|
577 | pctxt->myDoc = NULL;
|
---|
578 | }
|
---|
579 | }
|
---|
580 | /*
|
---|
581 | * xmlFreeParserCtxt(pctxt);
|
---|
582 | * libc complains about double free-ing with this line
|
---|
583 | */
|
---|
584 |
|
---|
585 | return(doc);
|
---|
586 | }
|
---|
587 |
|
---|
588 |
|
---|
589 | PyObject *
|
---|
590 | libxslt_xsltSetLoaderFunc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
591 | PyObject *py_retval;
|
---|
592 | PyObject *loader;
|
---|
593 |
|
---|
594 | if (!PyArg_ParseTuple(args, (char *)"O:libxslt_xsltSetLoaderFunc",
|
---|
595 | &loader))
|
---|
596 | return(NULL);
|
---|
597 |
|
---|
598 | pythonDocLoaderObject = loader;
|
---|
599 | xsltSetLoaderFunc(pythonDocLoaderFuncWrapper);
|
---|
600 |
|
---|
601 | py_retval = PyInt_FromLong(0);
|
---|
602 | return(py_retval);
|
---|
603 | }
|
---|
604 |
|
---|
605 | PyObject *
|
---|
606 | libxslt_xsltGetLoaderFunc(void) {
|
---|
607 | PyObject *py_retval;
|
---|
608 |
|
---|
609 | py_retval = pythonDocLoaderObject;
|
---|
610 | return(py_retval);
|
---|
611 | }
|
---|
612 |
|
---|
613 |
|
---|
614 | /************************************************************************
|
---|
615 | * *
|
---|
616 | * Some customized front-ends *
|
---|
617 | * *
|
---|
618 | ************************************************************************/
|
---|
619 |
|
---|
620 | PyObject *
|
---|
621 | libxslt_xsltNewTransformContext(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
622 | PyObject *py_retval;
|
---|
623 | PyObject *pyobj_style;
|
---|
624 | PyObject *pyobj_doc;
|
---|
625 | xsltStylesheetPtr style;
|
---|
626 | xmlDocPtr doc;
|
---|
627 | xsltTransformContextPtr c_retval;
|
---|
628 |
|
---|
629 | if (!PyArg_ParseTuple(args, (char *) "OO:xsltNewTransformContext",
|
---|
630 | &pyobj_style, &pyobj_doc))
|
---|
631 | return(NULL);
|
---|
632 |
|
---|
633 | style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
|
---|
634 | doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
|
---|
635 |
|
---|
636 | c_retval = xsltNewTransformContext(style, doc);
|
---|
637 | py_retval = libxslt_xsltTransformContextPtrWrap((xsltTransformContextPtr) c_retval);
|
---|
638 | return (py_retval);
|
---|
639 | }
|
---|
640 |
|
---|
641 | PyObject *
|
---|
642 | libxslt_xsltFreeTransformContext(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
643 | PyObject *py_tctxt;
|
---|
644 | xsltTransformContextPtr tctxt;
|
---|
645 |
|
---|
646 | if (!PyArg_ParseTuple(args, (char *) "O:xsltFreeTransformContext", &py_tctxt))
|
---|
647 | return(NULL);
|
---|
648 |
|
---|
649 | tctxt = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt);
|
---|
650 | xsltFreeTransformContext(tctxt);
|
---|
651 |
|
---|
652 | /* Return None */
|
---|
653 | Py_INCREF(Py_None);
|
---|
654 | return(Py_None);
|
---|
655 | }
|
---|
656 |
|
---|
657 | PyObject *
|
---|
658 | libxslt_xsltApplyStylesheetUser(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
659 | PyObject *py_retval;
|
---|
660 | xmlDocPtr c_retval;
|
---|
661 | xsltStylesheetPtr style;
|
---|
662 | PyObject *pyobj_style;
|
---|
663 | xmlDocPtr doc;
|
---|
664 | xsltTransformContextPtr transformCtxt;
|
---|
665 | PyObject *pyobj_doc;
|
---|
666 | PyObject *pyobj_params;
|
---|
667 | PyObject *pyobj_transformCtxt;
|
---|
668 | const char **params = NULL;
|
---|
669 | int len = 0, i = 0, j;
|
---|
670 | PyObject *name;
|
---|
671 | PyObject *value;
|
---|
672 |
|
---|
673 | if (!PyArg_ParseTuple(args, (char *) "OOOO:xsltApplyStylesheetUser",
|
---|
674 | &pyobj_style, &pyobj_doc, &pyobj_params, &pyobj_transformCtxt))
|
---|
675 | return(NULL);
|
---|
676 |
|
---|
677 | if (pyobj_params != Py_None) {
|
---|
678 | if (PyDict_Check(pyobj_params)) {
|
---|
679 | len = PyDict_Size(pyobj_params);
|
---|
680 | if (len > 0) {
|
---|
681 | params = (const char **) xmlMalloc((len + 1) * 2 *
|
---|
682 | sizeof(char *));
|
---|
683 | if (params == NULL) {
|
---|
684 | printf("libxslt_xsltApplyStylesheet: out of memory\n");
|
---|
685 | Py_INCREF(Py_None);
|
---|
686 | return(Py_None);
|
---|
687 | }
|
---|
688 | j = 0;
|
---|
689 | while (PyDict_Next(pyobj_params, &i, &name, &value)) {
|
---|
690 | const char *tmp;
|
---|
691 | int size;
|
---|
692 |
|
---|
693 | tmp = PyString_AS_STRING(name);
|
---|
694 | size = PyString_GET_SIZE(name);
|
---|
695 | params[j * 2] = (char *) xmlCharStrndup(tmp, size);
|
---|
696 | if (PyString_Check(value)) {
|
---|
697 | tmp = PyString_AS_STRING(value);
|
---|
698 | size = PyString_GET_SIZE(value);
|
---|
699 | params[(j * 2) + 1] = (char *)
|
---|
700 | xmlCharStrndup(tmp, size);
|
---|
701 | } else {
|
---|
702 | params[(j * 2) + 1] = NULL;
|
---|
703 | }
|
---|
704 | j = j + 1;
|
---|
705 | }
|
---|
706 | params[j * 2] = NULL;
|
---|
707 | params[(j * 2) + 1] = NULL;
|
---|
708 | }
|
---|
709 | } else {
|
---|
710 | printf("libxslt_xsltApplyStylesheet: parameters not a dict\n");
|
---|
711 | Py_INCREF(Py_None);
|
---|
712 | return(Py_None);
|
---|
713 | }
|
---|
714 | }
|
---|
715 | style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
|
---|
716 | doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
|
---|
717 | transformCtxt = (xsltTransformContextPtr) PytransformCtxt_Get(pyobj_transformCtxt);
|
---|
718 |
|
---|
719 | c_retval = xsltApplyStylesheetUser(style, doc, params, NULL, NULL, transformCtxt);
|
---|
720 | py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval);
|
---|
721 | if (params != NULL) {
|
---|
722 | if (len > 0) {
|
---|
723 | for (i = 0;i < 2 * len;i++) {
|
---|
724 | if (params[i] != NULL)
|
---|
725 | xmlFree((char *)params[i]);
|
---|
726 | }
|
---|
727 | xmlFree(params);
|
---|
728 | }
|
---|
729 | }
|
---|
730 | return(py_retval);
|
---|
731 | }
|
---|
732 |
|
---|
733 | PyObject *
|
---|
734 | libxslt_xsltApplyStylesheet(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
735 | PyObject *py_retval;
|
---|
736 | xmlDocPtr c_retval;
|
---|
737 | xsltStylesheetPtr style;
|
---|
738 | PyObject *pyobj_style;
|
---|
739 | xmlDocPtr doc;
|
---|
740 | PyObject *pyobj_doc;
|
---|
741 | PyObject *pyobj_params;
|
---|
742 | const char **params = NULL;
|
---|
743 | int len = 0, i = 0, j;
|
---|
744 | PyObject *name;
|
---|
745 | PyObject *value;
|
---|
746 |
|
---|
747 | if (!PyArg_ParseTuple(args, (char *) "OOO:xsltApplyStylesheet",
|
---|
748 | &pyobj_style, &pyobj_doc, &pyobj_params))
|
---|
749 | return(NULL);
|
---|
750 |
|
---|
751 | if (pyobj_params != Py_None) {
|
---|
752 | if (PyDict_Check(pyobj_params)) {
|
---|
753 | len = PyDict_Size(pyobj_params);
|
---|
754 | if (len > 0) {
|
---|
755 | params = (const char **) xmlMalloc((len + 1) * 2 *
|
---|
756 | sizeof(char *));
|
---|
757 | if (params == NULL) {
|
---|
758 | printf("libxslt_xsltApplyStylesheet: out of memory\n");
|
---|
759 | Py_INCREF(Py_None);
|
---|
760 | return(Py_None);
|
---|
761 | }
|
---|
762 | j = 0;
|
---|
763 | while (PyDict_Next(pyobj_params, &i, &name, &value)) {
|
---|
764 | const char *tmp;
|
---|
765 | int size;
|
---|
766 |
|
---|
767 | tmp = PyString_AS_STRING(name);
|
---|
768 | size = PyString_GET_SIZE(name);
|
---|
769 | params[j * 2] = (char *) xmlCharStrndup(tmp, size);
|
---|
770 | if (PyString_Check(value)) {
|
---|
771 | tmp = PyString_AS_STRING(value);
|
---|
772 | size = PyString_GET_SIZE(value);
|
---|
773 | params[(j * 2) + 1] = (char *)
|
---|
774 | xmlCharStrndup(tmp, size);
|
---|
775 | } else {
|
---|
776 | params[(j * 2) + 1] = NULL;
|
---|
777 | }
|
---|
778 | j = j + 1;
|
---|
779 | }
|
---|
780 | params[j * 2] = NULL;
|
---|
781 | params[(j * 2) + 1] = NULL;
|
---|
782 | }
|
---|
783 | } else {
|
---|
784 | printf("libxslt_xsltApplyStylesheet: parameters not a dict\n");
|
---|
785 | Py_INCREF(Py_None);
|
---|
786 | return(Py_None);
|
---|
787 | }
|
---|
788 | }
|
---|
789 | style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
|
---|
790 | doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
|
---|
791 |
|
---|
792 | c_retval = xsltApplyStylesheet(style, doc, params);
|
---|
793 | py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval);
|
---|
794 | if (params != NULL) {
|
---|
795 | if (len > 0) {
|
---|
796 | for (i = 0;i < 2 * len;i++) {
|
---|
797 | if (params[i] != NULL)
|
---|
798 | xmlFree((char *)params[i]);
|
---|
799 | }
|
---|
800 | xmlFree(params);
|
---|
801 | }
|
---|
802 | }
|
---|
803 | return(py_retval);
|
---|
804 | }
|
---|
805 |
|
---|
806 | PyObject *
|
---|
807 | libxslt_xsltSaveResultToString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
---|
808 | PyObject *py_retval; /* our final return value, a python string */
|
---|
809 | xmlChar *buffer;
|
---|
810 | int size = 0;
|
---|
811 | int emitted = 0;
|
---|
812 | xmlDocPtr result;
|
---|
813 | PyObject *pyobj_result;
|
---|
814 | xsltStylesheetPtr style;
|
---|
815 | PyObject *pyobj_style;
|
---|
816 |
|
---|
817 | if (!PyArg_ParseTuple(args, (char *)"OO:xsltSaveResultToString", &pyobj_style, &pyobj_result))
|
---|
818 | goto FAIL;
|
---|
819 | result = (xmlDocPtr) PyxmlNode_Get(pyobj_result);
|
---|
820 | style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
|
---|
821 |
|
---|
822 |
|
---|
823 | /* FIXME: We should probably add more restrictive error checking
|
---|
824 | * and raise an error instead of "just" returning NULL.
|
---|
825 | * FIXME: Documentation and code for xsltSaveResultToString diff
|
---|
826 | * -> emmitted will never be positive non-null.
|
---|
827 | */
|
---|
828 | emitted = xsltSaveResultToString(&buffer, &size, result, style);
|
---|
829 | if(!buffer || emitted < 0)
|
---|
830 | goto FAIL;
|
---|
831 | /* We haven't tested the aberrant case of a transformation that
|
---|
832 | * renders to an empty string. For now we try to play it save.
|
---|
833 | */
|
---|
834 | if(size)
|
---|
835 | {
|
---|
836 | buffer[size] = '\0';
|
---|
837 | py_retval = PyString_FromString((char *) buffer);
|
---|
838 | xmlFree(buffer);
|
---|
839 | }
|
---|
840 | else
|
---|
841 | py_retval = PyString_FromString("");
|
---|
842 | return(py_retval);
|
---|
843 | FAIL:
|
---|
844 | return(0);
|
---|
845 | }
|
---|
846 |
|
---|
847 |
|
---|
848 | /************************************************************************
|
---|
849 | * *
|
---|
850 | * Error message callback *
|
---|
851 | * *
|
---|
852 | ************************************************************************/
|
---|
853 |
|
---|
854 | static PyObject *libxslt_xsltPythonErrorFuncHandler = NULL;
|
---|
855 | static PyObject *libxslt_xsltPythonErrorFuncCtxt = NULL;
|
---|
856 |
|
---|
857 | static void
|
---|
858 | libxslt_xsltErrorFuncHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg,
|
---|
859 | ...)
|
---|
860 | {
|
---|
861 | int size;
|
---|
862 | int chars;
|
---|
863 | char *larger;
|
---|
864 | va_list ap;
|
---|
865 | char *str;
|
---|
866 | PyObject *list;
|
---|
867 | PyObject *message;
|
---|
868 | PyObject *result;
|
---|
869 |
|
---|
870 | #ifdef DEBUG_ERROR
|
---|
871 | printf("libxslt_xsltErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
|
---|
872 | #endif
|
---|
873 |
|
---|
874 |
|
---|
875 | if (libxslt_xsltPythonErrorFuncHandler == NULL) {
|
---|
876 | va_start(ap, msg);
|
---|
877 | vfprintf(stderr, msg, ap);
|
---|
878 | va_end(ap);
|
---|
879 | } else {
|
---|
880 | str = (char *) xmlMalloc(150);
|
---|
881 | if (str == NULL)
|
---|
882 | return;
|
---|
883 |
|
---|
884 | size = 150;
|
---|
885 |
|
---|
886 | while (1) {
|
---|
887 | va_start(ap, msg);
|
---|
888 | chars = vsnprintf(str, size, msg, ap);
|
---|
889 | va_end(ap);
|
---|
890 | if ((chars > -1) && (chars < size))
|
---|
891 | break;
|
---|
892 | if (chars > -1)
|
---|
893 | size += chars + 1;
|
---|
894 | else
|
---|
895 | size += 100;
|
---|
896 | if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
|
---|
897 | xmlFree(str);
|
---|
898 | return;
|
---|
899 | }
|
---|
900 | str = larger;
|
---|
901 | }
|
---|
902 |
|
---|
903 | list = PyTuple_New(2);
|
---|
904 | PyTuple_SetItem(list, 0, libxslt_xsltPythonErrorFuncCtxt);
|
---|
905 | Py_XINCREF(libxslt_xsltPythonErrorFuncCtxt);
|
---|
906 | message = libxml_charPtrWrap(str);
|
---|
907 | PyTuple_SetItem(list, 1, message);
|
---|
908 | result = PyEval_CallObject(libxslt_xsltPythonErrorFuncHandler, list);
|
---|
909 | Py_XDECREF(list);
|
---|
910 | Py_XDECREF(result);
|
---|
911 | }
|
---|
912 | }
|
---|
913 |
|
---|
914 | static void
|
---|
915 | libxslt_xsltErrorInitialize(void)
|
---|
916 | {
|
---|
917 | #ifdef DEBUG_ERROR
|
---|
918 | printf("libxslt_xsltErrorInitialize() called\n");
|
---|
919 | #endif
|
---|
920 | xmlSetGenericErrorFunc(NULL, libxslt_xsltErrorFuncHandler);
|
---|
921 | xsltSetGenericErrorFunc(NULL, libxslt_xsltErrorFuncHandler);
|
---|
922 | }
|
---|
923 |
|
---|
924 | PyObject *
|
---|
925 | libxslt_xsltRegisterErrorHandler(PyObject * self ATTRIBUTE_UNUSED,
|
---|
926 | PyObject * args)
|
---|
927 | {
|
---|
928 | PyObject *py_retval;
|
---|
929 | PyObject *pyobj_f;
|
---|
930 | PyObject *pyobj_ctx;
|
---|
931 |
|
---|
932 | if (!PyArg_ParseTuple
|
---|
933 | (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f,
|
---|
934 | &pyobj_ctx))
|
---|
935 | return (NULL);
|
---|
936 |
|
---|
937 | #ifdef DEBUG_ERROR
|
---|
938 | printf("libxml_registerXPathFunction(%p, %p) called\n", pyobj_ctx,
|
---|
939 | pyobj_f);
|
---|
940 | #endif
|
---|
941 |
|
---|
942 | if (libxslt_xsltPythonErrorFuncHandler != NULL) {
|
---|
943 | Py_XDECREF(libxslt_xsltPythonErrorFuncHandler);
|
---|
944 | }
|
---|
945 | if (libxslt_xsltPythonErrorFuncCtxt != NULL) {
|
---|
946 | Py_XDECREF(libxslt_xsltPythonErrorFuncCtxt);
|
---|
947 | }
|
---|
948 |
|
---|
949 | Py_XINCREF(pyobj_ctx);
|
---|
950 | Py_XINCREF(pyobj_f);
|
---|
951 |
|
---|
952 | /* TODO: check f is a function ! */
|
---|
953 | libxslt_xsltPythonErrorFuncHandler = pyobj_f;
|
---|
954 | libxslt_xsltPythonErrorFuncCtxt = pyobj_ctx;
|
---|
955 |
|
---|
956 | py_retval = libxml_intWrap(1);
|
---|
957 | return (py_retval);
|
---|
958 | }
|
---|
959 |
|
---|
960 | /************************************************************************
|
---|
961 | * *
|
---|
962 | * Extension classes *
|
---|
963 | * *
|
---|
964 | ************************************************************************/
|
---|
965 |
|
---|
966 | static xmlHashTablePtr libxslt_extModuleClasses = NULL;
|
---|
967 |
|
---|
968 | static void *
|
---|
969 | libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style,
|
---|
970 | const xmlChar * URI) {
|
---|
971 | PyObject *result = NULL;
|
---|
972 | PyObject *class = NULL;
|
---|
973 |
|
---|
974 | #ifdef DEBUG_EXTENSIONS
|
---|
975 | printf("libxslt_xsltPythonExtModuleStyleInit(%p, %s) called\n",
|
---|
976 | style, URI);
|
---|
977 | #endif
|
---|
978 |
|
---|
979 | if ((style == NULL) || (URI == NULL))
|
---|
980 | return(NULL);
|
---|
981 |
|
---|
982 | /*
|
---|
983 | * Find the function, it should be there it was there at lookup
|
---|
984 | */
|
---|
985 | class = xmlHashLookup(libxslt_extModuleClasses, URI);
|
---|
986 | if (class == NULL) {
|
---|
987 | fprintf(stderr, "libxslt_xsltPythonExtModuleStyleInit: internal error %s not found !\n", URI);
|
---|
988 | return(NULL);
|
---|
989 | }
|
---|
990 |
|
---|
991 | if (PyObject_HasAttrString(class, (char *) "_styleInit")) {
|
---|
992 | result = PyObject_CallMethod(class, (char *) "_styleInit",
|
---|
993 | (char *) "Os", libxslt_xsltStylesheetPtrWrap(style), URI);
|
---|
994 | }
|
---|
995 | return((void *)result);
|
---|
996 | }
|
---|
997 | static void
|
---|
998 | libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style,
|
---|
999 | const xmlChar * URI, void *data) {
|
---|
1000 | PyObject *class = NULL;
|
---|
1001 | PyObject *result;
|
---|
1002 |
|
---|
1003 | #ifdef DEBUG_EXTENSIONS
|
---|
1004 | printf("libxslt_xsltPythonExtModuleStyleShutdown(%p, %s, %p) called\n",
|
---|
1005 | style, URI, data);
|
---|
1006 | #endif
|
---|
1007 |
|
---|
1008 | if ((style == NULL) || (URI == NULL))
|
---|
1009 | return;
|
---|
1010 |
|
---|
1011 | /*
|
---|
1012 | * Find the function, it should be there it was there at lookup
|
---|
1013 | */
|
---|
1014 | class = xmlHashLookup(libxslt_extModuleClasses, URI);
|
---|
1015 | if (class == NULL) {
|
---|
1016 | fprintf(stderr, "libxslt_xsltPythonExtModuleStyleShutdown: internal error %s not found !\n", URI);
|
---|
1017 | return;
|
---|
1018 | }
|
---|
1019 |
|
---|
1020 | if (PyObject_HasAttrString(class, (char *) "_styleShutdown")) {
|
---|
1021 | result = PyObject_CallMethod(class, (char *) "_styleShutdown",
|
---|
1022 | (char *) "OsO", libxslt_xsltStylesheetPtrWrap(style),
|
---|
1023 | URI, (PyObject *) data);
|
---|
1024 | Py_XDECREF(result);
|
---|
1025 | Py_XDECREF((PyObject *)data);
|
---|
1026 | }
|
---|
1027 | }
|
---|
1028 |
|
---|
1029 | static void *
|
---|
1030 | libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt,
|
---|
1031 | const xmlChar * URI) {
|
---|
1032 | PyObject *result = NULL;
|
---|
1033 | PyObject *class = NULL;
|
---|
1034 |
|
---|
1035 | #ifdef DEBUG_EXTENSIONS
|
---|
1036 | printf("libxslt_xsltPythonExtModuleCtxtInit(%p, %s) called\n",
|
---|
1037 | ctxt, URI);
|
---|
1038 | #endif
|
---|
1039 |
|
---|
1040 | if ((ctxt == NULL) || (URI == NULL))
|
---|
1041 | return(NULL);
|
---|
1042 |
|
---|
1043 | /*
|
---|
1044 | * Find the function, it should be there it was there at lookup
|
---|
1045 | */
|
---|
1046 | class = xmlHashLookup(libxslt_extModuleClasses, URI);
|
---|
1047 | if (class == NULL) {
|
---|
1048 | fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtInit: internal error %s not found !\n", URI);
|
---|
1049 | return(NULL);
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | if (PyObject_HasAttrString(class, (char *) "_ctxtInit")) {
|
---|
1053 | result = PyObject_CallMethod(class, (char *) "_ctxtInit",
|
---|
1054 | (char *) "Os", libxslt_xsltTransformContextPtrWrap(ctxt),
|
---|
1055 | URI);
|
---|
1056 | }
|
---|
1057 | return((void *)result);
|
---|
1058 | }
|
---|
1059 | static void
|
---|
1060 | libxslt_xsltPythonExtModuleCtxtShutdown(xsltTransformContextPtr ctxt,
|
---|
1061 | const xmlChar * URI, void *data) {
|
---|
1062 | PyObject *class = NULL;
|
---|
1063 | PyObject *result;
|
---|
1064 |
|
---|
1065 | #ifdef DEBUG_EXTENSIONS
|
---|
1066 | printf("libxslt_xsltPythonExtModuleCtxtShutdown(%p, %s, %p) called\n",
|
---|
1067 | ctxt, URI, data);
|
---|
1068 | #endif
|
---|
1069 |
|
---|
1070 | if ((ctxt == NULL) || (URI == NULL))
|
---|
1071 | return;
|
---|
1072 |
|
---|
1073 | /*
|
---|
1074 | * Find the function, it should be there it was there at lookup
|
---|
1075 | */
|
---|
1076 | class = xmlHashLookup(libxslt_extModuleClasses, URI);
|
---|
1077 | if (class == NULL) {
|
---|
1078 | fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtShutdown: internal error %s not found !\n", URI);
|
---|
1079 | return;
|
---|
1080 | }
|
---|
1081 |
|
---|
1082 | if (PyObject_HasAttrString(class, (char *) "_ctxtShutdown")) {
|
---|
1083 | result = PyObject_CallMethod(class, (char *) "_ctxtShutdown",
|
---|
1084 | (char *) "OsO", libxslt_xsltTransformContextPtrWrap(ctxt),
|
---|
1085 | URI, (PyObject *) data);
|
---|
1086 | Py_XDECREF(result);
|
---|
1087 | Py_XDECREF((PyObject *)data);
|
---|
1088 | }
|
---|
1089 | }
|
---|
1090 |
|
---|
1091 | PyObject *
|
---|
1092 | libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED,
|
---|
1093 | PyObject *args) {
|
---|
1094 | PyObject *py_retval;
|
---|
1095 | int ret = 0;
|
---|
1096 | xmlChar *ns_uri;
|
---|
1097 | PyObject *pyobj_c;
|
---|
1098 |
|
---|
1099 | if (!PyArg_ParseTuple(args, (char *)"zO:registerExtensionClass",
|
---|
1100 | &ns_uri, &pyobj_c))
|
---|
1101 | return(NULL);
|
---|
1102 |
|
---|
1103 | if ((ns_uri == NULL) || (pyobj_c == NULL)) {
|
---|
1104 | py_retval = libxml_intWrap(-1);
|
---|
1105 | return(py_retval);
|
---|
1106 | }
|
---|
1107 |
|
---|
1108 | #ifdef DEBUG_EXTENSIONS
|
---|
1109 | printf("libxslt_xsltRegisterExtensionClass(%s) called\n", ns_uri);
|
---|
1110 | #endif
|
---|
1111 |
|
---|
1112 | if (libxslt_extModuleClasses == NULL)
|
---|
1113 | libxslt_extModuleClasses = xmlHashCreate(10);
|
---|
1114 | if (libxslt_extModuleClasses == NULL) {
|
---|
1115 | py_retval = libxml_intWrap(-1);
|
---|
1116 | return(py_retval);
|
---|
1117 | }
|
---|
1118 | ret = xmlHashAddEntry(libxslt_extModuleClasses, ns_uri, pyobj_c);
|
---|
1119 | if (ret != 0) {
|
---|
1120 | py_retval = libxml_intWrap(-1);
|
---|
1121 | return(py_retval);
|
---|
1122 | }
|
---|
1123 | Py_XINCREF(pyobj_c);
|
---|
1124 |
|
---|
1125 | ret = xsltRegisterExtModuleFull(ns_uri,
|
---|
1126 | (xsltExtInitFunction) libxslt_xsltPythonExtModuleCtxtInit,
|
---|
1127 | (xsltExtShutdownFunction) libxslt_xsltPythonExtModuleCtxtShutdown,
|
---|
1128 | (xsltStyleExtInitFunction) libxslt_xsltPythonExtModuleStyleInit,
|
---|
1129 | (xsltStyleExtShutdownFunction) libxslt_xsltPythonExtModuleStyleShutdown);
|
---|
1130 | py_retval = libxml_intWrap((int) ret);
|
---|
1131 | if (ret < 0) {
|
---|
1132 | Py_XDECREF(pyobj_c);
|
---|
1133 | }
|
---|
1134 | return(py_retval);
|
---|
1135 | }
|
---|
1136 |
|
---|
1137 | /************************************************************************
|
---|
1138 | * *
|
---|
1139 | * Integrated cleanup *
|
---|
1140 | * *
|
---|
1141 | ************************************************************************/
|
---|
1142 |
|
---|
1143 | PyObject *
|
---|
1144 | libxslt_xsltPythonCleanup(PyObject *self ATTRIBUTE_UNUSED,
|
---|
1145 | PyObject *args ATTRIBUTE_UNUSED) {
|
---|
1146 |
|
---|
1147 | if (libxslt_extModuleFunctions != NULL) {
|
---|
1148 | xmlHashFree(libxslt_extModuleFunctions, deallocateCallback);
|
---|
1149 | }
|
---|
1150 | if (libxslt_extModuleElements != NULL) {
|
---|
1151 | xmlHashFree(libxslt_extModuleElements, deallocateCallback);
|
---|
1152 | }
|
---|
1153 | if (libxslt_extModuleElementPreComp != NULL) {
|
---|
1154 | xmlHashFree(libxslt_extModuleElementPreComp, deallocateCallback);
|
---|
1155 | }
|
---|
1156 | if (libxslt_extModuleClasses != NULL) {
|
---|
1157 | xmlHashFree(libxslt_extModuleClasses, deallocateClasse);
|
---|
1158 | }
|
---|
1159 | xsltCleanupGlobals();
|
---|
1160 | Py_INCREF(Py_None);
|
---|
1161 | return(Py_None);
|
---|
1162 | }
|
---|
1163 |
|
---|
1164 | /************************************************************************
|
---|
1165 | * *
|
---|
1166 | * The registration stuff *
|
---|
1167 | * *
|
---|
1168 | ************************************************************************/
|
---|
1169 | static PyMethodDef libxsltMethods[] = {
|
---|
1170 | #include "libxslt-export.c"
|
---|
1171 | { NULL, NULL, 0, NULL }
|
---|
1172 | };
|
---|
1173 |
|
---|
1174 | #ifdef MERGED_MODULES
|
---|
1175 | extern void initlibxml2mod(void);
|
---|
1176 | #endif
|
---|
1177 |
|
---|
1178 | void initlibxsltmod(void) {
|
---|
1179 | static int initialized = 0;
|
---|
1180 | PyObject *m;
|
---|
1181 |
|
---|
1182 | #ifdef MERGED_MODULES
|
---|
1183 | initlibxml2mod();
|
---|
1184 | #endif
|
---|
1185 |
|
---|
1186 | if (initialized != 0)
|
---|
1187 | return;
|
---|
1188 | m = Py_InitModule((char *)"libxsltmod", libxsltMethods);
|
---|
1189 | initialized = 1;
|
---|
1190 | /*
|
---|
1191 | * Specific XSLT initializations
|
---|
1192 | */
|
---|
1193 | libxslt_xsltErrorInitialize();
|
---|
1194 | xmlInitMemory();
|
---|
1195 | xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
|
---|
1196 | xmlDefaultSAXHandler.cdataBlock = NULL;
|
---|
1197 | /*
|
---|
1198 | * Register the EXSLT extensions and the test module
|
---|
1199 | */
|
---|
1200 | exsltRegisterAll();
|
---|
1201 | }
|
---|
1202 |
|
---|
1203 |
|
---|