[xml] Patch for the RelaxNG error callbacks from Python



Hi Daniel,

here is the patch to support setting the error callbacks of the RelaxNG validation
contexts from Python code.

Currently, I'm trying to modify the generator to output the correct functions
to libxml2.py but without luck. Where must I include some text, so the Python
class "relaxNgValidCtxt" gets a new method "relaxNGSetSetValidErrors"?

Joachim

--
Joachim Bauch

struktur AG             Fon.:  +49 (0)711 896656 69
Junghansstr. 5          Fax.:  +49 (0)711 896656 10
D-70469 Stuttgart       eMail: bauch struktur de                    solutions for
Germany                 Web:   http://www.struktur.de            digital business

Download icoya OpenContent 1.3 for FREE!    visit http://www.icoya.de/iOC4free <-
2578a2579,2752
#ifdef LIBXML_SCHEMAS_ENABLED

/************************************************************************
 *                                                                      *
 * RelaxNG error handler registration                                   *
 *                                                                      *
 ************************************************************************/

typedef struct 
{
    PyObject *warn;
    PyObject *error;
    PyObject *arg;
} xmlRelaxNGValidCtxtPyCtxt;
typedef xmlRelaxNGValidCtxtPyCtxt *xmlRelaxNGValidCtxtPyCtxtPtr;

static void
libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void *ctx, char *str) 
{
    PyObject *list;
    PyObject *result;
    xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
    
#ifdef DEBUG_ERROR
    printf("libxml_xmlRelaxNGValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
#endif

    pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;

    list = PyTuple_New(2);
    PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
    PyTuple_SetItem(list, 1, pyCtxt->arg);
    Py_XINCREF(pyCtxt->arg);
    result = PyEval_CallObject(pyCtxt->error, list);
    if (result == NULL) 
    {
        /* TODO: manage for the exception to be propagated... */
        PyErr_Print();
    }
    Py_XDECREF(list);
    Py_XDECREF(result);
}

static void
libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void *ctx, char *str) 
{
    PyObject *list;
    PyObject *result;
    xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
    
#ifdef DEBUG_ERROR
    printf("libxml_xmlRelaxNGValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
#endif

    pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;

    list = PyTuple_New(2);
    PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
    PyTuple_SetItem(list, 1, pyCtxt->arg);
    Py_XINCREF(pyCtxt->arg);
    result = PyEval_CallObject(pyCtxt->warn, list);
    if (result == NULL) 
    {
        /* TODO: manage for the exception to be propagated... */
        PyErr_Print();
    }
    Py_XDECREF(list);
    Py_XDECREF(result);
}

static void
libxml_xmlRelaxNGValidityErrorFunc(void *ctx, const char *msg, ...)
{
    va_list ap;

    va_start(ap, msg);
    libxml_xmlRelaxNGValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
    va_end(ap);
}

static void
libxml_xmlRelaxNGValidityWarningFunc(void *ctx, const char *msg, ...)
{
    va_list ap;

    va_start(ap, msg);
    libxml_xmlRelaxNGValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
    va_end(ap);
}

static PyObject *
libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
{
    PyObject *py_retval;
    PyObject *pyobj_error;
    PyObject *pyobj_warn;
    PyObject *pyobj_ctx;
    PyObject *pyobj_arg = Py_None;
    xmlRelaxNGValidCtxtPtr ctxt;
    xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;

    if (!PyArg_ParseTuple
        (args, (char *) "OOO|O:xmlRelaxNGSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, 
&pyobj_arg))
        return (NULL);

#ifdef DEBUG_ERROR
    printf("libxml_xmlRelaxNGSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
#endif

    ctxt = PyrelaxNgValidCtxt_Get(pyobj_ctx);
    if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, &pyCtxt) == -1)
    {
        py_retval = libxml_intWrap(-1);
        return(py_retval);
    }
    
    if (pyCtxt == NULL)
    {
        // first time to set the error handlers
        pyCtxt = xmlMalloc(sizeof(xmlRelaxNGValidCtxtPyCtxt));
        if (pyCtxt == NULL) {
            py_retval = libxml_intWrap(-1);
            return(py_retval);
        }
        memset(pyCtxt, 0, sizeof(xmlRelaxNGValidCtxtPyCtxt));
    }
    
    /* TODO: check warn and error is a function ! */
    Py_XDECREF(pyCtxt->error);
    Py_XINCREF(pyobj_error);
    pyCtxt->error = pyobj_error;
    
    Py_XDECREF(pyCtxt->warn);
    Py_XINCREF(pyobj_warn);
    pyCtxt->warn = pyobj_warn;
    
    Py_XDECREF(pyCtxt->arg);
    Py_XINCREF(pyobj_arg);
    pyCtxt->arg = pyobj_arg;

    xmlRelaxNGSetValidErrors(ctxt, &libxml_xmlRelaxNGValidityErrorFunc, 
&libxml_xmlRelaxNGValidityWarningFunc, pyCtxt);

    py_retval = libxml_intWrap(1);
    return (py_retval);
}

PyObject *
libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
    xmlRelaxNGValidCtxtPtr ctxt;
    xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
    PyObject *pyobj_ctxt;

    if (!PyArg_ParseTuple(args, (char *)"O:xmlRelaxNGFreeValidCtxt", &pyobj_ctxt))
        return(NULL);
    ctxt = (xmlRelaxNGValidCtxtPtr) PyrelaxNgValidCtxt_Get(pyobj_ctxt);

    if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, &pyCtxt) == 0)
    {
        if (pyCtxt != NULL)
        {
            Py_XDECREF(pyCtxt->error);
            Py_XDECREF(pyCtxt->warn);
            Py_XDECREF(pyCtxt->arg);
            xmlFree(pyCtxt);
        }
    }
    
    xmlRelaxNGFreeValidCtxt(ctxt);
    Py_INCREF(Py_None);
    return(Py_None);
}

#endif

2608a2783,2786
#ifdef LIBXML_SCHEMAS_ENABLED
    {(char *)"xmlRelaxNGSetValidErrors", libxml_xmlRelaxNGSetValidErrors, METH_VARARGS, NULL},
    {(char *)"xmlRelaxNGFreeValidCtxt", libxml_xmlRelaxNGFreeValidCtxt, METH_VARARGS, NULL},
#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]