1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-30 22:43:14 +03:00

applied a patch from Stphane 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 Stphane Bidoul to allow per XMLtextReader error
  and warning handling
* python/tests/Makefile.am python/tests/readererr.py: adding the
  specific regression test
Daniel
This commit is contained in:
Daniel Veillard
2003-01-16 22:45:08 +00:00
parent 71f9d7310c
commit 26f70269c8
9 changed files with 390 additions and 3 deletions

View File

@ -1,3 +1,12 @@
Fri Jan 17 00:31:30 CET 2003 Daniel Veillard <daniel@veillard.com>
* xmlreader.c include/libxml/xmlreader.h python/generator.py
python/libxml.c python/libxml.py win32/libxml2.def.src: applied
a patch from St<53>phane Bidoul to allow per XMLtextReader error
and warning handling
* python/tests/Makefile.am python/tests/readererr.py: adding the
specific regression test
Tue Jan 14 17:00:08 CET 2003 Daniel Veillard <daniel@veillard.com>
* xpath.c: Alexey Efimov pointed out that concat('a', 'b', )

View File

@ -23,6 +23,13 @@ typedef enum {
XML_PARSER_SUBST_ENTITIES = 4
} xmlParserProperties;
typedef enum {
XMLREADER_SEVERITY_VALIDITY_WARNING = 1,
XMLREADER_SEVERITY_VALIDITY_ERROR = 2,
XMLREADER_SEVERITY_WARNING = 3,
XMLREADER_SEVERITY_ERROR = 4
} xmlReaderSeverities;
typedef struct _xmlTextReader xmlTextReader;
typedef xmlTextReader *xmlTextReaderPtr;
@ -99,6 +106,23 @@ int xmlTextReaderGetParserProp (xmlTextReaderPtr reader,
int prop);
xmlNodePtr xmlTextReaderCurrentNode (xmlTextReaderPtr reader);
xmlDocPtr xmlTextReaderCurrentDoc (xmlTextReaderPtr reader);
/*
* Error handling extensions
*/
typedef void (*xmlTextReaderErrorFunc) (void *arg,
const char *msg,
int line,
int col,
const char *URI,
xmlReaderSeverities severity);
void xmlTextReaderSetErrorHandler (xmlTextReaderPtr reader,
xmlTextReaderErrorFunc f,
void *arg);
void xmlTextReaderGetErrorHandler (xmlTextReaderPtr reader,
xmlTextReaderErrorFunc *f,
void **arg);
#ifdef __cplusplus
}
#endif

View File

@ -292,6 +292,8 @@ def skip_function(name):
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 @@ classes_ancestor = {
"outputBuffer": "ioWriteWrapper",
"inputBuffer": "ioReadWrapper",
"parserCtxt": "parserCtxtCore",
"xmlTextReader": "xmlTextReaderCore",
}
classes_destructors = {
"parserCtxt": "xmlFreeParserCtxt",

View File

@ -1485,6 +1485,170 @@ libxml_xmlSetParserCtxtWarningHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject
return(py_retval);
}
/************************************************************************
* *
* 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 @@ static PyMethodDef libxmlMethods[] = {
{(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}
};

View File

@ -461,6 +461,14 @@ PARSER_DEFAULTATTRS=2
PARSER_VALIDATE=3
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
#
@ -497,6 +505,28 @@ class parserCtxtCore:
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

View File

@ -558,7 +558,9 @@ Class xmlAttr(xmlNode)
freeProp()
freePropList()
removeProp()
Class xmlTextReader()
Class xmlTextReader(xmlTextReaderCore)
# functions from module xmlreader
AttributeCount()
@ -599,7 +601,6 @@ Class xmlTextReader()
SetParserProp()
Value()
XmlLang()
freeTextReader()
Class xmlReg()
# functions from module xmlregexp

View File

@ -23,7 +23,8 @@ PYTESTS= \
reader.py \
reader2.py \
reader3.py \
ctxterror.py
ctxterror.py\
readererr.py
XMLS= \
tst.xml \

View File

@ -1216,6 +1216,9 @@ xmlCleanupPredefinedEntities
xmlTextReaderGetParserProp
xmlTextReaderCurrentNode
xmlTextReaderCurrentDoc
/* Error handling extensions */
xmlTextReaderSetErrorHandler
xmlTextReaderGetErrorHandler

View File

