List Info

Thread: python wrapper for document API (AND transformCtxt API)




python wrapper for document API (AND transformCtxt API)
user name
2006-09-07 00:40:34
This is my two recent areas of work combined.

My motivation for building this API was to allow me to
identify what
transformation a particular load was occuring for and this
patch
enables me to do that. That's why I've combined them...
they actually
make sense (to me anyway) together.


It does the following:

- adds a function to create an xslt transformContext from
python

- adds a function to apply a stylesheet with a user supplied
  transformContext

- adds a python doc loader which calls a registered python
function
  with a URI, xpathParserContext and transformContext and
accepts a
  document in return

- adds a function to set the doc loader to a python function

- adds comparison API for transformContext objects


The patch is not complete... but it is usable and I will
complete it
by adding these functions:

- a free for transformContext objects

- a getter for the python doc loader function


There are some problems that I could use some help with:

- why is the doc loader context sometimes a stylesheet
instead of a
  transformContext?

  can libxslt/libxslt/documents.c:sltLo
adStyleDocument be changed so
  that it creates a transformContext or something?

- when the doc comes back from the python doc loader
function do I
  have to DECREF it in some way?

- if I uncomment the xmlFreeParserCtxt(pctxt) at the end of
the
  pythonDocLoaderFuncWrapper I get complaints from libc
about double
  free-ing:

    *** glibc detected *** double free or corruption
(fasttop): 0x0819a7f8 ***
    Aborted

  I can't see why this is really... I've copied the bones
of the
  function from the libxml2 entity loader solution and it
doesn't seem
  to have a problem with double free-ing.

- why could I not get a static cmp function to work as with
  libxml_compareNodesEqual? 

  There seems to be some difference between the libxml
generator and
  the libxslt one?


-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs

Only in ../pristine/libxslt-1.1.17/libexslt: exsltconfig.h
Only in ../pristine/libxslt-1.1.17/libxslt: xsltconfig.h
Only in ../pristine/libxslt-1.1.17/libxslt:
xsltwin32config.h
Only in ../pristine/libxslt-1.1.17: libxslt.spec
diff -r -u ../pristine/libxslt-1.1.17/python/generator.py
./python/generator.py
---
../pristine/libxslt-1.1.17/python/generator.py	2004-01-22
17:40:16.000000000 +0000
+++ ./python/generator.py	2006-09-07 00:24:31.000000000
+0100
 -564,6
+564,7 
 classes_ancestor = {
     "xpathContext" :
"libxml2.xpathContext",
     "xpathParserContext" :
"libxml2.xpathParserContext",
+    "transformCtxt":
"transformCtxtBase",
 }
 classes_destructors = {
     "xpathContext" : "pass"
Only in ./python: generator.py~
diff -r -u ../pristine/libxslt-1.1.17/python/libxsl.py
./python/libxsl.py
--- ../pristine/libxslt-1.1.17/python/libxsl.py	2004-07-11
12:12:33.000000000 +0100
+++ ./python/libxsl.py	2006-09-07 00:46:18.000000000 +0100
 -56,6
+56,20 
         import libxsltmod
         import libxml2
 
+
+class transformCtxtBase:
+    def __init__(self, _obj=None):
+        if _obj != None: 
+            self._o = _obj;
+            return
+        self._o = None
+    def __eq__(self, other):
+        if self == None or other == None:
+            return 0
+        v =
libxsltmod.xsltCompareTransformContextsEqual(self._o,
other._o)
+        return v
+        
+
 class extensionModule:
     def _styleInit(self, style, URI):
         return self.styleInit(stylesheet(_obj=style), URI)
Only in ./python: libxsl.py~
Only in ../pristine/libxslt-1.1.17/python: libxslt-py.c
diff -r -u
../pristine/libxslt-1.1.17/python/libxslt-python-api.xml
./python/libxslt-python-api.xml
---
../pristine/libxslt-1.1.17/python/libxslt-python-api.xml	200
6-09-01 03:14:20.000000000 +0100
+++ ./python/libxslt-python-api.xml	2006-09-07
00:33:35.000000000 +0100
 -11,6
+11,31 
       <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 or 1'/>
+      <arg name='loader' type='pythonObject'
info='the loader 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='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='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"/>
Only in ./python: libxslt-python-api.xml~
diff -r -u ../pristine/libxslt-1.1.17/python/libxslt.c
./python/libxslt.c
--- ../pristine/libxslt-1.1.17/python/libxslt.c	2004-07-02
14:49:07.000000000 +0100
+++ ./python/libxslt.c	2006-09-07 00:34:38.000000000 +0100
 -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,9 
     }
     ret = PyCObject_FromVoidPtrAndDesc((void *) style,
 	                               (char
*)"xsltStylesheetPtr", NULL);
+
+    // Py_AddAttr(ret, cmp_function_impl);
+
     return(ret);
 }
 
 -90,6
+95,26 
     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);
