mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-07-31 02:43:06 +03:00
applied patch from Nic James Ferrier to make stylesheets comparable and to
* configure python/generator.py python/libxsl.py python/libxslt-python-api.xml python/libxslt.c python/tests/2stage.py python/tests/loader.py: applied patch from Nic James Ferrier to make stylesheets comparable and to add transformContext handling Daniel
This commit is contained in:
@ -564,6 +564,8 @@ primary_classes = ["xpathParserContext", "xpathContext", "transformCtxt", "style
|
||||
classes_ancestor = {
|
||||
"xpathContext" : "libxml2.xpathContext",
|
||||
"xpathParserContext" : "libxml2.xpathParserContext",
|
||||
"transformCtxt": "transformCtxtBase",
|
||||
"stylesheet": "stylesheetBase",
|
||||
}
|
||||
classes_destructors = {
|
||||
"xpathContext" : "pass"
|
||||
|
@ -56,6 +56,37 @@ else:
|
||||
import libxsltmod
|
||||
import libxml2
|
||||
|
||||
|
||||
class transformCtxtBase:
|
||||
def __init__(self, _obj=None):
|
||||
if _obj != None:
|
||||
self._o = _obj;
|
||||
return
|
||||
self._o = None
|
||||
def __hash__(self):
|
||||
v = libxsltmod.xsltGetTransformContextHashCode(self._o)
|
||||
return v
|
||||
def __eq__(self, other):
|
||||
if other == None:
|
||||
return 0
|
||||
v = libxsltmod.xsltCompareTransformContextsEqual(self._o, other._o)
|
||||
return v
|
||||
|
||||
class stylesheetBase:
|
||||
def __init__(self, _obj=None):
|
||||
if _obj != None:
|
||||
self._o = _obj;
|
||||
return
|
||||
self._o = None
|
||||
def __hash__(self):
|
||||
v = libxsltmod.xsltGetStylesheetHashCode(self._o)
|
||||
return v
|
||||
def __eq__(self, other):
|
||||
if other == None:
|
||||
return 0
|
||||
v = libxsltmod.xsltCompareStylesheetsEqual(self._o, other._o)
|
||||
return v
|
||||
|
||||
class extensionModule:
|
||||
def _styleInit(self, style, URI):
|
||||
return self.styleInit(stylesheet(_obj=style), URI)
|
||||
|
@ -11,6 +11,56 @@
|
||||
<arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
|
||||
<arg name='result' type='xmlDocPtr' info='The result document'/>
|
||||
</function>
|
||||
<function name='xsltSetLoaderFunc' file='python'>
|
||||
<info>Set the function for controlling document loading</info>
|
||||
<return type='long' info='0 for failure or 1 for success'/>
|
||||
<arg name='loader' type='pythonObject' info='the loader function; should take: string URI, xsltParserContext, context, type; when type == 1 the context is a stylesheet, when type == 0 the context is a transformCtxt'/>
|
||||
</function>
|
||||
<function name='xsltGetLoaderFunc' file='python'>
|
||||
<info>Get the function for controlling document loading</info>
|
||||
<return type='pythonObject *' info='the function'/>
|
||||
</function>
|
||||
<function name='xsltNewTransformContext' file='python'>
|
||||
<info>Create a new XSLT TransformContext</info>
|
||||
<return type='xsltTransformContextPtr' info='an xslt TransformContext'/>
|
||||
<arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
|
||||
<arg name='doc' type='xmlDocPtr' info='the input document'/>
|
||||
</function>
|
||||
<function name='xsltFreeTransformContext' file='python'>
|
||||
<info>Free up an existing XSLT TransformContext</info>
|
||||
<return type='void' info='None'/>
|
||||
<arg name='transformCtxt' type='xsltTransformContextPtr' info='an existing tranformCtxt'/>
|
||||
</function>
|
||||
<function name='xsltGetTransformContextHashCode' file='python'>
|
||||
<info>Get the hash code of the transformContext</info>
|
||||
<return type='int' info='the hash code' />
|
||||
<arg name='transformCtxt' type='xsltTransformContextPtr' info='a parsed XSLT transformContext'/>
|
||||
</function>
|
||||
<function name='xsltGetStylesheetHashCode' file='python'>
|
||||
<info>Get the hash code of the stylesheet</info>
|
||||
<return type='int' info='the hash code' />
|
||||
<arg name='stylesheet' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
|
||||
</function>
|
||||
<function name='xsltCompareTransformContextsEqual' file='python'>
|
||||
<info>Compare one transformCtxt with another</info>
|
||||
<return type='int' info='1 in case of success, 0 or -1 in error' />
|
||||
<arg name='transformCtxt' type='xsltTransformContextPtr' info='a parsed XSLT transformContext'/>
|
||||
<arg name='other' type='xsltTransformContextPtr' info='a parsed XSLT transformContext'/>
|
||||
</function>
|
||||
<function name='xsltCompareStylesheetsEqual' file='python'>
|
||||
<info>Compare one stylesheet with another</info>
|
||||
<return type='int' info='1 in case of success, 0 or -1 in error' />
|
||||
<arg name='stylesheet' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
|
||||
<arg name='other' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
|
||||
</function>
|
||||
<function name='xsltApplyStylesheetUser' file='python'>
|
||||
<info>Apply the stylesheet to the document</info>
|
||||
<return type='xmlDocPtr' info="the result document or NULL in case of error"/>
|
||||
<arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
|
||||
<arg name='doc' type='xmlDocPtr' info='a parsed XML document'/>
|
||||
<arg name='params' type='pythonObject' info='the parameters dictionnary'/>
|
||||
<arg name='transformCtxt' type='xsltTransformContextPtr' info='transformation context'/>
|
||||
</function>
|
||||
<function name='xsltApplyStylesheet' file='python'>
|
||||
<info>Apply the stylesheet to the document</info>
|
||||
<return type='xmlDocPtr' info="the result document or NULL in case of error"/>
|
||||
|
301
python/libxslt.c
301
python/libxslt.c
@ -20,6 +20,8 @@
|
||||
#include "libxslt_wrap.h"
|
||||
#include "libxslt-py.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(vsnprintf)
|
||||
#define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
|
||||
#elif defined(XSLT_NEED_TRIO)
|
||||
@ -55,6 +57,7 @@ libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr style) {
|
||||
}
|
||||
ret = PyCObject_FromVoidPtrAndDesc((void *) style,
|
||||
(char *)"xsltStylesheetPtr", NULL);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -90,6 +93,81 @@ libxslt_xsltElemPreCompPtrWrap(xsltElemPreCompPtr ctxt) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltGetTransformContextHashCode(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_tctxt;
|
||||
PyObject *ret;
|
||||
long hash_code;
|
||||
xsltTransformContextPtr tctxt;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"O:getTransformContextHashCode",
|
||||
&py_tctxt))
|
||||
return NULL;
|
||||
|
||||
tctxt = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt);
|
||||
hash_code = (long) tctxt;
|
||||
|
||||
ret = PyInt_FromLong(hash_code);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltCompareTransformContextsEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
|
||||
PyObject *py_tctxt1, *py_tctxt2;
|
||||
xsltTransformContextPtr tctxt1, tctxt2;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"OO:compareTransformContextsEqual",
|
||||
&py_tctxt1, &py_tctxt2))
|
||||
return NULL;
|
||||
|
||||
tctxt1 = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt1);
|
||||
tctxt2 = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt2);
|
||||
|
||||
if ( tctxt1 == tctxt2 )
|
||||
return Py_BuildValue((char *)"i", 1);
|
||||
else
|
||||
return Py_BuildValue((char *)"i", 0);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltGetStylesheetHashCode(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_style;
|
||||
PyObject *ret;
|
||||
long hash_code;
|
||||
xsltStylesheetPtr style;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"O:getStylesheetHashCode",
|
||||
&py_style))
|
||||
return NULL;
|
||||
|
||||
style = (xsltStylesheetPtr) Pystylesheet_Get(py_style);
|
||||
hash_code = (long) style;
|
||||
|
||||
ret = PyInt_FromLong(hash_code);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltCompareStylesheetsEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
|
||||
PyObject *py_style1, *py_style2;
|
||||
xsltStylesheetPtr style1, style2;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"OO:compareStylesheetsEqual",
|
||||
&py_style1, &py_style2))
|
||||
return NULL;
|
||||
|
||||
style1 = (xsltStylesheetPtr) Pystylesheet_Get(py_style1);
|
||||
style2 = (xsltStylesheetPtr) Pystylesheet_Get(py_style2);
|
||||
|
||||
if ( style1 == style2 )
|
||||
return Py_BuildValue((char *)"i", 1);
|
||||
else
|
||||
return Py_BuildValue((char *)"i", 0);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Extending the API *
|
||||
@ -423,12 +501,235 @@ libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED,
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Document loading front-ends *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
static PyObject *pythonDocLoaderObject = NULL;
|
||||
|
||||
static xmlDocPtr
|
||||
pythonDocLoaderFuncWrapper(const xmlChar * URI, xmlDictPtr dict, int options,
|
||||
void *ctxt ATTRIBUTE_UNUSED,
|
||||
xsltLoadType type ATTRIBUTE_UNUSED)
|
||||
{
|
||||
xmlParserCtxtPtr pctxt;
|
||||
xmlDocPtr doc;
|
||||
|
||||
pctxt = xmlNewParserCtxt();
|
||||
if (pctxt == NULL)
|
||||
return(NULL);
|
||||
if ((dict != NULL) && (pctxt->dict != NULL)) {
|
||||
xmlDictFree(pctxt->dict);
|
||||
pctxt->dict = NULL;
|
||||
}
|
||||
if (dict != NULL) {
|
||||
pctxt->dict = dict;
|
||||
xmlDictReference(pctxt->dict);
|
||||
#ifdef WITH_XSLT_DEBUG
|
||||
xsltGenericDebug(xsltGenericDebugContext,
|
||||
"Reusing dictionary for document\n");
|
||||
#endif
|
||||
}
|
||||
xmlCtxtUseOptions(pctxt, options);
|
||||
|
||||
/*
|
||||
* Now pass to python the URI, the xsltParserContext and the context
|
||||
* (either a transformContext or a stylesheet) and get back an xmlDocPtr
|
||||
*/
|
||||
if (pythonDocLoaderObject != NULL) {
|
||||
PyObject *ctxtobj, *pctxtobj, *result;
|
||||
pctxtobj = libxml_xmlParserCtxtPtrWrap(pctxt);
|
||||
|
||||
if (type == XSLT_LOAD_DOCUMENT) {
|
||||
ctxtobj = libxslt_xsltTransformContextPtrWrap(ctxt);
|
||||
result = PyObject_CallFunction(pythonDocLoaderObject,
|
||||
(char *) "(sOOi)", URI, pctxtobj, ctxtobj, 0);
|
||||
}
|
||||
else {
|
||||
ctxtobj = libxslt_xsltStylesheetPtrWrap(ctxt);
|
||||
result = PyObject_CallFunction(pythonDocLoaderObject,
|
||||
(char *) "(sOOi)", URI, pctxtobj, ctxtobj, 1);
|
||||
}
|
||||
|
||||
Py_XDECREF(pctxtobj);
|
||||
|
||||
if (result != NULL) {
|
||||
/*
|
||||
* The return value should be the document
|
||||
* Should we test it somehow before getting the C object from it?
|
||||
*/
|
||||
PyObject *py_doc = PyObject_GetAttrString(result, "_o");
|
||||
doc = PyxmlNode_Get(py_doc);
|
||||
/* do we have to DECCREF the result?? */
|
||||
}
|
||||
}
|
||||
|
||||
if (! pctxt->wellFormed) {
|
||||
if (doc != NULL) {
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
if (pctxt->myDoc != NULL) {
|
||||
doc = NULL;
|
||||
xmlFreeDoc(pctxt->myDoc);
|
||||
pctxt->myDoc = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* xmlFreeParserCtxt(pctxt);
|
||||
* libc complains about double free-ing with this line
|
||||
*/
|
||||
|
||||
return(doc);
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltSetLoaderFunc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
PyObject *loader;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"O:libxslt_xsltSetLoaderFunc",
|
||||
&loader))
|
||||
return(NULL);
|
||||
|
||||
pythonDocLoaderObject = loader;
|
||||
xsltSetLoaderFunc(pythonDocLoaderFuncWrapper);
|
||||
|
||||
py_retval = PyInt_FromLong(0);
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltGetLoaderFunc(void) {
|
||||
PyObject *py_retval;
|
||||
|
||||
py_retval = pythonDocLoaderObject;
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Some customized front-ends *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltNewTransformContext(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
PyObject *pyobj_style;
|
||||
PyObject *pyobj_doc;
|
||||
xsltStylesheetPtr style;
|
||||
xmlDocPtr doc;
|
||||
xsltTransformContextPtr c_retval;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *) "OO:xsltNewTransformContext",
|
||||
&pyobj_style, &pyobj_doc))
|
||||
return(NULL);
|
||||
|
||||
style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
|
||||
doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
|
||||
|
||||
c_retval = xsltNewTransformContext(style, doc);
|
||||
py_retval = libxslt_xsltTransformContextPtrWrap((xsltTransformContextPtr) c_retval);
|
||||
return (py_retval);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltFreeTransformContext(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_tctxt;
|
||||
xsltTransformContextPtr tctxt;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *) "O:xsltFreeTransformContext", &py_tctxt))
|
||||
return(NULL);
|
||||
|
||||
tctxt = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt);
|
||||
xsltFreeTransformContext(tctxt);
|
||||
|
||||
/* Return None */
|
||||
Py_INCREF(Py_None);
|
||||
return(Py_None);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltApplyStylesheetUser(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
xmlDocPtr c_retval;
|
||||
xsltStylesheetPtr style;
|
||||
PyObject *pyobj_style;
|
||||
xmlDocPtr doc;
|
||||
xsltTransformContextPtr transformCtxt;
|
||||
PyObject *pyobj_doc;
|
||||
PyObject *pyobj_params;
|
||||
PyObject *pyobj_transformCtxt;
|
||||
const char **params = NULL;
|
||||
int len = 0, i = 0, j;
|
||||
PyObject *name;
|
||||
PyObject *value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *) "OOOO:xsltApplyStylesheetUser",
|
||||
&pyobj_style, &pyobj_doc, &pyobj_params, &pyobj_transformCtxt))
|
||||
return(NULL);
|
||||
|
||||
if (pyobj_params != Py_None) {
|
||||
if (PyDict_Check(pyobj_params)) {
|
||||
len = PyDict_Size(pyobj_params);
|
||||
if (len > 0) {
|
||||
params = (const char **) xmlMalloc((len + 1) * 2 *
|
||||
sizeof(char *));
|
||||
if (params == NULL) {
|
||||
printf("libxslt_xsltApplyStylesheet: out of memory\n");
|
||||
Py_INCREF(Py_None);
|
||||
return(Py_None);
|
||||
}
|
||||
j = 0;
|
||||
while (PyDict_Next(pyobj_params, &i, &name, &value)) {
|
||||
const char *tmp;
|
||||
int size;
|
||||
|
||||
tmp = PyString_AS_STRING(name);
|
||||
size = PyString_GET_SIZE(name);
|
||||
params[j * 2] = (char *) xmlCharStrndup(tmp, size);
|
||||
if (PyString_Check(value)) {
|
||||
tmp = PyString_AS_STRING(value);
|
||||
size = PyString_GET_SIZE(value);
|
||||
params[(j * 2) + 1] = (char *)
|
||||
xmlCharStrndup(tmp, size);
|
||||
} else {
|
||||
params[(j * 2) + 1] = NULL;
|
||||
}
|
||||
j = j + 1;
|
||||
}
|
||||
params[j * 2] = NULL;
|
||||
params[(j * 2) + 1] = NULL;
|
||||
}
|
||||
} else {
|
||||
printf("libxslt_xsltApplyStylesheet: parameters not a dict\n");
|
||||
Py_INCREF(Py_None);
|
||||
return(Py_None);
|
||||
}
|
||||
}
|
||||
style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
|
||||
doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
|
||||
transformCtxt = (xsltTransformContextPtr) PytransformCtxt_Get(pyobj_transformCtxt);
|
||||
|
||||
c_retval = xsltApplyStylesheetUser(style, doc, params, NULL, NULL, transformCtxt);
|
||||
py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval);
|
||||
if (params != NULL) {
|
||||
if (len > 0) {
|
||||
for (i = 0;i < 2 * len;i++) {
|
||||
if (params[i] != NULL)
|
||||
xmlFree((char *)params[i]);
|
||||
}
|
||||
xmlFree(params);
|
||||
}
|
||||
}
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxslt_xsltApplyStylesheet(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
|
@ -22,6 +22,7 @@ registerErrorHandler()
|
||||
registerExtModuleElement()
|
||||
registerExtModuleFunction()
|
||||
registerExtensionClass()
|
||||
setLoaderFunc()
|
||||
|
||||
# functions from module xslt
|
||||
cleanupGlobals()
|
||||
@ -74,7 +75,9 @@ Class xpathContext(libxml2.xpathContext)
|
||||
|
||||
# functions from module functions
|
||||
registerAllFunctions()
|
||||
Class transformCtxt()
|
||||
|
||||
|
||||
Class transformCtxt(transformCtxtBase)
|
||||
# accessors
|
||||
context()
|
||||
current()
|
||||
@ -112,6 +115,11 @@ Class transformCtxt()
|
||||
plainNamespace()
|
||||
specialNamespace()
|
||||
|
||||
# functions from module python
|
||||
compareTransformContextsEqual()
|
||||
freeTransformContext()
|
||||
transformContextHashCode()
|
||||
|
||||
# functions from module templates
|
||||
attrListTemplateProcess()
|
||||
attrTemplateProcess()
|
||||
@ -145,7 +153,9 @@ Class transformCtxt()
|
||||
profileInformation()
|
||||
saveProfiling()
|
||||
setCtxtParseOptions()
|
||||
Class stylesheet()
|
||||
|
||||
|
||||
Class stylesheet(stylesheetBase)
|
||||
# accessors
|
||||
doc()
|
||||
doctypePublic()
|
||||
@ -195,7 +205,11 @@ Class stylesheet()
|
||||
|
||||
# functions from module python
|
||||
applyStylesheet()
|
||||
applyStylesheetUser()
|
||||
compareStylesheetsEqual()
|
||||
newTransformContext()
|
||||
saveResultToString()
|
||||
stylesheetHashCode()
|
||||
|
||||
# functions from module variables
|
||||
parseGlobalParam()
|
||||
|
Reference in New Issue
Block a user