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
diff --git a/python/generator.py b/python/generator.py
index 6b66c92..df89c4e 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -282,6 +282,9 @@
'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 @@
'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 @@
"relaxNgSchema": "xmlRelaxNGFree",
"relaxNgParserCtxt": "xmlRelaxNGFreeParserCtxt",
"relaxNgValidCtxt": "xmlRelaxNGFreeValidCtxt",
+ "Schema": "xmlSchemaFree",
+ "SchemaParserCtxt": "xmlSchemaFreeParserCtxt",
+ "SchemaValidCtxt": "xmlSchemaFreeValidCtxt",
}
functions_noexcept = {
@@ -710,6 +719,7 @@
reference_keepers = {
"xmlTextReader": [('inputBuffer', 'input')],
"relaxNgValidCtxt": [('relaxNgSchema', 'schema')],
+ "SchemaValidCtxt": [('Schema', 'schema')],
}
function_classes = {}
diff --git a/python/libxml.c b/python/libxml.c
index 9dda18c..1c65e72 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -2948,6 +2948,171 @@
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
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index 2f082ea..9e2496e 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -219,6 +219,10 @@
# functions from module xmlregexp
regexpCompile()
+# functions from module xmlschemas
+schemaNewMemParserCtxt()
+schemaNewParserCtxt()
+
# functions from module xmlschemastypes
schemaCleanupTypes()
schemaCollapseString()
@@ -630,6 +634,10 @@
NewWalker()
readerWalker()
+ # functions from module xmlschemas
+ schemaNewDocParserCtxt()
+ schemaValidateDoc()
+
# functions from module xpath
xpathNewContext()
xpathOrderDocElems()
@@ -781,6 +789,11 @@
# functions from module xmlreader
RelaxNGSetSchema()
+Class Schema()
+
+ # functions from module xmlschemas
+ schemaDump()
+ schemaNewValidCtxt()
Class Error()
# accessors
code()
@@ -1032,6 +1045,14 @@
# 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
diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h
index 09fc77f..ad62be2 100644
--- a/python/libxml_wrap.h
+++ b/python/libxml_wrap.h
@@ -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 @@
#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 @@
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);
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
index 2788c0c..722e0ec 100644
--- a/python/tests/Makefile.am
+++ b/python/tests/Makefile.am
@@ -32,6 +32,7 @@
ctxterror.py\
readererr.py\
relaxng.py \
+ schema.py \
thread2.py \
sync.py \
tstLastError.py \
diff --git a/python/tests/schema.py b/python/tests/schema.py
new file mode 100755
index 0000000..bfa8423
--- /dev/null
+++ b/python/tests/schema.py
@@ -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()
+
diff --git a/python/types.c b/python/types.c
index 42279d0..fa91a65 100644
--- a/python/types.c
+++ b/python/types.c
@@ -640,6 +640,63 @@
(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 *