mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03:00
Applied patch from Torkel Lyng to add Schemas support to the Python
* xmlschemas.c include/libxml/xmlschemas.h python/generator.py python/libxml.c python/libxml_wrap.h python/types.c python/tests/schema.py python/tests/Makefile.am: Applied patch from Torkel Lyng to add Schemas support to the Python bindings and extend the schemas error API, registered a new test. * doc/* elfgcchack.h: rebuilt to regenerate the bindings Daniel
This commit is contained in:
@ -282,6 +282,9 @@ py_types = {
|
||||
'xmlRelaxNGPtr': ('O', "relaxNgSchema", "xmlRelaxNGPtr", "xmlRelaxNGPtr"),
|
||||
'xmlRelaxNGParserCtxtPtr': ('O', "relaxNgParserCtxt", "xmlRelaxNGParserCtxtPtr", "xmlRelaxNGParserCtxtPtr"),
|
||||
'xmlRelaxNGValidCtxtPtr': ('O', "relaxNgValidCtxt", "xmlRelaxNGValidCtxtPtr", "xmlRelaxNGValidCtxtPtr"),
|
||||
'xmlSchemaPtr': ('O', "Schema", "xmlSchemaPtr", "xmlSchemaPtr"),
|
||||
'xmlSchemaParserCtxtPtr': ('O', "SchemaParserCtxt", "xmlSchemaParserCtxtPtr", "xmlSchemaParserCtxtPtr"),
|
||||
'xmlSchemaValidCtxtPtr': ('O', "SchemaValidCtxt", "xmlSchemaValidCtxtPtr", "xmlSchemaValidCtxtPtr"),
|
||||
}
|
||||
|
||||
py_return_types = {
|
||||
@ -666,6 +669,9 @@ classes_type = {
|
||||
'xmlRelaxNGPtr': ('._o', "relaxNgSchema(_obj=%s)", "relaxNgSchema"),
|
||||
'xmlRelaxNGParserCtxtPtr': ('._o', "relaxNgParserCtxt(_obj=%s)", "relaxNgParserCtxt"),
|
||||
'xmlRelaxNGValidCtxtPtr': ('._o', "relaxNgValidCtxt(_obj=%s)", "relaxNgValidCtxt"),
|
||||
'xmlSchemaPtr': ("._o", "Schema(_obj=%s)", "Schema"),
|
||||
'xmlSchemaParserCtxtPtr': ("._o", "SchemaParserCtxt(_obj=%s)", "SchemaParserCtxt"),
|
||||
'xmlSchemaValidCtxtPtr': ("._o", "SchemaValidCtxt(_obj=%s)", "SchemaValidCtxt"),
|
||||
}
|
||||
|
||||
converter_type = {
|
||||
@ -699,6 +705,9 @@ classes_destructors = {
|
||||
"relaxNgSchema": "xmlRelaxNGFree",
|
||||
"relaxNgParserCtxt": "xmlRelaxNGFreeParserCtxt",
|
||||
"relaxNgValidCtxt": "xmlRelaxNGFreeValidCtxt",
|
||||
"Schema": "xmlSchemaFree",
|
||||
"SchemaParserCtxt": "xmlSchemaFreeParserCtxt",
|
||||
"SchemaValidCtxt": "xmlSchemaFreeValidCtxt",
|
||||
}
|
||||
|
||||
functions_noexcept = {
|
||||
@ -710,6 +719,7 @@ functions_noexcept = {
|
||||
reference_keepers = {
|
||||
"xmlTextReader": [('inputBuffer', 'input')],
|
||||
"relaxNgValidCtxt": [('relaxNgSchema', 'schema')],
|
||||
"SchemaValidCtxt": [('Schema', 'schema')],
|
||||
}
|
||||
|
||||
function_classes = {}
|
||||
|
165
python/libxml.c
165
python/libxml.c
@ -2948,6 +2948,171 @@ libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
|
||||
return(Py_None);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PyObject *warn;
|
||||
PyObject *error;
|
||||
PyObject *arg;
|
||||
} xmlSchemaValidCtxtPyCtxt;
|
||||
typedef xmlSchemaValidCtxtPyCtxt *xmlSchemaValidCtxtPyCtxtPtr;
|
||||
|
||||
static void
|
||||
libxml_xmlSchemaValidityGenericErrorFuncHandler(void *ctx, char *str)
|
||||
{
|
||||
PyObject *list;
|
||||
PyObject *result;
|
||||
xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
|
||||
|
||||
#ifdef DEBUG_ERROR
|
||||
printf("libxml_xmlSchemaValiditiyGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
|
||||
#endif
|
||||
|
||||
pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) 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_xmlSchemaValidityGenericWarningFuncHandler(void *ctx, char *str)
|
||||
{
|
||||
PyObject *list;
|
||||
PyObject *result;
|
||||
xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
|
||||
|
||||
#ifdef DEBUG_ERROR
|
||||
printf("libxml_xmlSchemaValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
|
||||
#endif
|
||||
|
||||
pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) 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_xmlSchemaValidityErrorFunc(void *ctx, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
libxml_xmlSchemaValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void
|
||||
libxml_xmlSchemaValidityWarningFunc(void *ctx, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, msg);
|
||||
libxml_xmlSchemaValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
libxml_xmlSchemaSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
|
||||
{
|
||||
PyObject *py_retval;
|
||||
PyObject *pyobj_error;
|
||||
PyObject *pyobj_warn;
|
||||
PyObject *pyobj_ctx;
|
||||
PyObject *pyobj_arg = Py_None;
|
||||
xmlSchemaValidCtxtPtr ctxt;
|
||||
xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
|
||||
|
||||
if (!PyArg_ParseTuple
|
||||
(args, (char *) "OOO|O:xmlSchemaSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
|
||||
return (NULL);
|
||||
|
||||
#ifdef DEBUG_ERROR
|
||||
printf("libxml_xmlSchemaSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
|
||||
#endif
|
||||
|
||||
ctxt = PySchemaValidCtxt_Get(pyobj_ctx);
|
||||
if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
|
||||
{
|
||||
py_retval = libxml_intWrap(-1);
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
if (pyCtxt == NULL)
|
||||
{
|
||||
/* first time to set the error handlers */
|
||||
pyCtxt = xmlMalloc(sizeof(xmlSchemaValidCtxtPyCtxt));
|
||||
if (pyCtxt == NULL) {
|
||||
py_retval = libxml_intWrap(-1);
|
||||
return(py_retval);
|
||||
}
|
||||
memset(pyCtxt, 0, sizeof(xmlSchemaValidCtxtPyCtxt));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
xmlSchemaSetValidErrors(ctxt, &libxml_xmlSchemaValidityErrorFunc, &libxml_xmlSchemaValidityWarningFunc, pyCtxt);
|
||||
|
||||
py_retval = libxml_intWrap(1);
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
libxml_xmlSchemaFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
|
||||
{
|
||||
xmlSchemaValidCtxtPtr ctxt;
|
||||
xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
|
||||
PyObject *pyobj_ctxt;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"O:xmlSchemaFreeValidCtxt", &pyobj_ctxt))
|
||||
return(NULL);
|
||||
ctxt = (xmlSchemaValidCtxtPtr) PySchemaValidCtxt_Get(pyobj_ctxt);
|
||||
|
||||
if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
|
||||
{
|
||||
if (pyCtxt != NULL)
|
||||
{
|
||||
Py_XDECREF(pyCtxt->error);
|
||||
Py_XDECREF(pyCtxt->warn);
|
||||
Py_XDECREF(pyCtxt->arg);
|
||||
xmlFree(pyCtxt);
|
||||
}
|
||||
}
|
||||
|
||||
xmlSchemaFreeValidCtxt(ctxt);
|
||||
Py_INCREF(Py_None);
|
||||
return(Py_None);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LIBXML_C14N_ENABLED
|
||||
|
@ -219,6 +219,10 @@ readerForMemory()
|
||||
# functions from module xmlregexp
|
||||
regexpCompile()
|
||||
|
||||
# functions from module xmlschemas
|
||||
schemaNewMemParserCtxt()
|
||||
schemaNewParserCtxt()
|
||||
|
||||
# functions from module xmlschemastypes
|
||||
schemaCleanupTypes()
|
||||
schemaCollapseString()
|
||||
@ -630,6 +634,10 @@ Class xmlDoc(xmlNode)
|
||||
NewWalker()
|
||||
readerWalker()
|
||||
|
||||
# functions from module xmlschemas
|
||||
schemaNewDocParserCtxt()
|
||||
schemaValidateDoc()
|
||||
|
||||
# functions from module xpath
|
||||
xpathNewContext()
|
||||
xpathOrderDocElems()
|
||||
@ -781,6 +789,11 @@ Class relaxNgSchema()
|
||||
|
||||
# functions from module xmlreader
|
||||
RelaxNGSetSchema()
|
||||
Class Schema()
|
||||
|
||||
# functions from module xmlschemas
|
||||
schemaDump()
|
||||
schemaNewValidCtxt()
|
||||
Class Error()
|
||||
# accessors
|
||||
code()
|
||||
@ -1032,6 +1045,14 @@ Class outputBuffer(ioWriteWrapper)
|
||||
# functions from module xmlIO
|
||||
write()
|
||||
writeString()
|
||||
Class SchemaParserCtxt()
|
||||
|
||||
# functions from module xmlschemas
|
||||
schemaParse()
|
||||
Class SchemaValidCtxt()
|
||||
|
||||
# functions from module xmlschemas
|
||||
schemaValidateDoc()
|
||||
Class xmlTextReaderLocator()
|
||||
|
||||
# functions from module xmlreader
|
||||
|
@ -18,7 +18,10 @@
|
||||
#include <libxml/xmlregexp.h>
|
||||
#include <libxml/xmlautomata.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||
#include <libxml/relaxng.h>
|
||||
#include <libxml/xmlschemas.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ATTRIBUTE_UNUSED:
|
||||
@ -165,6 +168,30 @@ typedef struct {
|
||||
#define PyrelaxNgValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyrelaxNgValidCtxt_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlSchemaPtr obj;
|
||||
} PySchema_Object;
|
||||
|
||||
#define PySchema_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PySchema_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlSchemaParserCtxtPtr obj;
|
||||
} PySchemaParserCtxt_Object;
|
||||
|
||||
#define PySchemaParserCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PySchemaParserCtxt_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlSchemaValidCtxtPtr obj;
|
||||
} PySchemaValidCtxt_Object;
|
||||
|
||||
#define PySchemaValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PySchemaValidCtxt_Object *)(v))->obj))
|
||||
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
||||
|
||||
PyObject * libxml_intWrap(int val);
|
||||
@ -201,5 +228,8 @@ xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
|
||||
PyObject * libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt);
|
||||
PyObject * libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt);
|
||||
PyObject * libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid);
|
||||
PyObject * libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt);
|
||||
PyObject * libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt);
|
||||
PyObject * libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid);
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
||||
PyObject * libxml_xmlErrorPtrWrap(xmlErrorPtr error);
|
||||
|
@ -32,6 +32,7 @@ PYTESTS= \
|
||||
ctxterror.py\
|
||||
readererr.py\
|
||||
relaxng.py \
|
||||
schema.py \
|
||||
thread2.py \
|
||||
sync.py \
|
||||
tstLastError.py \
|
||||
|
52
python/tests/schema.py
Executable file
52
python/tests/schema.py
Executable file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/python -u
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
schema="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<schema xmlns = "http://www.w3.org/2001/XMLSchema">
|
||||
<element name = "Customer">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "FirstName" type = "string" />
|
||||
<element name = "MiddleInitial" type = "string" />
|
||||
<element name = "LastName" type = "string" />
|
||||
</sequence>
|
||||
<attribute name = "customerID" type = "integer" />
|
||||
</complexType>
|
||||
</element>
|
||||
</schema>"""
|
||||
|
||||
instance="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<Customer customerID = "24332">
|
||||
<FirstName>Raymond</FirstName>
|
||||
<MiddleInitial>G</MiddleInitial>
|
||||
<LastName>Bayliss</LastName>
|
||||
</Customer>
|
||||
"""
|
||||
|
||||
ctxt_parser = libxml2.schemaNewMemParserCtxt(schema, len(schema))
|
||||
ctxt_schema = ctxt_parser.schemaParse()
|
||||
ctxt_valid = ctxt_schema.schemaNewValidCtxt()
|
||||
doc = libxml2.parseDoc(instance)
|
||||
ret = doc.schemaValidateDoc(ctxt_valid)
|
||||
if ret != 0:
|
||||
print "error doing schema validation"
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
del ctxt_parser
|
||||
del ctxt_schema
|
||||
del ctxt_valid
|
||||
libxml2.schemaCleanupTypes()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print "OK"
|
||||
else:
|
||||
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
|
||||
libxml2.dumpMemory()
|
||||
|
@ -640,6 +640,63 @@ libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid)
|
||||
(char *) "xmlRelaxNGValidCtxtPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("libxml_xmlSchemaPtrWrap: ctxt = %p\n", ctxt);
|
||||
#endif
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCObject_FromVoidPtrAndDesc((void *) ctxt,
|
||||
(char *) "xmlSchemaPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("libxml_xmlSchemaParserCtxtPtrWrap: ctxt = %p\n", ctxt);
|
||||
#endif
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCObject_FromVoidPtrAndDesc((void *) ctxt,
|
||||
(char *) "xmlSchemaParserCtxtPtr", NULL);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("libxml_xmlSchemaValidCtxtPtrWrap: valid = %p\n", valid);
|
||||
#endif
|
||||
if (valid == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
|
||||
ret =
|
||||
PyCObject_FromVoidPtrAndDesc((void *) valid,
|
||||
(char *) "xmlSchemaValidCtxtPtr", NULL);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
||||
|
||||
PyObject *
|
||||
|
Reference in New Issue
Block a user