1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-17 18:21:05 +03:00

patch from Stphane Bidoul for better per context error message APIs

* xmlreader.c python/drv_libxml2.py python/generator.py
  python/libxml.c python/libxml.py python/libxml_wrap.h
  python/types.c: patch from Stphane Bidoul for better per
  context error message APIs
* python/tests/ctxterror.py python/tests/readererr.py:
  update of the tests
Daniel
This commit is contained in:
Daniel Veillard
2003-01-20 21:26:34 +00:00
parent 97ddfc0b29
commit 417be3ae08
12 changed files with 400 additions and 238 deletions

View File

@ -9,10 +9,10 @@ USAGE
CAVEATS
- Lexical handlers are supported, except for start/endEntity
(waiting for XmlReader.ResolveEntity) and start/endDTD
- as understand it, libxml2 error handlers are globals (per thread);
each call to parse() registers a new error handler,
overwriting any previously registered handler
--> you can't have 2 LibXml2Reader active at the same time
- Error callbacks are not exactly synchronous, they tend
to be invoked before the corresponding content callback,
because the underlying reader interface parses
data by chunks of 512 bytes
TODO
- search for TODO
@ -34,7 +34,7 @@ TODO
"""
__author__ = u"St<EFBFBD>phane Bidoul <sbi@skynet.be>"
__version__ = "0.2"
__version__ = "0.3"
import codecs
import sys
@ -69,15 +69,27 @@ except ImportError, e:
raise SAXReaderNotAvailable("libxml2 not available: " \
"import error was: %s" % e)
def _registerErrorHandler(handler):
if not sys.modules.has_key('libxslt'):
# normal behaviour when libxslt is not imported
libxml2.registerErrorHandler(handler,"drv_libxml2")
else:
# when libxslt is imported, one must
# use libxst's error handler instead (see libxml2 bug 102181)
import libxslt
libxslt.registerErrorHandler(handler,"drv_libxml2")
class Locator(xmlreader.Locator):
"""SAX Locator adapter for libxml2.xmlTextReaderLocator"""
def __init__(self,locator):
self.__locator = locator
def getColumnNumber(self):
"Return the column number where the current event ends."
return -1
def getLineNumber(self):
"Return the line number where the current event ends."
return self.__locator.LineNumber()
def getPublicId(self):
"Return the public identifier for the current event."
return None
def getSystemId(self):
"Return the system identifier for the current event."
return self.__locator.BaseURI()
class LibXml2Reader(xmlreader.XMLReader):
@ -95,21 +107,30 @@ class LibXml2Reader(xmlreader.XMLReader):
# error messages accumulator
self.__errors = None
def _errorHandler(self,ctx,str):
def _errorHandler(self,arg,msg,severity,locator):
if self.__errors is None:
self.__errors = []
self.__errors.append(str)
self.__errors.append((severity,
SAXParseException(msg,None,
Locator(locator))))
def _reportError(self,callback):
# TODO: use SAXParseException, but we need a Locator for that
# TODO: distinguish warnings from errors
msg = "".join(self.__errors)
def _reportErrors(self,fatal):
for severity,exception in self.__errors:
if severity in (libxml2.PARSER_SEVERITY_VALIDITY_WARNING,
libxml2.PARSER_SEVERITY_WARNING):
self._err_handler.warning(exception)
else:
# when fatal is set, the parse will stop;
# we consider that the last error reported
# is the fatal one.
if fatal and exception is self.__errors[-1][1]:
self._err_handler.fatalError(exception)
else:
self._err_handler.error(exception)
self.__errors = None
callback(SAXException(msg))
def parse(self, source):
self.__parsing = 1
_registerErrorHandler(self._errorHandler)
try:
# prepare source and create reader
if type(source) in StringTypes:
@ -118,6 +139,7 @@ class LibXml2Reader(xmlreader.XMLReader):
source = saxutils.prepare_input_source(source)
input = libxml2.inputBuffer(source.getByteStream())
reader = input.newTextReader(source.getSystemId())
reader.SetErrorHandler(self._errorHandler,None)
# configure reader
reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
@ -137,21 +159,18 @@ class LibXml2Reader(xmlreader.XMLReader):
# check for errors
if r == 1:
if not self.__errors is None:
# non-fatal error
self._reportError(self._err_handler.error)
self._reportErrors(0)
elif r == 0:
if not self.__errors is None:
# non-fatal error
self._reportError(self._err_handler.error)
break
self._reportErrors(0)
break # end of parse
else:
# fatal error
if not self.__errors is None:
self._reportError(self._err_handler.fatalError)
self._reportErrors(1)
else:
self._err_handler.fatalError(\
SAXException("Read failed (no details available)"))
break
break # fatal parse error
# get node type
nodeType = reader.NodeType()
# Element
@ -180,6 +199,7 @@ class LibXml2Reader(xmlreader.XMLReader):
_d(reader.LocalName()))
qnames[attName] = qname
attrs[attName] = value
reader.MoveToElement()
self._cont_handler.startElementNS( \
eltName,eltQName,attributesNSImpl)
if reader.IsEmptyElement():
@ -194,6 +214,7 @@ class LibXml2Reader(xmlreader.XMLReader):
while reader.MoveToNextAttribute():
attName = _d(reader.Name())
attrs[attName] = _d(reader.Value())
reader.MoveToElement()
self._cont_handler.startElement( \
eltName,attributesImpl)
if reader.IsEmptyElement():
@ -275,7 +296,6 @@ class LibXml2Reader(xmlreader.XMLReader):
reader.Close()
finally:
self.__parsing = 0
# TODO: unregister error handler?
def setDTDHandler(self, handler):
# TODO (when supported, the inherited method works just fine)

View File

@ -271,6 +271,7 @@ py_types = {
'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutputBufferPtr"),
'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"),
'xmlRegexpPtr': ('O', "xmlReg", "xmlRegexpPtr", "xmlRegexpPtr"),
'xmlTextReaderLocatorPtr': ('O', "xmlTextReaderLocator", "xmlTextReaderLocatorPtr", "xmlTextReaderLocatorPtr"),
'xmlTextReaderPtr': ('O', "xmlTextReader", "xmlTextReaderPtr", "xmlTextReaderPtr"),
}
@ -602,6 +603,7 @@ classes_type = {
"xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"),
"xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"),
"xmlRegexpPtr": ("._o", "xmlReg(_obj=%s)", "xmlReg"),
"xmlTextReaderLocatorPtr": ("._o", "xmlTextReaderLocator(_obj=%s)", "xmlTextReaderLocator"),
"xmlTextReaderPtr": ("._o", "xmlTextReader(_obj=%s)", "xmlTextReader"),
}
@ -690,6 +692,8 @@ def nameFixup(name, classe, type, file):
func = "regexp" + name[9:]
elif name[0:6] == "xmlReg" and file == "xmlregexp":
func = "regexp" + name[6:]
elif name[0:20] == "xmlTextReaderLocator" and file == "xmlreader":
func = name[20:]
elif name[0:13] == "xmlTextReader" and file == "xmlreader":
func = name[13:]
elif name[0:11] == "xmlACatalog":

View File

@ -1177,32 +1177,6 @@ libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
return (Py_None);
}
PyObject *
libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
xmlParserCtxtPtr ctxt;
PyObject *pyobj_ctxt;
xmlParserCtxtPyCtxtPtr pyCtxt;
if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeParserCtxt", &pyobj_ctxt))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
if (ctxt != NULL) {
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
if (pyCtxt) {
Py_XDECREF(pyCtxt->errorFunc);
Py_XDECREF(pyCtxt->errorFuncArg);
Py_XDECREF(pyCtxt->warningFunc);
Py_XDECREF(pyCtxt->warningFuncArg);
xmlFree(pyCtxt);
}
xmlFreeParserCtxt(ctxt);
}
Py_INCREF(Py_None);
return(Py_None);
}
/************************************************************************
* *
* Error message callback *
@ -1332,44 +1306,87 @@ libxml_xmlRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,
* *
************************************************************************/
static void
libxml_xmlParserCtxtErrorFuncHandler(void *ctxt, const char *msg, ...)
typedef struct
{
PyObject *f;
PyObject *arg;
} xmlParserCtxtPyCtxt;
typedef xmlParserCtxtPyCtxt *xmlParserCtxtPyCtxtPtr;
static void
libxml_xmlParserCtxtGenericErrorFuncHandler(void *ctx, int severity, char *str)
{
char *str;
va_list ap;
PyObject *list;
PyObject *message;
PyObject *result;
xmlParserCtxtPtr ctxt;
xmlParserCtxtPyCtxtPtr pyCtxt;
#ifdef DEBUG_ERROR
printf("libxml_xmlParserCtxtErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
printf("libxml_xmlParserCtxtGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
#endif
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
ctxt = (xmlParserCtxtPtr)ctx;
pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
if (pyCtxt->errorFunc == NULL) {
va_start(ap, msg);
vfprintf(stdout, msg, ap);
va_end(ap);
} else {
va_start(ap, msg);
str = libxml_buildMessage(msg,ap);
va_end(ap);
list = PyTuple_New(2);
PyTuple_SetItem(list, 0, pyCtxt->errorFuncArg);
Py_XINCREF(pyCtxt->errorFuncArg);
message = libxml_charPtrWrap(str);
PyTuple_SetItem(list, 1, message);
result = PyEval_CallObject(pyCtxt->errorFunc, list);
Py_XDECREF(list);
Py_XDECREF(result);
list = PyTuple_New(4);
PyTuple_SetItem(list, 0, pyCtxt->arg);
Py_XINCREF(pyCtxt->arg);
PyTuple_SetItem(list, 1, libxml_charPtrWrap(str));
PyTuple_SetItem(list, 2, libxml_intWrap(severity));
PyTuple_SetItem(list, 3, Py_None);
Py_INCREF(Py_None);
result = PyEval_CallObject(pyCtxt->f, list);
if (result == NULL)
{
/* TODO: manage for the exception to be propagated... */
PyErr_Print();
}
Py_XDECREF(list);
Py_XDECREF(result);
}
static void
libxml_xmlParserCtxtErrorFuncHandler(void *ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_ERROR,libxml_buildMessage(msg,ap));
va_end(ap);
}
static void
libxml_xmlParserCtxtWarningFuncHandler(void *ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_WARNING,libxml_buildMessage(msg,ap));
va_end(ap);
}
static void
libxml_xmlParserCtxtValidityErrorFuncHandler(void *ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap));
va_end(ap);
}
static void
libxml_xmlParserCtxtValidityWarningFuncHandler(void *ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap));
va_end(ap);
}
PyObject *
libxml_xmlSetParserCtxtErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
libxml_xmlParserCtxtSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
{
PyObject *py_retval;
xmlParserCtxtPtr ctxt;
@ -1378,7 +1395,7 @@ libxml_xmlSetParserCtxtErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *a
PyObject *pyobj_f;
PyObject *pyobj_arg;
if (!PyArg_ParseTuple(args, (char *)"OOO:xmlSetParserCtxtErrorHandler",
if (!PyArg_ParseTuple(args, (char *)"OOO:xmlParserCtxtSetErrorHandler",
&pyobj_ctxt, &pyobj_f, &pyobj_arg))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
@ -1392,99 +1409,88 @@ libxml_xmlSetParserCtxtErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *a
ctxt->_private = pyCtxt;
}
else {
pyCtxt = ctxt->_private;
pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
}
/* TODO: check f is a function ! */
Py_XDECREF(pyCtxt->errorFunc);
Py_XDECREF(pyCtxt->f);
Py_XINCREF(pyobj_f);
pyCtxt->errorFunc = pyobj_f;
Py_XDECREF(pyCtxt->errorFuncArg);
pyCtxt->f = pyobj_f;
Py_XDECREF(pyCtxt->arg);
Py_XINCREF(pyobj_arg);
pyCtxt->errorFuncArg = pyobj_arg;
pyCtxt->arg = pyobj_arg;
ctxt->sax->error = libxml_xmlParserCtxtErrorFuncHandler;
ctxt->vctxt.error = libxml_xmlParserCtxtErrorFuncHandler;
if (pyobj_f != Py_None) {
ctxt->sax->error = libxml_xmlParserCtxtErrorFuncHandler;
ctxt->sax->warning = libxml_xmlParserCtxtWarningFuncHandler;
ctxt->vctxt.error = libxml_xmlParserCtxtValidityErrorFuncHandler;
ctxt->vctxt.warning = libxml_xmlParserCtxtValidityWarningFuncHandler;
}
else {
ctxt->sax->error = xmlParserError;
ctxt->vctxt.error = xmlParserValidityError;
ctxt->sax->warning = xmlParserWarning;
ctxt->vctxt.warning = xmlParserValidityWarning;
}
py_retval = libxml_intWrap(1);
return(py_retval);
}
static void
libxml_xmlParserCtxtWarningFuncHandler(void *ctxt, const char *msg, ...)
{
char *str;
va_list ap;
PyObject *list;
PyObject *message;
PyObject *result;
xmlParserCtxtPyCtxtPtr pyCtxt;
#ifdef DEBUG_ERROR
printf("libxml_xmlParserCtxtWarningFuncHandler(%p, %s, ...) called\n", ctx, msg);
#endif
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
if (pyCtxt->warningFunc == NULL) {
va_start(ap, msg);
vfprintf(stdout, msg, ap);
va_end(ap);
} else {
va_start(ap, msg);
str = libxml_buildMessage(msg,ap);
va_end(ap);
list = PyTuple_New(2);
PyTuple_SetItem(list, 0, pyCtxt->warningFuncArg);
Py_XINCREF(pyCtxt->warningFuncArg);
message = libxml_charPtrWrap(str);
PyTuple_SetItem(list, 1, message);
result = PyEval_CallObject(pyCtxt->warningFunc, list);
Py_XDECREF(list);
Py_XDECREF(result);
}
}
PyObject *
libxml_xmlSetParserCtxtWarningHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
libxml_xmlParserCtxtGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
{
PyObject *py_retval;
xmlParserCtxtPtr ctxt;
xmlParserCtxtPyCtxtPtr pyCtxt;
PyObject *pyobj_ctxt;
PyObject *pyobj_f;
PyObject *pyobj_arg;
if (!PyArg_ParseTuple(args, (char *)"OOO:xmlSetParserCtxtWarningHandler", &pyobj_ctxt, &pyobj_f, &pyobj_arg))
if (!PyArg_ParseTuple(args, (char *)"O:xmlParserCtxtGetErrorHandler",
&pyobj_ctxt))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
if (ctxt->_private == NULL) {
pyCtxt = xmlMalloc(sizeof(xmlParserCtxtPyCtxt));
if (pyCtxt == NULL) {
py_retval = libxml_intWrap(-1);
return(py_retval);
}
memset(pyCtxt,0,sizeof(xmlParserCtxtPyCtxt));
ctxt->_private = pyCtxt;
py_retval = PyTuple_New(2);
if (ctxt->_private != NULL) {
pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
PyTuple_SetItem(py_retval, 0, pyCtxt->f);
Py_XINCREF(pyCtxt->f);
PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
Py_XINCREF(pyCtxt->arg);
}
else {
pyCtxt = ctxt->_private;
/* no python error handler registered */
PyTuple_SetItem(py_retval, 0, Py_None);
Py_XINCREF(Py_None);
PyTuple_SetItem(py_retval, 1, Py_None);
Py_XINCREF(Py_None);
}
/* TODO: check f is a function ! */
Py_XDECREF(pyCtxt->warningFunc);
Py_XINCREF(pyobj_f);
pyCtxt->warningFunc = pyobj_f;
Py_XDECREF(pyCtxt->warningFuncArg);
Py_XINCREF(pyobj_arg);
pyCtxt->warningFuncArg = pyobj_arg;
ctxt->sax->warning = libxml_xmlParserCtxtWarningFuncHandler;
ctxt->vctxt.warning = libxml_xmlParserCtxtWarningFuncHandler;
py_retval = libxml_intWrap(1);
return(py_retval);
}
PyObject *
libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
xmlParserCtxtPtr ctxt;
PyObject *pyobj_ctxt;
xmlParserCtxtPyCtxtPtr pyCtxt;
if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeParserCtxt", &pyobj_ctxt))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
if (ctxt != NULL) {
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
if (pyCtxt) {
Py_XDECREF(pyCtxt->f);
Py_XDECREF(pyCtxt->arg);
xmlFree(pyCtxt);
}
xmlFreeParserCtxt(ctxt);
}
Py_INCREF(Py_None);
return(Py_None);
}
/************************************************************************
* *
* Per xmlTextReader error handler *
@ -1501,27 +1507,23 @@ typedef xmlTextReaderPyCtxt *xmlTextReaderPyCtxtPtr;
static void
libxml_xmlTextReaderErrorCallback(void *arg,
const char *msg,
int line,
int col,
const char *URI,
int severity)
int severity,
xmlTextReaderLocatorPtr locator)
{
xmlTextReaderPyCtxt *pyCtxt = (xmlTextReaderPyCtxt *)arg;
PyObject *list;
PyObject *result;
list = PyTuple_New(6);
list = PyTuple_New(4);
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));
PyTuple_SetItem(list, 2, libxml_intWrap(severity));
PyTuple_SetItem(list, 3, libxml_xmlTextReaderLocatorPtrWrap(locator));
result = PyEval_CallObject(pyCtxt->f, list);
if (result == NULL)
{
/* TODO: manage for the exception to be go up... */
/* TODO: manage for the exception to be propagated... */
PyErr_Print();
}
Py_XDECREF(list);
@ -2558,8 +2560,8 @@ static PyMethodDef libxmlMethods[] = {
{(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
{(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
{(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlSetParserCtxtErrorHandler", libxml_xmlSetParserCtxtErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlSetParserCtxtWarningHandler", libxml_xmlSetParserCtxtWarningHandler, METH_VARARGS, NULL },
{(char *)"xmlParserCtxtSetErrorHandler", libxml_xmlParserCtxtSetErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlParserCtxtGetErrorHandler", libxml_xmlParserCtxtGetErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
{(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },

View File

@ -462,12 +462,12 @@ PARSER_VALIDATE=3
PARSER_SUBST_ENTITIES=4
#
# For the xmlTextReader error severities
# For the error callback severities
#
XMLREADER_SEVERITY_VALIDITY_WARNING=1
XMLREADER_SEVERITY_VALIDITY_ERROR=2
XMLREADER_SEVERITY_WARNING=3
XMLREADER_SEVERITY_ERROR=4
PARSER_SEVERITY_VALIDITY_WARNING=1
PARSER_SEVERITY_VALIDITY_ERROR=2
PARSER_SEVERITY_WARNING=3
PARSER_SEVERITY_ERROR=4
#
# register the libxml2 error handler
@ -499,11 +499,21 @@ class parserCtxtCore:
libxml2mod.xmlFreeParserCtxt(self._o)
self._o = None
def registerErrorHandler(self,f,arg):
libxml2mod.xmlSetParserCtxtErrorHandler(self._o,f,arg)
def setErrorHandler(self,f,arg):
"""Register an error handler that will be called back as
f(arg,msg,severity,reserved).
@reserved is currently always None."""
libxml2mod.xmlParserCtxtSetErrorHandler(self._o,f,arg)
def registerWarningHandler(self,f,arg):
libxml2mod.xmlSetParserCtxtWarningHandler(self._o,f,arg)
def getErrorHandler(self):
"""Return (f,arg) as previously registered with setErrorHandler
or (None,None)."""
return libxml2mod.xmlParserCtxtGetErrorHandler(self._o)
def _xmlTextReaderErrorFunc((f,arg),msg,severity,locator):
"""Intermediate callback to wrap the locator"""
return f(arg,msg,severity,xmlTextReaderLocator(locator))
class xmlTextReaderCore:
@ -517,15 +527,25 @@ class xmlTextReaderCore:
libxml2mod.xmlFreeTextReader(self._o)
self._o = None
def setErrorHandler(self,f,arg):
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)
f(arg,msg,severity,locator)."""
if f is None:
libxml2mod.xmlTextReaderSetErrorHandler(\
self._o,None,None)
else:
libxml2mod.xmlTextReaderSetErrorHandler(\
self._o,_xmlTextReaderErrorFunc,(f,arg))
def getErrorHandler(self):
def GetErrorHandler(self):
"""Return (f,arg) as previously registered with setErrorHandler
or (None,None)."""
return libxml2mod.xmlTextReaderGetErrorHandler(self._o)
f,arg = libxml2mod.xmlTextReaderGetErrorHandler(self._o)
if f is None:
return None,None
else:
# assert f is _xmlTextReaderErrorFunc
return arg
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
#

