mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-07-31 02:43:06 +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:
@ -1,3 +1,12 @@
|
|||||||
|
Wed Jul 9 12:19:34 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
Tue Jul 8 12:20:11 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
Tue Jul 8 12:20:11 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
* python/libxml_wrap.h: applied patch from #116943 which should
|
* python/libxml_wrap.h: applied patch from #116943 which should
|
||||||
|
@ -185,6 +185,7 @@ skipped_modules = {
|
|||||||
'list': None,
|
'list': None,
|
||||||
'threads': None,
|
'threads': None,
|
||||||
'xpointer': None,
|
'xpointer': None,
|
||||||
|
'transform': None,
|
||||||
}
|
}
|
||||||
skipped_types = {
|
skipped_types = {
|
||||||
'int *': "usually a return type",
|
'int *': "usually a return type",
|
||||||
@ -267,6 +268,8 @@ py_types = {
|
|||||||
'FILE *': ('O', "File", "FILEPtr", "FILE *", "libxml_"),
|
'FILE *': ('O', "File", "FILEPtr", "FILE *", "libxml_"),
|
||||||
'xsltTransformContextPtr': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
|
'xsltTransformContextPtr': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
|
||||||
'xsltTransformContext *': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
|
'xsltTransformContext *': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
|
||||||
|
'xsltStylePreCompPtr': ('O', "compiledStyle", "xsltStylePreCompPtr", "xsltStylePreCompPtr", "libxslt_"),
|
||||||
|
'xsltStylePreComp *': ('O', "compiledStyle", "xsltStylePreCompPtr", "xsltStylePreCompPtr", "libxslt_"),
|
||||||
'xsltStylesheetPtr': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
|
'xsltStylesheetPtr': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
|
||||||
'xsltStylesheet *': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
|
'xsltStylesheet *': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
|
||||||
'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxslt_"),
|
'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxslt_"),
|
||||||
|
@ -24,6 +24,14 @@
|
|||||||
<arg name='f' type='pythonObject' info='the python function'/>
|
<arg name='f' type='pythonObject' info='the python function'/>
|
||||||
<arg name='ctx' type='pythonObject' info='a context for the callback'/>
|
<arg name='ctx' type='pythonObject' info='a context for the callback'/>
|
||||||
</function>
|
</function>
|
||||||
|
<function name='xsltRegisterExtModuleElement' file='python'>
|
||||||
|
<info>Register a Python written element to the XSLT engine</info>
|
||||||
|
<return type='int' info="0 in case of success, -1 in case of error"/>
|
||||||
|
<arg name='name' type='xmlChar *' info='the element name'/>
|
||||||
|
<arg name='URI' type='xmlChar *' info='the namespace or NULL'/>
|
||||||
|
<arg name='precompile' type='pythonObject' info='method called when stylesheet is compiled'/>
|
||||||
|
<arg name='transform' type='pythonObject' info='method called during transform, must not modify stylesheet'/>
|
||||||
|
</function>
|
||||||
<function name='xsltRegisterExtModuleFunction' file='python'>
|
<function name='xsltRegisterExtModuleFunction' file='python'>
|
||||||
<info>Register a Python written function to the XSLT engine</info>
|
<info>Register a Python written function to the XSLT engine</info>
|
||||||
<return type='int' info="0 in case of success, -1 in case of error"/>
|
<return type='int' info="0 in case of success, -1 in case of error"/>
|
||||||
|
288
python/libxslt.c
288
python/libxslt.c
@ -31,6 +31,7 @@
|
|||||||
/* #define DEBUG_ERROR */
|
/* #define DEBUG_ERROR */
|
||||||
/* #define DEBUG_MEMORY */
|
/* #define DEBUG_MEMORY */
|
||||||
/* #define DEBUG_EXTENSIONS */
|
/* #define DEBUG_EXTENSIONS */
|
||||||
|
/* #define DEBUG_EXTENSIONS */
|
||||||
|
|
||||||
void initlibxsltmod(void);
|
void initlibxsltmod(void);
|
||||||
|
|
||||||
@ -72,6 +73,22 @@ libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) {
|
|||||||
return(ret);
|
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 *
|
* Extending the API *
|
||||||
@ -79,7 +96,238 @@ libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) {
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
static xmlHashTablePtr libxslt_extModuleFunctions = NULL;
|
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
|
static void
|
||||||
libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) {
|
libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
PyObject *list, *cur, *result;
|
PyObject *list, *cur, *result;
|
||||||
@ -119,11 +367,17 @@ libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
cur = libxml_xmlXPathObjectPtrWrap(obj);
|
cur = libxml_xmlXPathObjectPtrWrap(obj);
|
||||||
PyTuple_SetItem(list, i + 1, cur);
|
PyTuple_SetItem(list, i + 1, cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Py_INCREF(current_function);
|
||||||
result = PyEval_CallObject(current_function, list);
|
result = PyEval_CallObject(current_function, list);
|
||||||
|
Py_DECREF(current_function);
|
||||||
Py_DECREF(list);
|
Py_DECREF(list);
|
||||||
|
|
||||||
|
/* Check for null in case of exception */
|
||||||
|
if (result != NULL) {
|
||||||
obj = libxml_xmlXPathObjectPtrConvert(result);
|
obj = libxml_xmlXPathObjectPtrConvert(result);
|
||||||
valuePush(ctxt, obj);
|
valuePush(ctxt, obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
@ -168,17 +422,6 @@ libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED,
|
|||||||
return(py_retval);
|
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 *
|
* Some customized front-ends *
|
||||||
@ -262,7 +505,6 @@ PyObject *
|
|||||||
libxslt_xsltSaveResultToString(PyObject *self, PyObject *args) {
|
libxslt_xsltSaveResultToString(PyObject *self, PyObject *args) {
|
||||||
PyObject *py_retval; /* our final return value, a python string */
|
PyObject *py_retval; /* our final return value, a python string */
|
||||||
xmlChar *buffer;
|
xmlChar *buffer;
|
||||||
xmlChar *tmp;
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int emitted = 0;
|
int emitted = 0;
|
||||||
xmlDocPtr result;
|
xmlDocPtr result;
|
||||||
@ -424,7 +666,7 @@ static xmlHashTablePtr libxslt_extModuleClasses = NULL;
|
|||||||
static void *
|
static void *
|
||||||
libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style,
|
libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style,
|
||||||
const xmlChar * URI) {
|
const xmlChar * URI) {
|
||||||
PyObject *result;
|
PyObject *result = NULL;
|
||||||
PyObject *class = NULL;
|
PyObject *class = NULL;
|
||||||
|
|
||||||
#ifdef DEBUG_EXTENSIONS
|
#ifdef DEBUG_EXTENSIONS
|
||||||
@ -485,7 +727,7 @@ libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style,
|
|||||||
static void *
|
static void *
|
||||||
libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt,
|
libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt,
|
||||||
const xmlChar * URI) {
|
const xmlChar * URI) {
|
||||||
PyObject *result;
|
PyObject *result = NULL;
|
||||||
PyObject *class = NULL;
|
PyObject *class = NULL;
|
||||||
|
|
||||||
#ifdef DEBUG_EXTENSIONS
|
#ifdef DEBUG_EXTENSIONS
|
||||||
@ -549,7 +791,6 @@ libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED,
|
|||||||
PyObject *args) {
|
PyObject *args) {
|
||||||
PyObject *py_retval;
|
PyObject *py_retval;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
xmlChar *name;
|
|
||||||
xmlChar *ns_uri;
|
xmlChar *ns_uri;
|
||||||
PyObject *pyobj_c;
|
PyObject *pyobj_c;
|
||||||
|
|
||||||
@ -591,17 +832,6 @@ libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED,
|
|||||||
return(py_retval);
|
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 *
|
* Integrated cleanup *
|
||||||
@ -615,6 +845,12 @@ libxslt_xsltCleanup(PyObject *self ATTRIBUTE_UNUSED,
|
|||||||
if (libxslt_extModuleFunctions != NULL) {
|
if (libxslt_extModuleFunctions != NULL) {
|
||||||
xmlHashFree(libxslt_extModuleFunctions, deallocateCallback);
|
xmlHashFree(libxslt_extModuleFunctions, deallocateCallback);
|
||||||
}
|
}
|
||||||
|
if (libxslt_extModuleElements != NULL) {
|
||||||
|
xmlHashFree(libxslt_extModuleElements, deallocateCallback);
|
||||||
|
}
|
||||||
|
if (libxslt_extModuleElementPreComp != NULL) {
|
||||||
|
xmlHashFree(libxslt_extModuleElementPreComp, deallocateCallback);
|
||||||
|
}
|
||||||
if (libxslt_extModuleClasses != NULL) {
|
if (libxslt_extModuleClasses != NULL) {
|
||||||
xmlHashFree(libxslt_extModuleClasses, deallocateClasse);
|
xmlHashFree(libxslt_extModuleClasses, deallocateClasse);
|
||||||
}
|
}
|
||||||
|
@ -34,5 +34,16 @@ typedef struct {
|
|||||||
xsltTransformContextPtr obj;
|
xsltTransformContextPtr obj;
|
||||||
} PytransformCtxt_Object;
|
} PytransformCtxt_Object;
|
||||||
|
|
||||||
|
#define PycompiledStyle_Get(v) (((v) == Py_None) ? NULL : \
|
||||||
|
(((PycompiledStyle_Object *)(v))->obj))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
xsltTransformContextPtr obj;
|
||||||
|
} PycompiledStyle_Object;
|
||||||
|
|
||||||
|
|
||||||
PyObject * libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr ctxt);
|
PyObject * libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr ctxt);
|
||||||
PyObject * libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt);
|
PyObject * libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt);
|
||||||
|
PyObject * libxslt_xsltStylePreCompPtrWrap(xsltStylePreCompPtr comp);
|
||||||
|
PyObject * libxslt_xsltElemPreCompPtrWrap(xsltElemPreCompPtr comp);
|
||||||
|
@ -19,13 +19,10 @@ registerAllExtras()
|
|||||||
# functions from module python
|
# functions from module python
|
||||||
cleanup()
|
cleanup()
|
||||||
registerErrorHandler()
|
registerErrorHandler()
|
||||||
|
registerExtModuleElement()
|
||||||
registerExtModuleFunction()
|
registerExtModuleFunction()
|
||||||
registerExtensionClass()
|
registerExtensionClass()
|
||||||
|
|
||||||
# functions from module transform
|
|
||||||
setXIncludeDefault()
|
|
||||||
xincludeDefault()
|
|
||||||
|
|
||||||
# functions from module xslt
|
# functions from module xslt
|
||||||
cleanupGlobals()
|
cleanupGlobals()
|
||||||
|
|
||||||
@ -98,6 +95,7 @@ Class transformCtxt()
|
|||||||
shutdownCtxtExts()
|
shutdownCtxtExts()
|
||||||
|
|
||||||
# functions from module extra
|
# functions from module extra
|
||||||
|
debug()
|
||||||
registerExtras()
|
registerExtras()
|
||||||
|
|
||||||
# functions from module imports
|
# functions from module imports
|
||||||
@ -118,11 +116,6 @@ Class transformCtxt()
|
|||||||
evalAttrValueTemplate()
|
evalAttrValueTemplate()
|
||||||
evalTemplateString()
|
evalTemplateString()
|
||||||
|
|
||||||
# functions from module transform
|
|
||||||
applyStripSpaces()
|
|
||||||
freeTransformContext()
|
|
||||||
registerAllElement()
|
|
||||||
|
|
||||||
# functions from module variables
|
# functions from module variables
|
||||||
evalGlobalVariables()
|
evalGlobalVariables()
|
||||||
evalOneUserParam()
|
evalOneUserParam()
|
||||||
@ -196,9 +189,6 @@ Class stylesheet()
|
|||||||
applyStylesheet()
|
applyStylesheet()
|
||||||
saveResultToString()
|
saveResultToString()
|
||||||
|
|
||||||
# functions from module transform
|
|
||||||
newTransformContext()
|
|
||||||
|
|
||||||
# functions from module variables
|
# functions from module variables
|
||||||
parseGlobalParam()
|
parseGlobalParam()
|
||||||
parseGlobalVariable()
|
parseGlobalVariable()
|
||||||
|
@ -3,6 +3,7 @@ EXAMPLE_DIR = $(datadir)/doc/libxslt-python-$(LIBXSLT_VERSION)/examples
|
|||||||
TESTSPY= \
|
TESTSPY= \
|
||||||
basic.py \
|
basic.py \
|
||||||
exslt.py \
|
exslt.py \
|
||||||
|
extelem.py \
|
||||||
extfunc.py
|
extfunc.py
|
||||||
|
|
||||||
XMLS= \
|
XMLS= \
|
||||||
|
89
python/tests/extelem.py
Normal file
89
python/tests/extelem.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/python -u
|
||||||
|
import sys
|
||||||
|
import string
|
||||||
|
import StringIO
|
||||||
|
import libxml2
|
||||||
|
# Memory debug specific
|
||||||
|
libxml2.debugMemory(1)
|
||||||
|
import libxslt
|
||||||
|
|
||||||
|
EXT_URL="http://example.com/foo"
|
||||||
|
|
||||||
|
insertNodeName = None
|
||||||
|
transformNodeName = None
|
||||||
|
|
||||||
|
def compile_test(style, inst, func):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def transform_test(ctx, node, inst, comp):
|
||||||
|
global insertNodeName
|
||||||
|
|
||||||
|
#
|
||||||
|
# Small check to verify the context is correcly accessed
|
||||||
|
#
|
||||||
|
try:
|
||||||
|
#
|
||||||
|
# FIXME add some more sanity checks
|
||||||
|
#
|
||||||
|
tctxt = libxslt.transformCtxt(_obj=ctx)
|
||||||
|
insertNodeName = tctxt.insertNode().name
|
||||||
|
|
||||||
|
# FIXME find and confirm the note being replaced is called 'test'
|
||||||
|
# transformNodeName = libxml2.xmlNode(inst).name
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
tctxt.insertNode().addContent('SUCCESS')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
styledoc = libxml2.parseDoc("""
|
||||||
|
<xsl:stylesheet version='1.0'
|
||||||
|
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
|
||||||
|
xmlns:foo='%s'
|
||||||
|
xsl:extension-element-prefixes='foo'>
|
||||||
|
|
||||||
|
<xsl:template match='/'>
|
||||||
|
<article><foo:test>FAILURE</foo:test></article>
|
||||||
|
<deeper><article><foo:test>something<foo:test>nested</foo:test>even</foo:test></article></deeper>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
||||||
|
""" % EXT_URL)
|
||||||
|
|
||||||
|
style = libxslt.parseStylesheetDoc(styledoc)
|
||||||
|
libxslt.registerExtModuleElement("test", EXT_URL, compile_test, transform_test)
|
||||||
|
doc = libxml2.parseDoc("<doc/>")
|
||||||
|
result = style.applyStylesheet(doc, None)
|
||||||
|
style.freeStylesheet()
|
||||||
|
doc.freeDoc()
|
||||||
|
|
||||||
|
|
||||||
|
extensions = StringIO.StringIO()
|
||||||
|
libxslt.debugDumpExtensions(extensions)
|
||||||
|
|
||||||
|
if 0 and extensions.buf.find(EXT_URL) < 0:
|
||||||
|
print "Element extension not registered (or dumping broken)"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
root = result.children
|
||||||
|
|
||||||
|
if root.name != "article":
|
||||||
|
print "Unexpected root node name"
|
||||||
|
sys.exit(1)
|
||||||
|
if root.content != "SUCCESS":
|
||||||
|
print "Unexpected root node content, extension function failed"
|
||||||
|
sys.exit(1)
|
||||||
|
if insertNodeName != 'article':
|
||||||
|
print "The function callback failed to access its context"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
result.dump(sys.stdout)
|
||||||
|
result.freeDoc()
|
||||||
|
|
||||||
|
# Memory debug specific
|
||||||
|
libxslt.cleanup()
|
||||||
|
if libxml2.debugMemory(1) == 0:
|
||||||
|
print "OK"
|
||||||
|
else:
|
||||||
|
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
|
||||||
|
libxml2.dumpMemory()
|
Reference in New Issue
Block a user