@ -24,6 +24,7 @@
#include "libxml.h"
#include <string.h> /* for memset() only ! */
#include <stdarg.h>
#ifdef HAVE_CTYPE_H
#include <ctype.h>
@ -107,6 +108,10 @@ struct _xmlTextReader {
int entNr; /* Depth of the entities stack */
int entMax; /* Max depth of the entities stack */
xmlNodePtr *entTab; /* array of entities */
/* error handling */
xmlTextReaderErrorFunc errorFunc; /* callback function */
void *errorFuncArg; /* callback function user argument */
};
static const char *xmlTextReaderIsEmpty = "This element is empty";
@ -2235,6 +2240,150 @@ xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
return(reader->ctxt->myDoc);
}
/************************************************************************
* *
* Error Handling Extensions *
* *
************************************************************************/
/* helper to build a xmlMalloc'ed string from a format and va_list */
static char *
xmlTextReaderBuildMessage(const char *msg, va_list ap) {
int size;
int chars;
char *larger;
char *str;
str = (char *) xmlMalloc(150);
if (str == NULL) {
xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
return NULL;
}
size = 150;
while (1) {
chars = vsnprintf(str, size, msg, ap);
if ((chars > -1) && (chars < size))
break;
if (chars > -1)
size += chars + 1;
else
size += 100;
if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
xmlFree(str);
return NULL;
}
str = larger;
}
return str;
}
static void
xmlTextReaderGenericError(void *ctxt, int severity, char *str) {
xmlParserCtxtPtr ctx = (xmlParserCtxtPtr)ctxt;
xmlTextReaderPtr reader = (xmlTextReaderPtr)ctx->_private;
if (str != NULL) {
reader->errorFunc(reader->errorFuncArg,
str,
ctx->input->line,
ctx->input->col,
ctx->input->filename,
severity);
xmlFree(str);
}
}
static void
xmlTextReaderError(void *ctxt, const char *msg, ...) {
va_list ap;
va_start(ap,msg);
xmlTextReaderGenericError(ctxt,
XMLREADER_SEVERITY_ERROR,
xmlTextReaderBuildMessage(msg,ap));
va_end(ap);
}
static void
xmlTextReaderWarning(void *ctxt, const char *msg, ...) {
va_list ap;
va_start(ap,msg);
xmlTextReaderGenericError(ctxt,
XMLREADER_SEVERITY_WARNING,
xmlTextReaderBuildMessage(msg,ap));
va_end(ap);
}
static void
xmlTextReaderValidityError(void *ctxt, const char *msg, ...) {
va_list ap;
va_start(ap,msg);
xmlTextReaderGenericError(ctxt,
XMLREADER_SEVERITY_VALIDITY_ERROR,
xmlTextReaderBuildMessage(msg,ap));
va_end(ap);
}
static void
xmlTextReaderValidityWarning(void *ctxt, const char *msg, ...) {
va_list ap;
va_start(ap,msg);
xmlTextReaderGenericError(ctxt,
XMLREADER_SEVERITY_VALIDITY_WARNING,
xmlTextReaderBuildMessage(msg,ap));
va_end(ap);
}
/**
* xmlTextReaderSetErrorHandler:
* @reader: the xmlTextReaderPtr used
* @f: the callback function to call on error and warnings
* @arg: a user argument to pass to the callback function
*
* If @f is NULL, the default error and warning handlers are restored.
*/
void
xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
xmlTextReaderErrorFunc f,
void *arg)
{
if (f != NULL) {
reader->ctxt->sax->error = xmlTextReaderError;
reader->ctxt->vctxt.error = xmlTextReaderValidityError;
reader->ctxt->sax->warning = xmlTextReaderWarning;
reader->ctxt->vctxt.warning = xmlTextReaderValidityWarning;
reader->errorFunc = f;
reader->errorFuncArg = arg;
}
else {
/* restore defaults */
reader->ctxt->sax->error = xmlParserError;
reader->ctxt->vctxt.error = xmlParserValidityError;
reader->ctxt->sax->warning = xmlParserWarning;
reader->ctxt->vctxt.warning = xmlParserValidityWarning;
reader->errorFunc = NULL;
reader->errorFuncArg = NULL;
}
}
void
xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader,
xmlTextReaderErrorFunc *f,
void **arg)
{
*f = reader->errorFunc;
*arg = reader->errorFuncArg;
}
/************************************************************************
* *
* Utilities *