View File

@ -93,6 +93,14 @@ typedef struct {
xmlTextReaderPtr obj;
} PyxmlTextReader_Object;
#define PyxmlTextReaderLocator_Get(v) (((v) == Py_None) ? NULL : \
(((PyxmlTextReaderLocator_Object *)(v))->obj))
typedef struct {
PyObject_HEAD
xmlTextReaderLocatorPtr obj;
} PyxmlTextReaderLocator_Object;
#define PyURI_Get(v) (((v) == Py_None) ? NULL : \
(((PyURI_Object *)(v))->obj))
@ -147,19 +155,6 @@ PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer);
PyObject * libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer);
PyObject * libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp);
PyObject * libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader);
PyObject * libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator);
xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
/*
* Data structure that makes the link from the parser context
* to the python wrapper.
*/
typedef struct
{
PyObject *errorFunc;
PyObject *errorFuncArg;
PyObject *warningFunc;
PyObject *warningFuncArg;
} xmlParserCtxtPyCtxt;
typedef xmlParserCtxtPyCtxt *xmlParserCtxtPyCtxtPtr;

View File

@ -9,20 +9,22 @@ import libxml2
# Memory debug specific
libxml2.debugMemory(1)
expect="""--> Opening and ending tag mismatch: x and y
expect="""--> (3) xmlns: URI foo is not absolute
--> (4) Opening and ending tag mismatch: x and y
"""
err=""
def callback(ctx, str):
global err
def callback(arg,msg,severity,reserved):
global err
err = err + "%s (%d) %s" % (arg,severity,msg)
err = err + "%s %s" % (ctx, str)
s = """<x></y>"""
s = """<x xmlns="foo"></y>"""
parserCtxt = libxml2.createPushParser(None,"",0,"test.xml")
parserCtxt.registerErrorHandler(callback, "-->")
parserCtxt.registerWarningHandler(callback, "-->")
parserCtxt.setErrorHandler(callback, "-->")
if parserCtxt.getErrorHandler() != (callback,"-->"):
print "getErrorHandler failed"
sys.exit(1)
parserCtxt.parseChunk(s,len(s),1)
doc = parserCtxt.doc()
doc.freeDoc()
@ -37,8 +39,7 @@ if err != expect:
i = 10000
while i > 0:
parserCtxt = libxml2.createPushParser(None,"",0,"test.xml")
parserCtxt.registerErrorHandler(callback, "-->")
parserCtxt.registerWarningHandler(callback, "-->")
parserCtxt.setErrorHandler(callback, "-->")
parserCtxt.parseChunk(s,len(s),1)
doc = parserCtxt.doc()
doc.freeDoc()

View File

@ -13,14 +13,14 @@ expect="""--> (3) test1:1:xmlns: URI foo is not absolute
--> (4) test1:1:Opening and ending tag mismatch: c and a
"""
err=""
def myErrorHandler(arg,msg,line,col,URI,severity):
def myErrorHandler(arg,msg,severity,locator):
global err
err = err + "%s (%d) %s:%d:%s" % (arg,severity,URI,line,msg)
err = err + "%s (%d) %s:%d:%s" % (arg,severity,locator.BaseURI(),locator.LineNumber(),msg)
f = StringIO.StringIO("""<a xmlns="foo"><b b1="b1"/><c>content of c</a>""")
input = libxml2.inputBuffer(f)
reader = input.newTextReader("test1")
reader.setErrorHandler(myErrorHandler,"-->")
reader.SetErrorHandler(myErrorHandler,"-->")
while reader.Read() == 1:
pass
@ -30,9 +30,9 @@ if err != expect:
print "expected %s" %(expect)
sys.exit(1)
reader.setErrorHandler(None,None)
if reader.getErrorHandler() != (None,None):
print "getErrorHandler failed"
reader.SetErrorHandler(None,None)
if reader.GetErrorHandler() != (None,None):
print "GetErrorHandler failed"
sys.exit(1)
#

View File

@ -566,3 +566,22 @@ libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader)
(char *) "xmlTextReaderPtr", NULL);
return (ret);
}
PyObject *
libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator)
{
PyObject *ret;
#ifdef DEBUG
printf("libxml_xmlTextReaderLocatorPtrWrap: locator = %p\n", locator);
#endif
if (locator == NULL) {
Py_INCREF(Py_None);
return (Py_None);
}
ret =
PyCObject_FromVoidPtrAndDesc((void *) locator,
(char *) "xmlTextReaderLocatorPtr", NULL);
return (ret);
}