+}
+
+
 /**********************************************************
**************
  *									*
  *			Extending the API				*
 -423,6
+448,105 
     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: pctxt, uri, options, ctxt
+    // the ctxt should be the stylesheet allowing us to
differentiate between transformations
+    if (pythonDocLoaderObject != NULL) {
+        xsltStylesheetPtr style;
+        PyObject *ctxtobj;
+        PyObject *pctxtobj;
+        PyObject *result;
+
+        style = (xsltStylesheetPtr) ctxt;
+        ctxtobj = libxslt_xsltStylesheetPtrWrap(ctxt);
+        pctxtobj = libxml_xmlParserCtxtPtrWrap(pctxt);
+
+        // For now just send parserContext and URL
+        result =
PyObject_CallFunction(pythonDocLoaderObject, 
+                                       (char *)
"(sOO)", URI, pctxtobj, ctxtobj);
+	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) {
+        // xmlDocDump(stderr, doc);
+        ;
+    }
+    else {
+        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);    
+}
+
+
+
 /**********************************************************
**************
  *									*
  *			Some customized front-ends			*
 -430,6
+554,103 
 
************************************************************
************/
 
 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 *) "OOsltNe
wTransformContext",
+		          &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_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 *) "OOOOsltAp
plyStylesheetUser",
+		          &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;
     xmlDocPtr c_retval;
Only in ./python: libxslt.c~
Only in ./python/tests: loader.py
Only in ./python/tests: loader.py~
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
python wrapper for document API (AND transformCtxt API)
user name
2006-09-07 01:51:06
On Thu, Sep 07, 2006 at 01:40:34AM +0100, Nic James Ferrier
wrote:
> This is my two recent areas of work combined.
> 
> My motivation for building this API was to allow me to
identify what
> transformation a particular load was occuring for and
this patch
> enables me to do that. That's why I've combined
them... they actually
> make sense (to me anyway) together.
> 
> 
> It does the following:
> 
> - adds a function to create an xslt transformContext
from python
> 
> - adds a function to apply a stylesheet with a user
supplied
>   transformContext
> 
> - adds a python doc loader which calls a registered
python function
>   with a URI, xpathParserContext and transformContext
and accepts a
>   document in return
> 
> - adds a function to set the doc loader to a python
function
> 
> - adds comparison API for transformContext objects
> 
> 
> The patch is not complete... but it is usable and I
will complete it
> by adding these functions:
> 
> - a free for transformContext objects
> 
> - a getter for the python doc loader function
> 
> 
> There are some problems that I could use some help
with:
> 
> - why is the doc loader context sometimes a stylesheet
instead of a
>   transformContext?
> 
>   can libxslt/libxslt/documents.c:sltLo
adStyleDocument be changed so
>   that it creates a transformContext or something?

  You may load files at stylesheet compilation time or at 
transformation time
the context are clearly different, and can't be unified...

> - when the doc comes back from the python doc loader
function do I
>   have to DECREF it in some way?

  Can't tell from memory. I guess that when python passes
an argument it 
increase the count for the function, but when it's a return
value the
count is not incremented.

> - if I uncomment the xmlFreeParserCtxt(pctxt) at the
end of the
>   pythonDocLoaderFuncWrapper I get complaints from libc
about double
>   free-ing:
> 
>     *** glibc detected *** double free or corruption
(fasttop): 0x0819a7f8 ***
>     Aborted
> 
>   I can't see why this is really... I've copied the
bones of the
>   function from the libxml2 entity loader solution and
it doesn't seem
>   to have a problem with double free-ing.

  No idea, need debug.

> - why could I not get a static cmp function to work as
with
>   libxml_compareNodesEqual? 

  out of context, what function ?

>   There seems to be some difference between the libxml
generator and
>   the libxslt one?

  well some of it may be error when updating one and not the
other, but
also the libxslt one need to support more types, so they
aren't really the
same.

Daniel

-- 
Red Hat Virtualization group http://redhat.com/v
irtualization/
Daniel Veillard      | virtualization library  http://libvirt.org/
veillardredhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ |
Rpmfind RPM search engine  http://rpmfind.net/
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
python wrapper for document API (AND transformCtxt API)
user name
2006-09-07 02:26:11
Daniel Veillard <veillardredhat.com> writes:

>> There are some problems that I could use some help
with:
>> 
>> - why is the doc loader context sometimes a
stylesheet instead of a
>>   transformContext?
>> 
>>   can libxslt/libxslt/documents.c:sltLo
adStyleDocument be changed so
>>   that it creates a transformContext or something?
>
> You may load files at stylesheet compilation time or at
 transformation time
> the context are clearly different, and can't be
unified...

A struct of an identifier and a union of stylesheet and
transformContext? 

or 2 different values in the function sig with one being
NULL when the
other is used?


My problem is passing the context to the python code
requires me to
establish what the context is. I'm not a C expert by any
stroke of the
chalk... but I don't think there is a way to tell one
struct from
another via a void *. Is there?

Or can I just do it by the xsltLoadType?

-- 
Nic Ferrier
http://www.tapsellfer
rier.co.uk   for all your tapsell ferrier needs
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
xmlgnome.org
http://mai
l.gnome.org/mailman/listinfo/xml
[1-3]

about | contact  Other archives ( Real Estate discussion Medical topics )