diff options
author | Daniel Veillard <veillard@src.gnome.org> | 2003-07-09 10:22:14 +0000 |
---|---|---|
committer | Daniel Veillard <veillard@src.gnome.org> | 2003-07-09 10:22:14 +0000 |
commit | 9332a25a91e7a0584885d4e1715442de48a085ff (patch) | |
tree | df245d21afa656b138ce26cf7cc6022e9046a263 /python/libxslt.c | |
parent | 0232312dde5d26ffa3f5ac8c89dc1b2ebef16e6b (diff) | |
download | libxslt-9332a25a91e7a0584885d4e1715442de48a085ff.tar.gz libxslt-9332a25a91e7a0584885d4e1715442de48a085ff.tar.bz2 libxslt-9332a25a91e7a0584885d4e1715442de48a085ff.zip |
patch from Sean Treadway, adding Python bindings for extension element and
* python/generator.py python/libxslt-python-api.xml python/libxslt.c
python/libxslt_wrap.h python/libxsltclass.txt: patch from
Sean Treadway, adding Python bindings for extension element and
some bindings cleanups.
* python/tests/Makefile.am python/tests/extelem.py: also add an
example/test.
Daniel
Diffstat (limited to 'python/libxslt.c')
-rw-r--r-- | python/libxslt.c | 292 |
1 files changed, 264 insertions, 28 deletions
diff --git a/python/libxslt.c b/python/libxslt.c index a6310a51..84978414 100644 --- a/python/libxslt.c +++ b/python/libxslt.c @@ -31,6 +31,7 @@ /* #define DEBUG_ERROR */ /* #define DEBUG_MEMORY */ /* #define DEBUG_EXTENSIONS */ +/* #define DEBUG_EXTENSIONS */ void initlibxsltmod(void); @@ -72,6 +73,22 @@ libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) { return(ret); } +PyObject * +libxslt_xsltElemPreCompPtrWrap(xsltElemPreCompPtr ctxt) { + PyObject *ret; + +#ifdef DEBUG + printf("libxslt_xsltElemPreCompPtrWrap: ctxt = %p\n", ctxt); +#endif + if (ctxt == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, + (char *)"xsltElemPreCompPtr", NULL); + return(ret); +} + /************************************************************************ * * * Extending the API * @@ -79,7 +96,238 @@ libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) { ************************************************************************/ static xmlHashTablePtr libxslt_extModuleFunctions = NULL; +static xmlHashTablePtr libxslt_extModuleElements = NULL; +static xmlHashTablePtr libxslt_extModuleElementPreComp = NULL; + +static void +deallocateCallback(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { + PyObject *function = (PyObject *) payload; + +#ifdef DEBUG_EXTENSIONS + printf("deallocateCallback(%s) called\n", name); +#endif + + Py_XDECREF(function); +} + +static void +deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { + PyObject *class = (PyObject *) payload; + +#ifdef DEBUG_EXTENSIONS + printf("deallocateClasse(%s) called\n", name); +#endif + + Py_XDECREF(class); +} + + +/** + * libxslt_xsltElementPreCompCallback + * @style: the stylesheet + * @inst: the instruction in the stylesheet + * + * Callback for preprocessing of a custom element + */ +static xsltElemPreCompPtr +libxslt_xsltElementPreCompCallback(xsltStylesheetPtr style, xmlNodePtr inst, + xsltTransformFunction function) { + xsltElemPreCompPtr ret; + const xmlChar *name; + PyObject *args; + PyObject *result; + PyObject *pyobj_element_f; + PyObject *pyobj_precomp_f; + + const xmlChar *ns_uri; + + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltElementPreCompCallback called\n"); +#endif + + if (style == NULL) { + xsltTransformError(NULL, NULL, inst, + "libxslt_xsltElementPreCompCallback: no transformation context\n"); + return (NULL); + } + + if (inst == NULL) { + xsltTransformError(NULL, style, inst, + "libxslt_xsltElementPreCompCallback: no instruction\n"); + if (style != NULL) style->errors++; + return (NULL); + } + + if (style == NULL) + return (NULL); + + if (inst != NULL && inst->ns != NULL) { + name = inst->name; + ns_uri = inst->ns->href; + } else { + xsltTransformError(NULL, style, inst, + "libxslt_xsltElementPreCompCallback: internal error bad parameter\n"); + printf("libxslt_xsltElementPreCompCallback: internal error bad parameter\n"); + if (style != NULL) style->errors++; + return (NULL); + } + + /* + * Find the functions, they should be there it was there at lookup + */ + pyobj_precomp_f = xmlHashLookup2(libxslt_extModuleElementPreComp, + name, ns_uri); + if (pyobj_precomp_f == NULL) { + xsltTransformError(NULL, style, inst, + "libxslt_xsltElementPreCompCallback: internal error, could not find precompile python function!\n"); + if (style != NULL) style->errors++; + return (NULL); + } + + pyobj_element_f = xmlHashLookup2(libxslt_extModuleElements, + name, ns_uri); + if (pyobj_element_f == NULL) { + xsltTransformError(NULL, style, inst, + "libxslt_xsltElementPreCompCallback: internal error, could not find element python function!\n"); + if (style != NULL) style->errors++; + return (NULL); + } + + args = Py_BuildValue("(OOO)", + libxslt_xsltStylesheetPtrWrap(style), + libxml_xmlNodePtrWrap(inst), + pyobj_element_f); + + Py_INCREF(pyobj_precomp_f); /* Protect refcount against reentrant manipulation of callback hash */ + result = PyEval_CallObject(pyobj_precomp_f, args); + Py_DECREF(pyobj_precomp_f); + Py_DECREF(args); + + /* FIXME allow callbacks to return meaningful information to modify compile process */ + /* If error, do we need to check the result and throw exception? */ + + Py_XDECREF(result); + + ret = xsltNewElemPreComp (style, inst, function); + return (ret); +} + + +static void +libxslt_xsltElementTransformCallback(xsltTransformContextPtr ctxt, + xmlNodePtr node, + xmlNodePtr inst, + xsltElemPreCompPtr comp) +{ + PyObject *args, *result; + PyObject *func = NULL; + const xmlChar *name; + const xmlChar *ns_uri; + + if (ctxt == NULL) + return; + + if (inst != NULL && inst->name != NULL && inst->ns != NULL && inst->ns->href != NULL) { + name = inst->name; + ns_uri = inst->ns->href; + } else { + printf("libxslt_xsltElementTransformCallback: internal error bad parameter\n"); + return; + } + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltElementTransformCallback called name %s URI %s\n", name, ns_uri); +#endif + + /* + * Find the function, it should be there it was there at lookup + */ + func = xmlHashLookup2(libxslt_extModuleElements, + name, ns_uri); + if (func == NULL) { + printf("libxslt_xsltElementTransformCallback: internal error %s not found !\n", + name); + return; + } + + args = Py_BuildValue("OOOO", + libxslt_xsltTransformContextPtrWrap(ctxt), + libxml_xmlNodePtrWrap(node), + libxml_xmlNodePtrWrap(inst), + libxslt_xsltElemPreCompPtrWrap(comp)); + + Py_INCREF(func); /* Protect refcount against reentrant manipulation of callback hash */ + result = PyEval_CallObject(func, args); + Py_DECREF(func); + Py_DECREF(args); + + /* FIXME Check result of callobject and set exception if fail */ + + Py_XDECREF(result); +} + +PyObject * +libxslt_xsltRegisterExtModuleElement(PyObject *self ATTRIBUTE_UNUSED, + PyObject *args) { + PyObject *py_retval; + int ret = 0; + xmlChar *name; + xmlChar *ns_uri; + PyObject *pyobj_element_f; + PyObject *pyobj_precomp_f; +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltRegisterExtModuleElement called\n", + name, ns_uri); +#endif + + if (!PyArg_ParseTuple(args, (char *)"szOO:registerExtModuleElement", + &name, &ns_uri, &pyobj_precomp_f, &pyobj_element_f)) + return(NULL); + + if ((name == NULL) || (pyobj_element_f == NULL) || (pyobj_precomp_f == NULL)) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + +#ifdef DEBUG_EXTENSIONS + printf("libxslt_xsltRegisterExtModuleElement(%s, %s) called\n", + name, ns_uri); +#endif + + if (libxslt_extModuleElements == NULL) + libxslt_extModuleElements = xmlHashCreate(10); + + if (libxslt_extModuleElementPreComp == NULL) + libxslt_extModuleElementPreComp = xmlHashCreate(10); + + if (libxslt_extModuleElements == NULL || libxslt_extModuleElementPreComp == NULL) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + + ret = xmlHashAddEntry2(libxslt_extModuleElements, name, ns_uri, pyobj_element_f); + if (ret != 0) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + Py_XINCREF(pyobj_element_f); + + ret = xmlHashAddEntry2(libxslt_extModuleElementPreComp, name, ns_uri, pyobj_precomp_f); + if (ret != 0) { + xmlHashRemoveEntry2(libxslt_extModuleElements, name, ns_uri, deallocateCallback); + py_retval = libxml_intWrap(-1); + return(py_retval); + } + Py_XINCREF(pyobj_precomp_f); + + ret = xsltRegisterExtModuleElement(name, ns_uri, + libxslt_xsltElementPreCompCallback, + libxslt_xsltElementTransformCallback); + py_retval = libxml_intWrap((int) ret); + return(py_retval); +} static void libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) { PyObject *list, *cur, *result; @@ -119,11 +367,17 @@ libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) { cur = libxml_xmlXPathObjectPtrWrap(obj); PyTuple_SetItem(list, i + 1, cur); } + + Py_INCREF(current_function); result = PyEval_CallObject(current_function, list); + Py_DECREF(current_function); Py_DECREF(list); - obj = libxml_xmlXPathObjectPtrConvert(result); - valuePush(ctxt, obj); + /* Check for null in case of exception */ + if (result != NULL) { + obj = libxml_xmlXPathObjectPtrConvert(result); + valuePush(ctxt, obj); + } } PyObject * @@ -168,17 +422,6 @@ libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED, return(py_retval); } -static void -deallocateCallback(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { - PyObject *function = (PyObject *) payload; - -#ifdef DEBUG_XPATH - printf("deallocateCallback(%s) called\n", name); -#endif - - Py_XDECREF(function); -} - /************************************************************************ * * * Some customized front-ends * @@ -262,7 +505,6 @@ PyObject * libxslt_xsltSaveResultToString(PyObject *self, PyObject *args) { PyObject *py_retval; /* our final return value, a python string */ xmlChar *buffer; - xmlChar *tmp; int size = 0; int emitted = 0; xmlDocPtr result; @@ -424,7 +666,7 @@ static xmlHashTablePtr libxslt_extModuleClasses = NULL; static void * libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style, const xmlChar * URI) { - PyObject *result; + PyObject *result = NULL; PyObject *class = NULL; #ifdef DEBUG_EXTENSIONS @@ -485,7 +727,7 @@ libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style, static void * libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt, const xmlChar * URI) { - PyObject *result; + PyObject *result = NULL; PyObject *class = NULL; #ifdef DEBUG_EXTENSIONS @@ -549,7 +791,6 @@ libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int ret = 0; - xmlChar *name; xmlChar *ns_uri; PyObject *pyobj_c; @@ -591,17 +832,6 @@ libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED, return(py_retval); } -static void -deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) { - PyObject *class = (PyObject *) payload; - -#ifdef DEBUG_EXTENSIONS - printf("deallocateClasse(%s) called\n", name); -#endif - - Py_XDECREF(class); -} - /************************************************************************ * * * Integrated cleanup * @@ -615,6 +845,12 @@ libxslt_xsltCleanup(PyObject *self ATTRIBUTE_UNUSED, if (libxslt_extModuleFunctions != NULL) { xmlHashFree(libxslt_extModuleFunctions, deallocateCallback); } + if (libxslt_extModuleElements != NULL) { + xmlHashFree(libxslt_extModuleElements, deallocateCallback); + } + if (libxslt_extModuleElementPreComp != NULL) { + xmlHashFree(libxslt_extModuleElementPreComp, deallocateCallback); + } if (libxslt_extModuleClasses != NULL) { xmlHashFree(libxslt_extModuleClasses, deallocateClasse); } |