mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-29 11:41:22 +03:00
updated the python bindings, added code for easier File I/O, and the
* python/generator.py python/libxml.c python/libxml.py python/libxml2-python-api.xml python/libxml2class.txt python/libxml_wrap.h python/types.c: updated the python bindings, added code for easier File I/O, and the ability to define a resolver from Python fixing bug #91635 * python/tests/Makefile.am python/tests/inbuf.py python/tests/outbuf.py python/tests/pushSAXhtml.py python/tests/resolver.py python/tests/serialize.py: updated and augmented the set of Python tests. Daniel
This commit is contained in:
@ -268,6 +268,8 @@ py_types = {
|
||||
'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"),
|
||||
'FILE *': ('O', "File", "FILEPtr", "FILE *"),
|
||||
'xmlURIPtr': ('O', "URI", "xmlURIPtr", "xmlURIPtr"),
|
||||
'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutputBufferPtr"),
|
||||
'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"),
|
||||
}
|
||||
|
||||
py_return_types = {
|
||||
@ -583,6 +585,8 @@ classes_type = {
|
||||
"htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
|
||||
"xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"),
|
||||
"xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"),
|
||||
"xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"),
|
||||
"xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"),
|
||||
}
|
||||
|
||||
converter_type = {
|
||||
@ -600,11 +604,15 @@ classes_ancestor = {
|
||||
"xmlEntity" : "xmlNode",
|
||||
"xmlElement" : "xmlNode",
|
||||
"xmlAttribute" : "xmlNode",
|
||||
"outputBuffer": "ioWriteWrapper",
|
||||
"inputBuffer": "ioReadWrapper",
|
||||
}
|
||||
classes_destructors = {
|
||||
"parserCtxt": "xmlFreeParserCtxt",
|
||||
"catalog": "xmlFreeCatalog",
|
||||
"URI": "xmlFreeURI",
|
||||
# "outputBuffer": "xmlOutputBufferClose",
|
||||
"inputBuffer": "xmlFreeParserInputBuffer",
|
||||
}
|
||||
|
||||
functions_noexcept = {
|
||||
@ -647,6 +655,12 @@ def nameFixup(name, classe, type, file):
|
||||
elif name[0:11] == "xmlXPathSet" and file == "python_accessor":
|
||||
func = name[8:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
elif name[0:15] == "xmlOutputBuffer" and file != "python":
|
||||
func = name[15:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
elif name[0:20] == "xmlParserInputBuffer" and file != "python":
|
||||
func = name[20:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
elif name[0:11] == "xmlACatalog":
|
||||
func = name[11:]
|
||||
func = string.lower(func[0:1]) + func[1:]
|
||||
|
380
python/libxml.c
380
python/libxml.c
@ -12,6 +12,7 @@
|
||||
* daniel@veillard.com
|
||||
*/
|
||||
#include <Python.h>
|
||||
#include <fileobject.h>
|
||||
#include "config.h"
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/parser.h>
|
||||
@ -20,21 +21,30 @@
|
||||
#include <libxml/xmlerror.h>
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/xmlIO.h>
|
||||
#include "libxml_wrap.h"
|
||||
#include "libxml2-py.h"
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
/* #define DEBUG_SAX */
|
||||
|
||||
/* #define DEBUG_XPATH */
|
||||
|
||||
/* #define DEBUG_ERROR */
|
||||
|
||||
/* #define DEBUG_MEMORY */
|
||||
/* #define DEBUG_FILES */
|
||||
/* #define DEBUG_LOADER */
|
||||
|
||||
void initlibxml2mod(void);
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
*
|
||||
* macro to flag unimplemented blocks
|
||||
*/
|
||||
#define TODO \
|
||||
xmlGenericError(xmlGenericErrorContext, \
|
||||
"Unimplemented block at %s:%d\n", \
|
||||
__FILE__, __LINE__);
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Memory debug interface *
|
||||
@ -123,6 +133,363 @@ libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
|
||||
return (Py_None);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Handling Python FILE I/O at the C level *
|
||||
* The raw I/O attack diectly the File objects, while the *
|
||||
* other routines address the ioWrapper instance instead *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* xmlPythonFileCloseUnref:
|
||||
* @context: the I/O context
|
||||
*
|
||||
* Close an I/O channel
|
||||
*/
|
||||
static int
|
||||
xmlPythonFileCloseRaw (void * context) {
|
||||
PyObject *file, *ret;
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
printf("xmlPythonFileCloseUnref\n");
|
||||
#endif
|
||||
file = (PyObject *) context;
|
||||
if (file == NULL) return(-1);
|
||||
ret = PyEval_CallMethod(file, "close", "()");
|
||||
if (ret != NULL) {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
Py_DECREF(file);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlPythonFileReadRaw:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to drop data
|
||||
* @len: number of bytes to write
|
||||
*
|
||||
* Read @len bytes to @buffer from the Python file in the I/O channel
|
||||
*
|
||||
* Returns the number of bytes read
|
||||
*/
|
||||
static int
|
||||
xmlPythonFileReadRaw (void * context, char * buffer, int len) {
|
||||
PyObject *file;
|
||||
PyObject *ret;
|
||||
int lenread = -1;
|
||||
char *data;
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
printf("xmlPythonFileReadRaw: %d\n", len);
|
||||
#endif
|
||||
file = (PyObject *) context;
|
||||
if (file == NULL) return(-1);
|
||||
ret = PyEval_CallMethod(file, "read", "(i)", len);
|
||||
if (ret == NULL) {
|
||||
printf("xmlPythonFileReadRaw: result is NULL\n");
|
||||
return(-1);
|
||||
} else if (PyString_Check(ret)) {
|
||||
lenread = PyString_Size(ret);
|
||||
data = PyString_AsString(ret);
|
||||
if (lenread > len)
|
||||
memcpy(buffer, data, len);
|
||||
else
|
||||
memcpy(buffer, data, lenread);
|
||||
Py_DECREF(ret);
|
||||
} else {
|
||||
printf("xmlPythonFileReadRaw: result is not a String\n");
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
return(lenread);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlPythonFileRead:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to drop data
|
||||
* @len: number of bytes to write
|
||||
*
|
||||
* Read @len bytes to @buffer from the I/O channel.
|
||||
*
|
||||
* Returns the number of bytes read
|
||||
*/
|
||||
static int
|
||||
xmlPythonFileRead (void * context, char * buffer, int len) {
|
||||
PyObject *file;
|
||||
PyObject *ret;
|
||||
int lenread = -1;
|
||||
char *data;
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
printf("xmlPythonFileRead: %d\n", len);
|
||||
#endif
|
||||
file = (PyObject *) context;
|
||||
if (file == NULL) return(-1);
|
||||
ret = PyEval_CallMethod(file, "io_read", "(i)", len);
|
||||
if (ret == NULL) {
|
||||
printf("xmlPythonFileRead: result is NULL\n");
|
||||
return(-1);
|
||||
} else if (PyString_Check(ret)) {
|
||||
lenread = PyString_Size(ret);
|
||||
data = PyString_AsString(ret);
|
||||
if (lenread > len)
|
||||
memcpy(buffer, data, len);
|
||||
else
|
||||
memcpy(buffer, data, lenread);
|
||||
Py_DECREF(ret);
|
||||
} else {
|
||||
printf("xmlPythonFileRead: result is not a String\n");
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
return(lenread);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFileWrite:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to drop data
|
||||
* @len: number of bytes to write
|
||||
*
|
||||
* Write @len bytes from @buffer to the I/O channel.
|
||||
*
|
||||
* Returns the number of bytes written
|
||||
*/
|
||||
static int
|
||||
xmlPythonFileWrite (void * context, const char * buffer, int len) {
|
||||
PyObject *file;
|
||||
PyObject *string;
|
||||
PyObject *ret;
|
||||
int written = -1;
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
printf("xmlPythonFileWrite: %d\n", len);
|
||||
#endif
|
||||
file = (PyObject *) context;
|
||||
if (file == NULL) return(-1);
|
||||
string = PyString_FromStringAndSize(buffer, len);
|
||||
if (string == NULL) return(-1);
|
||||
ret = PyEval_CallMethod(file, "io_write", "(O)", string);
|
||||
Py_DECREF(string);
|
||||
if (ret == NULL) {
|
||||
printf("xmlPythonFileWrite: result is NULL\n");
|
||||
return(-1);
|
||||
} else if (PyInt_Check(ret)) {
|
||||
written = (int) PyInt_AsLong(ret);
|
||||
Py_DECREF(ret);
|
||||
} else if (ret == Py_None) {
|
||||
written = len;
|
||||
Py_DECREF(ret);
|
||||
} else {
|
||||
printf("xmlPythonFileWrite: result is not an Int nor None\n");
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
return(written);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlPythonFileClose:
|
||||
* @context: the I/O context
|
||||
*
|
||||
* Close an I/O channel
|
||||
*/
|
||||
static int
|
||||
xmlPythonFileClose (void * context) {
|
||||
PyObject *file, *ret;
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
printf("xmlPythonFileClose\n");
|
||||
#endif
|
||||
file = (PyObject *) context;
|
||||
if (file == NULL) return(-1);
|
||||
ret = PyEval_CallMethod(file, "io_close", "()");
|
||||
if (ret != NULL) {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferCreatePythonFile:
|
||||
* @file: a PyFile_Type
|
||||
* @encoder: the encoding converter or NULL
|
||||
*
|
||||
* Create a buffered output for the progressive saving to a PyFile_Type
|
||||
* buffered C I/O
|
||||
*
|
||||
* Returns the new parser output or NULL
|
||||
*/
|
||||
xmlOutputBufferPtr
|
||||
xmlOutputBufferCreatePythonFile(PyObject *file,
|
||||
xmlCharEncodingHandlerPtr encoder) {
|
||||
xmlOutputBufferPtr ret;
|
||||
|
||||
if (file == NULL) return(NULL);
|
||||
|
||||
ret = xmlAllocOutputBuffer(encoder);
|
||||
if (ret != NULL) {
|
||||
ret->context = file;
|
||||
/* Py_INCREF(file); */
|
||||
ret->writecallback = xmlPythonFileWrite;
|
||||
ret->closecallback = xmlPythonFileClose;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
PyObject *file;
|
||||
xmlChar *encoding;
|
||||
xmlCharEncodingHandlerPtr handler = NULL;
|
||||
xmlOutputBufferPtr buffer;
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate",
|
||||
&file, &encoding))
|
||||
return(NULL);
|
||||
if ((encoding != NULL) && (encoding[0] != 0)) {
|
||||
handler = xmlFindCharEncodingHandler(encoding);
|
||||
}
|
||||
buffer = xmlOutputBufferCreatePythonFile(file, handler);
|
||||
if (buffer == NULL)
|
||||
printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n");
|
||||
py_retval = libxml_xmlOutputBufferPtrWrap(buffer);
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlParserInputBufferCreatePythonFile:
|
||||
* @file: a PyFile_Type
|
||||
* @encoder: the encoding converter or NULL
|
||||
*
|
||||
* Create a buffered output for the progressive saving to a PyFile_Type
|
||||
* buffered C I/O
|
||||
*
|
||||
* Returns the new parser output or NULL
|
||||
*/
|
||||
xmlParserInputBufferPtr
|
||||
xmlParserInputBufferCreatePythonFile(PyObject *file,
|
||||
xmlCharEncoding encoding) {
|
||||
xmlParserInputBufferPtr ret;
|
||||
|
||||
if (file == NULL) return(NULL);
|
||||
|
||||
ret = xmlAllocParserInputBuffer(encoding);
|
||||
if (ret != NULL) {
|
||||
ret->context = file;
|
||||
/* Py_INCREF(file); */
|
||||
ret->readcallback = xmlPythonFileRead;
|
||||
ret->closecallback = xmlPythonFileClose;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlCreateInputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
PyObject *file;
|
||||
xmlChar *encoding;
|
||||
xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
|
||||
xmlParserInputBufferPtr buffer;
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"Oz:xmlParserInputBufferCreate",
|
||||
&file, &encoding))
|
||||
return(NULL);
|
||||
if ((encoding != NULL) && (encoding[0] != 0)) {
|
||||
enc = xmlParseCharEncoding(encoding);
|
||||
}
|
||||
buffer = xmlParserInputBufferCreatePythonFile(file, enc);
|
||||
if (buffer == NULL)
|
||||
printf("libxml_xmlParserInputBufferCreate: buffer == NULL\n");
|
||||
py_retval = libxml_xmlParserInputBufferPtrWrap(buffer);
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Providing the resolver at the Python level *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
static xmlExternalEntityLoader defaultExternalEntityLoader = NULL;
|
||||
static PyObject *pythonExternalEntityLoaderObjext;
|
||||
|
||||
static xmlParserInputPtr
|
||||
pythonExternalEntityLoader(const char *URL, const char *ID,
|
||||
xmlParserCtxtPtr ctxt) {
|
||||
xmlParserInputPtr result = NULL;
|
||||
if (pythonExternalEntityLoaderObjext != NULL) {
|
||||
PyObject *ret;
|
||||
PyObject *ctxtobj;
|
||||
|
||||
ctxtobj = libxml_xmlParserCtxtPtrWrap(ctxt);
|
||||
#ifdef DEBUG_LOADER
|
||||
printf("pythonExternalEntityLoader: ready to call\n");
|
||||
#endif
|
||||
|
||||
ret = PyObject_CallFunction(pythonExternalEntityLoaderObjext,
|
||||
"(ssO)", URL, ID, ctxtobj);
|
||||
#ifdef DEBUG_LOADER
|
||||
printf("pythonExternalEntityLoader: result ");
|
||||
PyObject_Print(ret, stdout, 0);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if (ret != NULL) {
|
||||
if (PyObject_HasAttrString(ret, "read")) {
|
||||
xmlParserInputBufferPtr buf;
|
||||
|
||||
buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
|
||||
if (buf != NULL) {
|
||||
buf->context = ret;
|
||||
buf->readcallback = xmlPythonFileReadRaw;
|
||||
buf->closecallback = xmlPythonFileCloseRaw;
|
||||
result = xmlNewIOInputStream(ctxt, buf,
|
||||
XML_CHAR_ENCODING_NONE);
|
||||
}
|
||||
} else {
|
||||
printf("pythonExternalEntityLoader: can't read\n");
|
||||
}
|
||||
if (result == NULL) {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((result == NULL) && (defaultExternalEntityLoader != NULL)) {
|
||||
result = defaultExternalEntityLoader(URL, ID, ctxt);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
|
||||
PyObject *py_retval;
|
||||
PyObject *loader;
|
||||
|
||||
if (!PyArg_ParseTuple(args, (char *)"O:libxml_xmlSetEntityLoader",
|
||||
&loader))
|
||||
return(NULL);
|
||||
|
||||
#ifdef DEBUG_LOADER
|
||||
printf("libxml_xmlSetEntityLoader\n");
|
||||
#endif
|
||||
if (defaultExternalEntityLoader == NULL)
|
||||
defaultExternalEntityLoader = xmlGetExternalEntityLoader();
|
||||
|
||||
pythonExternalEntityLoaderObjext = loader;
|
||||
xmlSetExternalEntityLoader(pythonExternalEntityLoader);
|
||||
|
||||
py_retval = PyInt_FromLong(0);
|
||||
return(py_retval);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Handling SAX/xmllib/sgmlop callback interfaces *
|
||||
@ -1821,6 +2188,9 @@ static PyMethodDef libxmlMethods[] = {
|
||||
{(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
|
||||
{(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
|
||||
{(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
|
||||
{(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
|
||||
{(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
|
||||
{(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
@ -1836,6 +2206,8 @@ initlibxml2mod(void)
|
||||
|
||||
if (initialized != 0)
|
||||
return;
|
||||
xmlRegisterDefaultOutputCallbacks();
|
||||
xmlRegisterDefaultInputCallbacks();
|
||||
m = Py_InitModule((char *) "libxml2mod", libxmlMethods);
|
||||
initialized = 1;
|
||||
libxml_xmlErrorInitialize();
|
||||
|
@ -27,6 +27,74 @@ class xpathError:
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class ioWrapper:
|
||||
def __init__(self, _obj):
|
||||
self.__io = _obj
|
||||
self._o = None
|
||||
|
||||
def io_close(self):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
self.__io.close()
|
||||
self.__io = None
|
||||
return(0)
|
||||
|
||||
def io_flush(self):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
self.__io.flush()
|
||||
return(0)
|
||||
|
||||
def io_read(self, len = -1):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
if len < 0:
|
||||
return(self.__io.read())
|
||||
return(self.__io.read(len))
|
||||
|
||||
def io_write(self, str, len = -1):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
if len < 0:
|
||||
return(self.__io.write(str))
|
||||
return(self.__io.write(str, len))
|
||||
|
||||
class ioReadWrapper(ioWrapper):
|
||||
def __init__(self, _obj, enc = ""):
|
||||
ioWrapper.__init__(self, _obj)
|
||||
self._o = libxml2mod.xmlCreateInputBuffer(self, enc)
|
||||
|
||||
def __del__(self):
|
||||
print "__del__"
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlFreeParserInputBuffer(self._o)
|
||||
self._o = None
|
||||
|
||||
def close(self):
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlFreeParserInputBuffer(self._o)
|
||||
self._o = None
|
||||
|
||||
class ioWriteWrapper(ioWrapper):
|
||||
def __init__(self, _obj, enc = ""):
|
||||
ioWrapper.__init__(self, _obj)
|
||||
self._o = libxml2mod.xmlCreateOutputBuffer(self, enc)
|
||||
|
||||
def __del__(self):
|
||||
print "__del__"
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlOutputBufferClose(self._o)
|
||||
self._o = None
|
||||
|
||||
def close(self):
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlOutputBufferClose(self._o)
|
||||
self._o = None
|
||||
|
||||
#
|
||||
# Example of a class to handle SAX events
|
||||
#
|
||||
|
@ -50,6 +50,23 @@
|
||||
<arg name='URI' type='xmlChar *' info='The URI of the resource'/>
|
||||
<arg name='encoding' type='const char *' info='encoding or None'/>
|
||||
</function>
|
||||
<function name='xmlCreateOutputBuffer' file='python'>
|
||||
<info>Create a libxml2 output buffer from a Python file</info>
|
||||
<return type='xmlOutputBufferPtr' info="the output buffer"/>
|
||||
<arg name='file' type='pythonObject' info='the Python file'/>
|
||||
<arg name='encoding' type='xmlChar *' info='an optionnal encoding'/>
|
||||
</function>
|
||||
<function name='xmlCreateInputBuffer' file='python'>
|
||||
<info>Create a libxml2 input buffer from a Python file</info>
|
||||
<return type='xmlParserInputBufferPtr' info="the input buffer"/>
|
||||
<arg name='file' type='pythonObject' info='the Python file'/>
|
||||
<arg name='encoding' type='xmlChar *' info='an optionnal encoding'/>
|
||||
</function>
|
||||
<function name='xmlSetEntityLoader' file='python'>
|
||||
<info>Set the entity resolver as a python function</info>
|
||||
<return type='int' info="0 in case of success, -1 for error"/>
|
||||
<arg name='resolver' type='pythonObject' info='the Python function'/>
|
||||
</function>
|
||||
<!-- xmlParserCtxtPtr accessors -->
|
||||
<function name='xmlParserGetDoc' file='python_accessor'>
|
||||
<info>Get the document tree from a parser context.</info>
|
||||
|
@ -114,6 +114,8 @@ nodePush()
|
||||
|
||||
# functions from module python
|
||||
SAXParseFile()
|
||||
createInputBuffer()
|
||||
createOutputBuffer()
|
||||
createPushParser()
|
||||
debugMemory()
|
||||
dumpMemory()
|
||||
@ -121,6 +123,7 @@ htmlCreatePushParser()
|
||||
htmlSAXParseFile()
|
||||
newNode()
|
||||
registerErrorHandler()
|
||||
setEntityLoader()
|
||||
|
||||
# functions from module tree
|
||||
compressMode()
|
||||
@ -276,10 +279,13 @@ Class xmlDoc(xmlNode)
|
||||
htmlIsAutoClosed()
|
||||
|
||||
# functions from module HTMLtree
|
||||
htmlDocContentDumpFormatOutput()
|
||||
htmlDocContentDumpOutput()
|
||||
htmlDocDump()
|
||||
htmlGetMetaEncoding()
|
||||
htmlNodeDumpFile()
|
||||
htmlNodeDumpFileFormat()
|
||||
htmlNodeDumpFormatOutput()
|
||||
htmlSaveFile()
|
||||
htmlSaveFileEnc()
|
||||
htmlSaveFileFormat()
|
||||
@ -323,10 +329,13 @@ Class xmlDoc(xmlNode)
|
||||
newDtd()
|
||||
newGlobalNs()
|
||||
newReference()
|
||||
nodeDumpOutput()
|
||||
saveFile()
|
||||
saveFileEnc()
|
||||
saveFileTo()
|
||||
saveFormatFile()
|
||||
saveFormatFileEnc()
|
||||
saveFormatFileTo()
|
||||
setDocCompressMode()
|
||||
stringGetNodeList()
|
||||
stringLenGetNodeList()
|
||||
@ -510,6 +519,15 @@ Class parserCtxt()
|
||||
stringDecodeEntities()
|
||||
|
||||
|
||||
Class outputBuffer(ioWriteWrapper)
|
||||
|
||||
# functions from module xmlIO
|
||||
close()
|
||||
flush()
|
||||
write()
|
||||
writeString()
|
||||
|
||||
|
||||
Class xmlElement(xmlNode)
|
||||
|
||||
|
||||
@ -584,3 +602,12 @@ Class xpathContext()
|
||||
xpathRegisteredVariablesCleanup()
|
||||
xpathVariableLookup()
|
||||
xpathVariableLookupNS()
|
||||
|
||||
|
||||
Class inputBuffer(ioReadWrapper)
|
||||
|
||||
# functions from module xmlIO
|
||||
freeParserInputBuffer()
|
||||
grow()
|
||||
push()
|
||||
read()
|
||||
|
@ -58,6 +58,22 @@ typedef struct {
|
||||
#define PyURI_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyURI_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlOutputBufferPtr obj;
|
||||
} PyoutputBuffer_Object;
|
||||
|
||||
#define PyoutputBuffer_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyURI_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlParserInputBufferPtr obj;
|
||||
} PyinputBuffer_Object;
|
||||
|
||||
#define PyinputBuffer_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyURI_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlURIPtr obj;
|
||||
@ -89,5 +105,7 @@ PyObject * libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt);
|
||||
PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj);
|
||||
PyObject * libxml_xmlCatalogPtrWrap(xmlCatalogPtr obj);
|
||||
PyObject * libxml_xmlURIPtrWrap(xmlURIPtr uri);
|
||||
PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer);
|
||||
PyObject * libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer);
|
||||
|
||||
xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
|
||||
|
@ -15,7 +15,10 @@ PYTESTS= \
|
||||
tstURI.py \
|
||||
cutnpaste.py\
|
||||
xpathret.py \
|
||||
xpath.py
|
||||
xpath.py \
|
||||
outbuf.py \
|
||||
inbuf.py \
|
||||
resolver.py
|
||||
|
||||
XMLS= \
|
||||
tst.xml \
|
||||
|
25
python/tests/inbuf.py
Executable file
25
python/tests/inbuf.py
Executable file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/python -u
|
||||
import sys
|
||||
import libxml2
|
||||
import StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
i = 0
|
||||
while i < 5000:
|
||||
f = StringIO.StringIO("foobar")
|
||||
buf = libxml2.inputBuffer(f)
|
||||
i = i + 1
|
||||
|
||||
del f
|
||||
del buf
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print "OK"
|
||||
else:
|
||||
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
|
||||
libxml2.dumpMemory()
|
||||
|
33
python/tests/outbuf.py
Executable file
33
python/tests/outbuf.py
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/python -u
|
||||
import sys
|
||||
import libxml2
|
||||
import StringIO
|
||||
|
||||
print "Skipped"
|
||||
sys.exit(1)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#f = open('res', 'w')
|
||||
f = StringIO.StringIO()
|
||||
buf = libxml2.createOutputBuffer(f, "ISO-8859-1")
|
||||
buf.write(3, "foo")
|
||||
buf.writeString("bar")
|
||||
buf.close()
|
||||
del buf
|
||||
|
||||
if f.getvalue() != "foobar":
|
||||
print "Failed to save to StringIO"
|
||||
sys.exit(1)
|
||||
|
||||
del f
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print "OK"
|
||||
else:
|
||||
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
|
||||
libxml2.dumpMemory()
|
||||
|
@ -49,7 +49,8 @@ chunk = "ar</foo>"
|
||||
ctxt.htmlParseChunk(chunk, len(chunk), 1)
|
||||
ctxt=None
|
||||
|
||||
reference = "startDocument:startElement foo {'url': 'tst'}:characters: bar:endElement foo:endDocument:"
|
||||
reference = """startDocument:startElement html None:startElement body None:startElement foo {'url': 'tst'}:error: Tag foo invalid
|
||||
:characters: bar:endElement foo:endElement body:endElement html:endDocument:"""
|
||||
if log != reference:
|
||||
print "Error got: %s" % log
|
||||
print "Exprected: %s" % reference
|
||||
|
39
python/tests/resolver.py
Executable file
39
python/tests/resolver.py
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/python -u
|
||||
import sys
|
||||
import libxml2
|
||||
import StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
def myResolver(URL, ID, ctxt):
|
||||
return(StringIO.StringIO("<foo/>"))
|
||||
|
||||
libxml2.setEntityLoader(myResolver)
|
||||
|
||||
doc = libxml2.parseFile("doesnotexist.xml")
|
||||
root = doc.children
|
||||
if root.name != "foo":
|
||||
print "root element name error"
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
i = 0
|
||||
while i < 5000:
|
||||
doc = libxml2.parseFile("doesnotexist.xml")
|
||||
root = doc.children
|
||||
if root.name != "foo":
|
||||
print "root element name error"
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
i = i + 1
|
||||
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print "OK"
|
||||
else:
|
||||
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
|
||||
libxml2.dumpMemory()
|
||||
|
@ -76,7 +76,7 @@ if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http
|
||||
sys.exit(1)
|
||||
str = doc.serialize("ISO-8859-1")
|
||||
if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>Hello</title></head><body><p>hello</p></body></html>
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Hello</title></head><body><p>hello</p></body></html>
|
||||
""":
|
||||
print "error serializing HTML document 2"
|
||||
sys.exit(1)
|
||||
@ -84,7 +84,7 @@ str = doc.serialize(format=1)
|
||||
if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body><p>hello</p></body>
|
||||
@ -96,7 +96,7 @@ str = doc.serialize("iso-8859-1", 1)
|
||||
if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body><p>hello</p></body>
|
||||
@ -115,13 +115,13 @@ if str != """<html><head><title>Hello</title></head><body><p>hello</p></body></h
|
||||
print "error serializing HTML root 1"
|
||||
sys.exit(1)
|
||||
str = root.serialize("ISO-8859-1")
|
||||
if str != """<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>Hello</title></head><body><p>hello</p></body></html>""":
|
||||
if str != """<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Hello</title></head><body><p>hello</p></body></html>""":
|
||||
print "error serializing HTML root 2"
|
||||
sys.exit(1)
|
||||
str = root.serialize(format=1)
|
||||
if str != """<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body><p>hello</p></body>
|
||||
@ -131,7 +131,7 @@ if str != """<html>
|
||||
str = root.serialize("iso-8859-1", 1)
|
||||
if str != """<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body><p>hello</p></body>
|
||||
|
@ -469,3 +469,39 @@ libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal)
|
||||
(char *) "xmlCatalogPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("libxml_xmlOutputBufferPtrWrap: buffer = %p\n", buffer);
|
||||
#endif
|
||||
if (buffer == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCObject_FromVoidPtrAndDesc((void *) buffer,
|
||||
(char *) "xmlOutputBufferPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("libxml_xmlParserInputBufferPtrWrap: buffer = %p\n", buffer);
|
||||
#endif
|
||||
if (buffer == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCObject_FromVoidPtrAndDesc((void *) buffer,
|
||||
(char *) "xmlParserInputBufferPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
Reference in New Issue
Block a user