applied a patch from Stéphane Bidoul to allow per XMLtextReader error and
* xmlreader.c include/libxml/xmlreader.h python/generator.py
python/libxml.c python/libxml.py win32/libxml2.def.src: applied
a patch from Stéphane Bidoul to allow per XMLtextReader error
and warning handling
* python/tests/Makefile.am python/tests/readererr.py: adding the
specific regression test
Daniel
diff --git a/python/generator.py b/python/generator.py
index f8a1e0b..cc1b41b 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -292,6 +292,8 @@
return 1
if name == "xmlFreeParserCtxt":
return 1
+ if name == "xmlFreeTextReader":
+ return 1
# if name[0:11] == "xmlXPathNew":
# return 1
return 0
@@ -621,6 +623,7 @@
"outputBuffer": "ioWriteWrapper",
"inputBuffer": "ioReadWrapper",
"parserCtxt": "parserCtxtCore",
+ "xmlTextReader": "xmlTextReaderCore",
}
classes_destructors = {
"parserCtxt": "xmlFreeParserCtxt",
diff --git a/python/libxml.c b/python/libxml.c
index f1b0d6a..a762ac7 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -1487,6 +1487,170 @@
/************************************************************************
* *
+ * Per xmlTextReader error handler *
+ * *
+ ************************************************************************/
+
+typedef struct
+{
+ PyObject *f;
+ PyObject *arg;
+} xmlTextReaderPyCtxt;
+typedef xmlTextReaderPyCtxt *xmlTextReaderPyCtxtPtr;
+
+static void
+libxml_xmlTextReaderErrorCallback(void *arg,
+ const char *msg,
+ int line,
+ int col,
+ const char *URI,
+ int severity)
+{
+ xmlTextReaderPyCtxt *pyCtxt = (xmlTextReaderPyCtxt *)arg;
+ PyObject *list;
+ PyObject *result;
+
+ list = PyTuple_New(6);
+ PyTuple_SetItem(list, 0, pyCtxt->arg);
+ Py_XINCREF(pyCtxt->arg);
+ PyTuple_SetItem(list, 1, libxml_charPtrConstWrap(msg));
+ PyTuple_SetItem(list, 2, libxml_intWrap(line));
+ PyTuple_SetItem(list, 3, libxml_intWrap(col));
+ PyTuple_SetItem(list, 4, libxml_charPtrConstWrap(URI));
+ PyTuple_SetItem(list, 5, libxml_intWrap(severity));
+ result = PyEval_CallObject(pyCtxt->f, list);
+ if (result == NULL)
+ {
+ /* TODO: manage for the exception to be go up... */
+ PyErr_Print();
+ }
+ Py_XDECREF(list);
+ Py_XDECREF(result);
+}
+
+PyObject *
+libxml_xmlTextReaderSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
+{
+ xmlTextReaderPtr reader;
+ xmlTextReaderPyCtxtPtr pyCtxt;
+ xmlTextReaderErrorFunc f;
+ void *arg;
+ PyObject *pyobj_reader;
+ PyObject *pyobj_f;
+ PyObject *pyobj_arg;
+ PyObject *py_retval;
+
+ if (!PyArg_ParseTuple(args, (char *)"OOO:xmlTextReaderSetErrorHandler", &pyobj_reader, &pyobj_f, &pyobj_arg))
+ return(NULL);
+ reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
+ /* clear previous error handler */
+ xmlTextReaderGetErrorHandler(reader,&f,&arg);
+ if (arg != NULL) {
+ if (f == libxml_xmlTextReaderErrorCallback) {
+ /* ok, it's our error handler! */
+ pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
+ Py_XDECREF(pyCtxt->f);
+ Py_XDECREF(pyCtxt->arg);
+ xmlFree(pyCtxt);
+ }
+ else {
+ /*
+ * there already an arg, and it's not ours,
+ * there is definitely something wrong going on here...
+ * we don't know how to free it, so we bail out...
+ */
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ }
+ xmlTextReaderSetErrorHandler(reader,NULL,NULL);
+ /* set new error handler */
+ if (pyobj_f != Py_None)
+ {
+ pyCtxt = (xmlTextReaderPyCtxtPtr)xmlMalloc(sizeof(xmlTextReaderPyCtxt));
+ if (pyCtxt == NULL) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ Py_XINCREF(pyobj_f);
+ pyCtxt->f = pyobj_f;
+ Py_XINCREF(pyobj_arg);
+ pyCtxt->arg = pyobj_arg;
+ xmlTextReaderSetErrorHandler(reader,libxml_xmlTextReaderErrorCallback,pyCtxt);
+ }
+
+ py_retval = libxml_intWrap(1);
+ return(py_retval);
+}
+
+PyObject *
+libxml_xmlTextReaderGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
+{
+ xmlTextReaderPtr reader;
+ xmlTextReaderPyCtxtPtr pyCtxt;
+ xmlTextReaderErrorFunc f;
+ void *arg;
+ PyObject *pyobj_reader;
+ PyObject *py_retval;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:xmlTextReaderSetErrorHandler", &pyobj_reader))
+ return(NULL);
+ reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
+ xmlTextReaderGetErrorHandler(reader,&f,&arg);
+ py_retval = PyTuple_New(2);
+ if (f == libxml_xmlTextReaderErrorCallback) {
+ /* ok, it's our error handler! */
+ pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
+ PyTuple_SetItem(py_retval, 0, pyCtxt->f);
+ Py_XINCREF(pyCtxt->f);
+ PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
+ Py_XINCREF(pyCtxt->arg);
+ }
+ else
+ {
+ /* f is null or it's not our error handler */
+ PyTuple_SetItem(py_retval, 0, Py_None);
+ Py_XINCREF(Py_None);
+ PyTuple_SetItem(py_retval, 1, Py_None);
+ Py_XINCREF(Py_None);
+ }
+ return(py_retval);
+}
+
+PyObject *
+libxml_xmlFreeTextReader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
+ xmlTextReaderPtr reader;
+ PyObject *pyobj_reader;
+ xmlTextReaderPyCtxtPtr pyCtxt;
+ xmlTextReaderErrorFunc f;
+ void *arg;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeTextReader", &pyobj_reader))
+ return(NULL);
+ reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
+
+ xmlTextReaderGetErrorHandler(reader,&f,&arg);
+ if (arg != NULL) {
+ if (f == libxml_xmlTextReaderErrorCallback) {
+ /* ok, it's our error handler! */
+ pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
+ Py_XDECREF(pyCtxt->f);
+ Py_XDECREF(pyCtxt->arg);
+ xmlFree(pyCtxt);
+ }
+ /*
+ * else, something wrong happened, because the error handler is
+ * not owned by the python bindings...
+ */
+ }
+
+ xmlFreeTextReader(reader);
+ Py_INCREF(Py_None);
+ return(Py_None);
+}
+
+/************************************************************************
+ * *
* XPath extensions *
* *
************************************************************************/
@@ -2397,6 +2561,9 @@
{(char *)"xmlSetParserCtxtErrorHandler", libxml_xmlSetParserCtxtErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlSetParserCtxtWarningHandler", libxml_xmlSetParserCtxtWarningHandler, METH_VARARGS, NULL },
{(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
+ {(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
+ {(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },
+ {(char *)"xmlFreeTextReader", libxml_xmlFreeTextReader, METH_VARARGS, NULL },
{NULL, NULL, 0, NULL}
};
diff --git a/python/libxml.py b/python/libxml.py
index 3e87891..8f9185c 100644
--- a/python/libxml.py
+++ b/python/libxml.py
@@ -462,6 +462,14 @@
PARSER_SUBST_ENTITIES=4
#
+# For the xmlTextReader error severities
+#
+XMLREADER_SEVERITY_VALIDITY_WARNING=1
+XMLREADER_SEVERITY_VALIDITY_ERROR=2
+XMLREADER_SEVERITY_WARNING=3
+XMLREADER_SEVERITY_ERROR=4
+
+#
# register the libxml2 error handler
#
def registerErrorHandler(f, ctx):
@@ -497,6 +505,28 @@
def registerWarningHandler(self,f,arg):
libxml2mod.xmlSetParserCtxtWarningHandler(self._o,f,arg)
+class xmlTextReaderCore:
+
+ def __init__(self, _obj=None):
+ self.input = None
+ if _obj != None:self._o = _obj;return
+ self._o = None
+
+ def __del__(self):
+ if self._o != None:
+ libxml2mod.xmlFreeTextReader(self._o)
+ self._o = None
+
+ def setErrorHandler(self,f,arg):
+ """Register an error handler that will be called back as
+ f(arg,msg,line,col,URI,severity)."""
+ libxml2mod.xmlTextReaderSetErrorHandler(self._o,f,arg)
+
+ def getErrorHandler(self):
+ """Return (f,arg) as previously registered with setErrorHandler
+ or (None,None)."""
+ return libxml2mod.xmlTextReaderGetErrorHandler(self._o)
+
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
#
# Everything before this line comes from libxml.py
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index d35d34b..a116126 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -558,7 +558,9 @@
freeProp()
freePropList()
removeProp()
-Class xmlTextReader()
+
+
+Class xmlTextReader(xmlTextReaderCore)
# functions from module xmlreader
AttributeCount()
@@ -599,7 +601,6 @@
SetParserProp()
Value()
XmlLang()
- freeTextReader()
Class xmlReg()
# functions from module xmlregexp
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
index 23c9b55..55a9acb 100644
--- a/python/tests/Makefile.am
+++ b/python/tests/Makefile.am
@@ -23,7 +23,8 @@
reader.py \
reader2.py \
reader3.py \
- ctxterror.py
+ ctxterror.py\
+ readererr.py
XMLS= \
tst.xml \