mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-07-01 13:41:39 +03:00
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
This commit is contained in:
292
python/libxslt.c
292
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user