summaryrefslogtreecommitdiff
path: root/python/libxslt.c
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2003-07-09 10:22:14 +0000
committerDaniel Veillard <veillard@src.gnome.org>2003-07-09 10:22:14 +0000
commit9332a25a91e7a0584885d4e1715442de48a085ff (patch)
treedf245d21afa656b138ce26cf7cc6022e9046a263 /python/libxslt.c
parent0232312dde5d26ffa3f5ac8c89dc1b2ebef16e6b (diff)
downloadlibxslt-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.c292
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);
}