applied patch from Nic James Ferrier to make stylesheets comparable and to
authorDaniel Veillard <veillard@src.gnome.org>
Mon, 11 Dec 2006 11:11:06 +0000 (11:11 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Mon, 11 Dec 2006 11:11:06 +0000 (11:11 +0000)
* 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

ChangeLog
configure.in
python/generator.py
python/libxsl.py
python/libxslt-python-api.xml
python/libxslt.c
python/libxsltclass.txt

index a9b2f80..65c71bd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Mon Dec 11 12:13:14 CET 2006 Daniel Veillard <daniel@veillard.com>
+
+       * 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
+
 Sat Dec  9 15:22:34 PST 2006 William Brack <wbrack@mmm.com.hk>
 
        * libexslt/functions.c: changed handling of function params
index 73e1b78..bf93c3a 100644 (file)
@@ -183,6 +183,7 @@ if test "$with_python" != "no" ; then
     fi
     if test "$PYTHON" != ""
     then
+        echo "PYTHON is pointing at $PYTHON"
         PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"`
        echo Found Python version $PYTHON_VERSION
        LIBXML2_PYTHON=`$PYTHON -c "try : import libxml2 ; print 1
index 7b82b04..c13d606 100755 (executable)
@@ -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"
index 56aa8f1..503aa4f 100644 (file)
@@ -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)
index 8fbaacf..fc35e5d 100644 (file)
       <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"/>
index 6433626..5337b7a 100644 (file)
@@ -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,6 +501,116 @@ 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                      *
@@ -430,6 +618,119 @@ libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED,
  ************************************************************************/
 
 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;
     xmlDocPtr c_retval;
index 555b69f..7ed4056 100644 (file)
@@ -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()