| #include "Python.h" |
| #include "xmlparse.h" |
| |
| /* |
| ** The version number should match the one in _checkversion |
| */ |
| #define VERSION "1.9" |
| |
| enum HandlerTypes { |
| StartElement, |
| EndElement, |
| ProcessingInstruction, |
| CharacterData, |
| UnparsedEntityDecl, |
| NotationDecl, |
| StartNamespaceDecl, |
| EndNamespaceDecl, |
| Comment, |
| StartCdataSection, |
| EndCdataSection, |
| Default, |
| DefaultHandlerExpand, |
| NotStandalone, |
| ExternalEntityRef |
| }; |
| |
| static PyObject *ErrorObject; |
| |
| /* ----------------------------------------------------- */ |
| |
| /* Declarations for objects of type xmlparser */ |
| |
| typedef struct { |
| PyObject_HEAD |
| |
| XML_Parser itself; |
| int returns_unicode; /* True if Unicode strings are returned; |
| if false, UTF-8 strings are returned */ |
| PyObject **handlers; |
| } xmlparseobject; |
| |
| staticforward PyTypeObject Xmlparsetype; |
| |
| typedef void (*xmlhandlersetter)(XML_Parser *self, void *meth); |
| typedef void* xmlhandler; |
| |
| struct HandlerInfo { |
| const char *name; |
| xmlhandlersetter setter; |
| xmlhandler handler; |
| }; |
| |
| staticforward struct HandlerInfo handler_info[64]; |
| |
| /* Convert an array of attributes and their values into a Python dict */ |
| |
| static PyObject * |
| conv_atts_using_string(XML_Char **atts) |
| { |
| PyObject *attrs_obj = NULL; |
| XML_Char **attrs_p, **attrs_k = NULL; |
| int attrs_len; |
| PyObject *rv; |
| |
| if ((attrs_obj = PyDict_New()) == NULL) |
| goto finally; |
| for (attrs_len = 0, attrs_p = atts; |
| *attrs_p; |
| attrs_p++, attrs_len++) { |
| if (attrs_len % 2) { |
| rv = PyString_FromString(*attrs_p); |
| if (!rv) { |
| Py_DECREF(attrs_obj); |
| attrs_obj = NULL; |
| goto finally; |
| } |
| if (PyDict_SetItemString(attrs_obj, |
| (char*)*attrs_k, rv) < 0) { |
| Py_DECREF(attrs_obj); |
| attrs_obj = NULL; |
| goto finally; |
| } |
| Py_DECREF(rv); |
| } |
| else |
| attrs_k = attrs_p; |
| } |
| finally: |
| return attrs_obj; |
| } |
| |
| #if !(PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6) |
| static PyObject * |
| conv_atts_using_unicode(XML_Char **atts) |
| { |
| PyObject *attrs_obj = NULL; |
| XML_Char **attrs_p, **attrs_k = NULL; |
| int attrs_len; |
| |
| if ((attrs_obj = PyDict_New()) == NULL) |
| goto finally; |
| for (attrs_len = 0, attrs_p = atts; |
| *attrs_p; |
| attrs_p++, attrs_len++) { |
| if (attrs_len % 2) { |
| PyObject *attr_str, *value_str; |
| const char *p = (const char *) (*attrs_k); |
| attr_str = PyUnicode_DecodeUTF8(p, strlen(p), "strict"); |
| if (!attr_str) { |
| Py_DECREF(attrs_obj); |
| attrs_obj = NULL; |
| goto finally; |
| } |
| p = (const char *) *attrs_p; |
| value_str = PyUnicode_DecodeUTF8(p, strlen(p), "strict"); |
| if (!value_str) { |
| Py_DECREF(attrs_obj); |
| Py_DECREF(attr_str); |
| attrs_obj = NULL; |
| goto finally; |
| } |
| if (PyDict_SetItem(attrs_obj, attr_str, value_str) < 0) { |
| Py_DECREF(attrs_obj); |
| attrs_obj = NULL; |
| goto finally; |
| } |
| Py_DECREF(attr_str); |
| Py_DECREF(value_str); |
| } |
| else |
| attrs_k = attrs_p; |
| } |
| finally: |
| return attrs_obj; |
| } |
| |
| /* Convert a string of XML_Chars into a Unicode string. |
| Returns None if str is a null pointer. */ |
| |
| static PyObject * |
| conv_string_to_unicode(XML_Char *str) |
| { |
| /* XXX currently this code assumes that XML_Char is 8-bit, |
| and hence in UTF-8. */ |
| /* UTF-8 from Expat, Unicode desired */ |
| if (str == NULL) { |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| return PyUnicode_DecodeUTF8((const char *)str, |
| strlen((const char *)str), |
| "strict"); |
| } |
| |
| static PyObject * |
| conv_string_len_to_unicode(const XML_Char *str, int len) |
| { |
| /* XXX currently this code assumes that XML_Char is 8-bit, |
| and hence in UTF-8. */ |
| /* UTF-8 from Expat, Unicode desired */ |
| if (str == NULL) { |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| return PyUnicode_DecodeUTF8((const char *)str, len, "strict"); |
| } |
| #endif |
| |
| /* Convert a string of XML_Chars into an 8-bit Python string. |
| Returns None if str is a null pointer. */ |
| |
| static PyObject * |
| conv_string_to_utf8(XML_Char *str) |
| { |
| /* XXX currently this code assumes that XML_Char is 8-bit, |
| and hence in UTF-8. */ |
| /* UTF-8 from Expat, UTF-8 desired */ |
| if (str == NULL) { |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| return PyString_FromString((const char *)str); |
| } |
| |
| static PyObject * |
| conv_string_len_to_utf8(const XML_Char *str, int len) |
| { |
| /* XXX currently this code assumes that XML_Char is 8-bit, |
| and hence in UTF-8. */ |
| /* UTF-8 from Expat, UTF-8 desired */ |
| if (str == NULL) { |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| return PyString_FromStringAndSize((const char *)str, len); |
| } |
| |
| /* Callback routines */ |
| |
| static void clear_handlers(xmlparseobject *self); |
| |
| static void |
| flag_error(xmlparseobject *self) |
| { |
| clear_handlers(self); |
| } |
| |
| #define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \ |
| RETURN, GETUSERDATA) \ |
| \ |
| static RC my_##NAME##Handler PARAMS {\ |
| xmlparseobject *self = GETUSERDATA ; \ |
| PyObject *args=NULL; \ |
| PyObject *rv=NULL; \ |
| INIT \ |
| \ |
| if (self->handlers[NAME] \ |
| && self->handlers[NAME] != Py_None) { \ |
| args = Py_BuildValue PARAM_FORMAT ;\ |
| if (!args) return RETURN; \ |
| rv = PyEval_CallObject(self->handlers[NAME], args); \ |
| Py_DECREF(args); \ |
| if (rv == NULL) { \ |
| flag_error(self); \ |
| return RETURN; \ |
| } \ |
| CONVERSION \ |
| Py_DECREF(rv); \ |
| } \ |
| return RETURN; \ |
| } |
| |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| #define STRING_CONV_FUNC conv_string_to_utf8 |
| #else |
| /* Python 1.6 and later versions */ |
| #define STRING_CONV_FUNC (self->returns_unicode \ |
| ? conv_string_to_unicode : conv_string_to_utf8) |
| #endif |
| |
| #define VOID_HANDLER(NAME, PARAMS, PARAM_FORMAT) \ |
| RC_HANDLER(void, NAME, PARAMS, ;, PARAM_FORMAT, ;, ;,\ |
| (xmlparseobject *)userData) |
| |
| #define INT_HANDLER(NAME, PARAMS, PARAM_FORMAT)\ |
| RC_HANDLER(int, NAME, PARAMS, int rc=0;, PARAM_FORMAT, \ |
| rc = PyInt_AsLong(rv);, rc, \ |
| (xmlparseobject *)userData) |
| |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| VOID_HANDLER(StartElement, |
| (void *userData, const XML_Char *name, const XML_Char **atts), |
| ("(O&O&)", STRING_CONV_FUNC, name, |
| conv_atts_using_string, atts ) ) |
| #else |
| /* Python 1.6 and later */ |
| VOID_HANDLER(StartElement, |
| (void *userData, const XML_Char *name, const XML_Char **atts), |
| ("(O&O&)", STRING_CONV_FUNC, name, |
| (self->returns_unicode |
| ? conv_atts_using_unicode |
| : conv_atts_using_string), atts)) |
| #endif |
| |
| VOID_HANDLER(EndElement, |
| (void *userData, const XML_Char *name), |
| ("(O&)", STRING_CONV_FUNC, name)) |
| |
| VOID_HANDLER(ProcessingInstruction, |
| (void *userData, |
| const XML_Char *target, |
| const XML_Char *data), |
| ("(O&O&)",STRING_CONV_FUNC,target, STRING_CONV_FUNC,data)) |
| |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| VOID_HANDLER(CharacterData, |
| (void *userData, const XML_Char *data, int len), |
| ("(O)", conv_string_len_to_utf8(data,len))) |
| #else |
| VOID_HANDLER(CharacterData, |
| (void *userData, const XML_Char *data, int len), |
| ("(O)", (self->returns_unicode |
| ? conv_string_len_to_unicode(data,len) |
| : conv_string_len_to_utf8(data,len)))) |
| #endif |
| |
| VOID_HANDLER(UnparsedEntityDecl, |
| (void *userData, |
| const XML_Char *entityName, |
| const XML_Char *base, |
| const XML_Char *systemId, |
| const XML_Char *publicId, |
| const XML_Char *notationName), |
| ("(O&O&O&O&O&)", |
| STRING_CONV_FUNC,entityName, STRING_CONV_FUNC,base, |
| STRING_CONV_FUNC,systemId, STRING_CONV_FUNC,publicId, |
| STRING_CONV_FUNC,notationName)) |
| |
| VOID_HANDLER(NotationDecl, |
| (void *userData, |
| const XML_Char *notationName, |
| const XML_Char *base, |
| const XML_Char *systemId, |
| const XML_Char *publicId), |
| ("(O&O&O&O&)", |
| STRING_CONV_FUNC,notationName, STRING_CONV_FUNC,base, |
| STRING_CONV_FUNC,systemId, STRING_CONV_FUNC,publicId)) |
| |
| VOID_HANDLER(StartNamespaceDecl, |
| (void *userData, |
| const XML_Char *prefix, |
| const XML_Char *uri), |
| ("(O&O&)", STRING_CONV_FUNC,prefix, STRING_CONV_FUNC,uri)) |
| |
| VOID_HANDLER(EndNamespaceDecl, |
| (void *userData, |
| const XML_Char *prefix), |
| ("(O&)", STRING_CONV_FUNC,prefix)) |
| |
| VOID_HANDLER(Comment, |
| (void *userData, const XML_Char *prefix), |
| ("(O&)", STRING_CONV_FUNC,prefix)) |
| |
| VOID_HANDLER(StartCdataSection, |
| (void *userData), |
| ("()")) |
| |
| VOID_HANDLER(EndCdataSection, |
| (void *userData), |
| ("()")) |
| |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| VOID_HANDLER(Default, |
| (void *userData, const XML_Char *s, int len), |
| ("(O)", conv_string_len_to_utf8(s,len))) |
| |
| VOID_HANDLER(DefaultHandlerExpand, |
| (void *userData, const XML_Char *s, int len), |
| ("(O)", conv_string_len_to_utf8(s,len))) |
| #else |
| VOID_HANDLER(Default, |
| (void *userData, const XML_Char *s, int len), |
| ("(O)", (self->returns_unicode |
| ? conv_string_len_to_unicode(s,len) |
| : conv_string_len_to_utf8(s,len)))) |
| |
| VOID_HANDLER(DefaultHandlerExpand, |
| (void *userData, const XML_Char *s, int len), |
| ("(O)", (self->returns_unicode |
| ? conv_string_len_to_unicode(s,len) |
| : conv_string_len_to_utf8(s,len)))) |
| #endif |
| |
| INT_HANDLER(NotStandalone, |
| (void *userData), |
| ("()")) |
| |
| RC_HANDLER(int, ExternalEntityRef, |
| (XML_Parser parser, |
| const XML_Char *context, |
| const XML_Char *base, |
| const XML_Char *systemId, |
| const XML_Char *publicId), |
| int rc=0;, |
| ("(O&O&O&O&)", |
| STRING_CONV_FUNC,context, STRING_CONV_FUNC,base, |
| STRING_CONV_FUNC,systemId, STRING_CONV_FUNC,publicId), |
| rc = PyInt_AsLong(rv);, rc, |
| XML_GetUserData(parser)) |
| |
| |
| |
| /* File reading copied from cPickle */ |
| |
| #define UNLESS(E) if (!(E)) |
| |
| /* |
| static int |
| read_other(xmlparseobject *self, char **s, int n) { |
| PyObject *bytes=NULL, *str=NULL, *arg=NULL; |
| int res = -1; |
| |
| UNLESS(bytes = PyInt_FromLong(n)) { |
| if (!PyErr_Occurred()) |
| PyErr_SetNone(PyExc_EOFError); |
| |
| goto finally; |
| } |
| |
| UNLESS(arg) |
| UNLESS(arg = PyTuple_New(1)) |
| goto finally; |
| |
| Py_INCREF(bytes); |
| if (PyTuple_SetItem(arg, 0, bytes) < 0) |
| goto finally; |
| |
| UNLESS(str = PyObject_CallObject(self->read, arg)) |
| goto finally; |
| |
| *s = PyString_AsString(str); |
| |
| res = n; |
| |
| finally: |
| Py_XDECREF(arg); |
| Py_XDECREF(bytes); |
| |
| return res; |
| } |
| |
| */ |
| |
| |
| |
| /* ---------------------------------------------------------------- */ |
| |
| static char xmlparse_Parse__doc__[] = |
| "Parse(data[, isfinal])\n\ |
| Parse XML data. `isfinal' should be true at end of input."; |
| |
| static PyObject * |
| xmlparse_Parse(xmlparseobject *self, PyObject *args) |
| { |
| char *s; |
| int slen; |
| int isFinal = 0; |
| int rv; |
| |
| if (!PyArg_ParseTuple(args, "s#|i:Parse", &s, &slen, &isFinal)) |
| return NULL; |
| rv = XML_Parse(self->itself, s, slen, isFinal); |
| if (PyErr_Occurred()) { |
| return NULL; |
| } |
| else if (rv == 0) { |
| PyErr_Format(ErrorObject, "%.200s: line %i, column %i", |
| XML_ErrorString(XML_GetErrorCode(self->itself)), |
| XML_GetErrorLineNumber(self->itself), |
| XML_GetErrorColumnNumber(self->itself)); |
| return NULL; |
| } |
| return PyInt_FromLong(rv); |
| } |
| |
| #define BUF_SIZE 2048 |
| |
| static int |
| readinst(char *buf, int buf_size, PyObject *meth) |
| { |
| PyObject *arg = NULL; |
| PyObject *bytes = NULL; |
| PyObject *str = NULL; |
| int len = -1; |
| |
| UNLESS(bytes = PyInt_FromLong(buf_size)) { |
| if (!PyErr_Occurred()) |
| PyErr_SetNone(PyExc_EOFError); |
| goto finally; |
| } |
| UNLESS(arg) |
| UNLESS(arg = PyTuple_New(1)) |
| goto finally; |
| |
| if (PyTuple_SetItem(arg, 0, bytes) < 0) |
| goto finally; |
| |
| UNLESS(str = PyObject_CallObject(meth, arg)) |
| goto finally; |
| |
| /* XXX what to do if it returns a Unicode string? */ |
| UNLESS(PyString_Check(str)) { |
| PyErr_Format(PyExc_TypeError, |
| "read() did not return a string object (type=%.400s)", |
| str->ob_type->tp_name); |
| goto finally; |
| } |
| len = PyString_GET_SIZE(str); |
| if (len > buf_size) { |
| PyErr_Format(PyExc_ValueError, |
| "read() returned too much data: " |
| "%i bytes requested, %i returned", |
| buf_size, len); |
| Py_DECREF(str); |
| goto finally; |
| } |
| memcpy(buf, PyString_AsString(str), len); |
| Py_XDECREF(str); |
| finally: |
| Py_XDECREF(arg); |
| return len; |
| } |
| |
| static char xmlparse_ParseFile__doc__[] = |
| "ParseFile(file)\n\ |
| Parse XML data from file-like object."; |
| |
| static PyObject * |
| xmlparse_ParseFile(xmlparseobject *self, PyObject *args) |
| { |
| int rv = 1; |
| PyObject *f; |
| FILE *fp; |
| PyObject *readmethod = NULL; |
| |
| if (!PyArg_ParseTuple(args, "O:ParseFile", &f)) |
| return NULL; |
| |
| if (PyFile_Check(f)) { |
| fp = PyFile_AsFile(f); |
| } |
| else{ |
| fp = NULL; |
| UNLESS(readmethod = PyObject_GetAttrString(f, "read")) { |
| PyErr_Clear(); |
| PyErr_SetString(PyExc_TypeError, |
| "argument must have 'read' attribute"); |
| return 0; |
| } |
| } |
| for (;;) { |
| int bytes_read; |
| void *buf = XML_GetBuffer(self->itself, BUF_SIZE); |
| if (buf == NULL) |
| return PyErr_NoMemory(); |
| |
| if (fp) { |
| bytes_read = fread(buf, sizeof(char), BUF_SIZE, fp); |
| if (bytes_read < 0) { |
| PyErr_SetFromErrno(PyExc_IOError); |
| return NULL; |
| } |
| } |
| else { |
| bytes_read = readinst(buf, BUF_SIZE, readmethod); |
| if (bytes_read < 0) |
| return NULL; |
| } |
| rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0); |
| if (PyErr_Occurred()) |
| return NULL; |
| |
| if (!rv || bytes_read == 0) |
| break; |
| } |
| return Py_BuildValue("i", rv); |
| } |
| |
| static char xmlparse_SetBase__doc__[] = |
| "SetBase(base_url)\n\ |
| Set the base URL for the parser."; |
| |
| static PyObject * |
| xmlparse_SetBase(xmlparseobject *self, PyObject *args) |
| { |
| char *base; |
| |
| if (!PyArg_ParseTuple(args, "s:SetBase", &base)) |
| return NULL; |
| if (!XML_SetBase(self->itself, base)) { |
| return PyErr_NoMemory(); |
| } |
| Py_INCREF(Py_None); |
| return Py_None; |
| } |
| |
| static char xmlparse_GetBase__doc__[] = |
| "GetBase() -> url\n\ |
| Return base URL string for the parser."; |
| |
| static PyObject * |
| xmlparse_GetBase(xmlparseobject *self, PyObject *args) |
| { |
| if (!PyArg_ParseTuple(args, ":GetBase")) |
| return NULL; |
| |
| return Py_BuildValue("z", XML_GetBase(self->itself)); |
| } |
| |
| static struct PyMethodDef xmlparse_methods[] = { |
| {"Parse", (PyCFunction)xmlparse_Parse, |
| METH_VARARGS, xmlparse_Parse__doc__}, |
| {"ParseFile", (PyCFunction)xmlparse_ParseFile, |
| METH_VARARGS, xmlparse_ParseFile__doc__}, |
| {"SetBase", (PyCFunction)xmlparse_SetBase, |
| METH_VARARGS, xmlparse_SetBase__doc__}, |
| {"GetBase", (PyCFunction)xmlparse_GetBase, |
| METH_VARARGS, xmlparse_GetBase__doc__}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| /* ---------- */ |
| |
| |
| static xmlparseobject * |
| newxmlparseobject(char *encoding, char *namespace_separator) |
| { |
| int i; |
| xmlparseobject *self; |
| |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| self = PyObject_NEW(xmlparseobject, &Xmlparsetype); |
| if (self == NULL) |
| return NULL; |
| |
| self->returns_unicode = 0; |
| #else |
| /* Code for versions 1.6 and later */ |
| self = PyObject_New(xmlparseobject, &Xmlparsetype); |
| if (self == NULL) |
| return NULL; |
| |
| self->returns_unicode = 1; |
| #endif |
| if (namespace_separator) { |
| self->itself = XML_ParserCreateNS(encoding, *namespace_separator); |
| } |
| else{ |
| self->itself = XML_ParserCreate(encoding); |
| } |
| if (self->itself == NULL) { |
| PyErr_SetString(PyExc_RuntimeError, |
| "XML_ParserCreate failed"); |
| Py_DECREF(self); |
| return NULL; |
| } |
| XML_SetUserData(self->itself, (void *)self); |
| |
| for(i = 0; handler_info[i].name != NULL; i++) |
| /* do nothing */; |
| |
| self->handlers = malloc(sizeof(PyObject *)*i); |
| clear_handlers(self); |
| |
| return self; |
| } |
| |
| |
| static void |
| xmlparse_dealloc(xmlparseobject *self) |
| { |
| int i; |
| if (self->itself) |
| XML_ParserFree(self->itself); |
| self->itself = NULL; |
| |
| for (i=0; handler_info[i].name != NULL; i++) { |
| Py_XDECREF(self->handlers[i]); |
| } |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| /* Code for versions before 1.6 */ |
| free(self); |
| #else |
| /* Code for versions 1.6 and later */ |
| PyObject_Del(self); |
| #endif |
| } |
| |
| static int |
| handlername2int(const char *name) |
| { |
| int i; |
| for (i=0; handler_info[i].name != NULL; i++) { |
| if (strcmp(name, handler_info[i].name) == 0) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| static PyObject * |
| xmlparse_getattr(xmlparseobject *self, char *name) |
| { |
| int handlernum; |
| if (strcmp(name, "ErrorCode") == 0) |
| return Py_BuildValue("l", |
| (long)XML_GetErrorCode(self->itself)); |
| if (strcmp(name, "ErrorLineNumber") == 0) |
| return Py_BuildValue("l", |
| (long)XML_GetErrorLineNumber(self->itself)); |
| if (strcmp(name, "ErrorColumnNumber") == 0) |
| return Py_BuildValue("l", |
| (long)XML_GetErrorColumnNumber(self->itself)); |
| if (strcmp(name, "ErrorByteIndex") == 0) |
| return Py_BuildValue("l", |
| XML_GetErrorByteIndex(self->itself)); |
| if (strcmp(name, "returns_unicode") == 0) |
| return Py_BuildValue("i", self->returns_unicode); |
| |
| handlernum = handlername2int(name); |
| |
| if (handlernum != -1 && self->handlers[handlernum] != NULL) { |
| Py_INCREF(self->handlers[handlernum]); |
| return self->handlers[handlernum]; |
| } |
| if (strcmp(name, "__members__") == 0) { |
| int i; |
| PyObject *rc = PyList_New(0); |
| for(i = 0; handler_info[i].name!=NULL; i++) { |
| PyList_Append(rc, |
| PyString_FromString(handler_info[i].name)); |
| } |
| PyList_Append(rc, PyString_FromString("ErrorCode")); |
| PyList_Append(rc, PyString_FromString("ErrorLineNumber")); |
| PyList_Append(rc, PyString_FromString("ErrorColumnNumber")); |
| PyList_Append(rc, PyString_FromString("ErrorByteIndex")); |
| |
| return rc; |
| } |
| return Py_FindMethod(xmlparse_methods, (PyObject *)self, name); |
| } |
| |
| static int |
| sethandler(xmlparseobject *self, const char *name, PyObject* v) |
| { |
| int handlernum = handlername2int(name); |
| if (handlernum != -1) { |
| Py_INCREF(v); |
| Py_XDECREF(self->handlers[handlernum]); |
| self->handlers[handlernum] = v; |
| handler_info[handlernum].setter(self->itself, |
| handler_info[handlernum].handler); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int |
| xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v) |
| { |
| /* Set attribute 'name' to value 'v'. v==NULL means delete */ |
| if (v==NULL) { |
| PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); |
| return -1; |
| } |
| if (strcmp(name, "returns_unicode") == 0) { |
| PyObject *intobj = PyNumber_Int(v); |
| if (intobj == NULL) return -1; |
| if (PyInt_AsLong(intobj)) { |
| #if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6 |
| PyErr_SetString(PyExc_ValueError, |
| "Cannot return Unicode strings in Python 1.5"); |
| return -1; |
| #else |
| self->returns_unicode = 1; |
| #endif |
| } |
| else |
| self->returns_unicode = 0; |
| Py_DECREF(intobj); |
| return 0; |
| } |
| if (sethandler(self, name, v)) { |
| return 0; |
| } |
| PyErr_SetString(PyExc_AttributeError, name); |
| return -1; |
| } |
| |
| static char Xmlparsetype__doc__[] = |
| "XML parser"; |
| |
| static PyTypeObject Xmlparsetype = { |
| PyObject_HEAD_INIT(NULL) |
| 0, /*ob_size*/ |
| "xmlparser", /*tp_name*/ |
| sizeof(xmlparseobject), /*tp_basicsize*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)xmlparse_dealloc, /*tp_dealloc*/ |
| (printfunc)0, /*tp_print*/ |
| (getattrfunc)xmlparse_getattr, /*tp_getattr*/ |
| (setattrfunc)xmlparse_setattr, /*tp_setattr*/ |
| (cmpfunc)0, /*tp_compare*/ |
| (reprfunc)0, /*tp_repr*/ |
| 0, /*tp_as_number*/ |
| 0, /*tp_as_sequence*/ |
| 0, /*tp_as_mapping*/ |
| (hashfunc)0, /*tp_hash*/ |
| (ternaryfunc)0, /*tp_call*/ |
| (reprfunc)0, /*tp_str*/ |
| |
| /* Space for future expansion */ |
| 0L,0L,0L,0L, |
| Xmlparsetype__doc__ /* Documentation string */ |
| }; |
| |
| /* End of code for xmlparser objects */ |
| /* -------------------------------------------------------- */ |
| |
| |
| static char pyexpat_ParserCreate__doc__[] = |
| "ParserCreate([encoding[, namespace_separator]]) -> parser\n\ |
| Return a new XML parser object."; |
| |
| static PyObject * |
| pyexpat_ParserCreate(PyObject *notused, PyObject *args, PyObject *kw) |
| { |
| char *encoding = NULL; |
| char *namespace_separator = NULL; |
| static char *kwlist[] = {"encoding", "namespace_separator", NULL}; |
| |
| if (!PyArg_ParseTupleAndKeywords(args, kw, "|zz:ParserCreate", kwlist, |
| &encoding, &namespace_separator)) |
| return NULL; |
| return (PyObject *)newxmlparseobject(encoding, namespace_separator); |
| } |
| |
| static char pyexpat_ErrorString__doc__[] = |
| "ErrorString(errno) -> string\n\ |
| Returns string error for given number."; |
| |
| static PyObject * |
| pyexpat_ErrorString(PyObject *self, PyObject *args) |
| { |
| long code = 0; |
| |
| if (!PyArg_ParseTuple(args, "l:ErrorString", &code)) |
| return NULL; |
| return Py_BuildValue("z", XML_ErrorString((int)code)); |
| } |
| |
| /* List of methods defined in the module */ |
| |
| static struct PyMethodDef pyexpat_methods[] = { |
| {"ParserCreate", (PyCFunction)pyexpat_ParserCreate, |
| METH_VARARGS|METH_KEYWORDS, pyexpat_ParserCreate__doc__}, |
| {"ErrorString", (PyCFunction)pyexpat_ErrorString, |
| METH_VARARGS, pyexpat_ErrorString__doc__}, |
| |
| {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ |
| }; |
| |
| /* Module docstring */ |
| |
| static char pyexpat_module_documentation[] = |
| "Python wrapper for Expat parser."; |
| |
| /* Initialization function for the module */ |
| |
| DL_EXPORT(void) initpyexpat(void); /* supply a prototype */ |
| |
| DL_EXPORT(void) |
| initpyexpat(void) |
| { |
| PyObject *m, *d; |
| char *rev = "$Revision$"; |
| PyObject *errmod_name = PyString_FromString("pyexpat.errors"); |
| PyObject *errors_module, *errors_dict; |
| PyObject *sys_modules; |
| |
| if (errmod_name == NULL) |
| return; |
| |
| Xmlparsetype.ob_type = &PyType_Type; |
| |
| /* Create the module and add the functions */ |
| m = Py_InitModule4("pyexpat", pyexpat_methods, |
| pyexpat_module_documentation, |
| (PyObject*)NULL, PYTHON_API_VERSION); |
| |
| /* Add some symbolic constants to the module */ |
| d = PyModule_GetDict(m); |
| if (ErrorObject == NULL) |
| ErrorObject = PyErr_NewException("pyexpat.error", NULL, NULL); |
| PyDict_SetItemString(d, "error", ErrorObject); |
| |
| PyDict_SetItemString(d, "__version__", |
| PyString_FromStringAndSize(rev+11, |
| strlen(rev+11)-2)); |
| |
| /* XXX When Expat supports some way of figuring out how it was |
| compiled, this should check and set native_encoding |
| appropriately. |
| */ |
| PyDict_SetItemString(d, "native_encoding", |
| PyString_FromString("UTF-8")); |
| |
| errors_module = PyDict_GetItem(d, errmod_name); |
| if (errors_module == NULL) { |
| errors_module = PyModule_New("pyexpat.errors"); |
| if (errors_module != NULL) { |
| sys_modules = PySys_GetObject("modules"); |
| PyDict_SetItemString(d, "errors", errors_module); |
| PyDict_SetItem(sys_modules, errmod_name, errors_module); |
| } |
| } |
| Py_DECREF(errmod_name); |
| if (errors_module == NULL) |
| /* Don't code dump later! */ |
| return; |
| |
| errors_dict = PyModule_GetDict(errors_module); |
| |
| #define MYCONST(name) \ |
| PyDict_SetItemString(errors_dict, #name, \ |
| PyString_FromString(XML_ErrorString(name))) |
| |
| MYCONST(XML_ERROR_NO_MEMORY); |
| MYCONST(XML_ERROR_SYNTAX); |
| MYCONST(XML_ERROR_NO_ELEMENTS); |
| MYCONST(XML_ERROR_INVALID_TOKEN); |
| MYCONST(XML_ERROR_UNCLOSED_TOKEN); |
| MYCONST(XML_ERROR_PARTIAL_CHAR); |
| MYCONST(XML_ERROR_TAG_MISMATCH); |
| MYCONST(XML_ERROR_DUPLICATE_ATTRIBUTE); |
| MYCONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT); |
| MYCONST(XML_ERROR_PARAM_ENTITY_REF); |
| MYCONST(XML_ERROR_UNDEFINED_ENTITY); |
| MYCONST(XML_ERROR_RECURSIVE_ENTITY_REF); |
| MYCONST(XML_ERROR_ASYNC_ENTITY); |
| MYCONST(XML_ERROR_BAD_CHAR_REF); |
| MYCONST(XML_ERROR_BINARY_ENTITY_REF); |
| MYCONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF); |
| MYCONST(XML_ERROR_MISPLACED_XML_PI); |
| MYCONST(XML_ERROR_UNKNOWN_ENCODING); |
| MYCONST(XML_ERROR_INCORRECT_ENCODING); |
| } |
| |
| static void |
| clear_handlers(xmlparseobject *self) |
| { |
| int i = 0; |
| |
| for (; handler_info[i].name!=NULL; i++) { |
| self->handlers[i]=NULL; |
| handler_info[i].setter(self->itself, NULL); |
| } |
| } |
| |
| typedef void (*pairsetter)(XML_Parser, void *handler1, void *handler2); |
| |
| static void |
| pyxml_UpdatePairedHandlers(xmlparseobject *self, |
| int startHandler, |
| int endHandler, |
| pairsetter setter) |
| { |
| void *start_handler=NULL; |
| void *end_handler=NULL; |
| |
| if (self->handlers[startHandler] |
| && self->handlers[endHandler]!=Py_None) { |
| start_handler=handler_info[startHandler].handler; |
| } |
| if (self->handlers[EndElement] |
| && self->handlers[EndElement] !=Py_None) { |
| end_handler=handler_info[endHandler].handler; |
| } |
| setter(self->itself, start_handler, end_handler); |
| } |
| |
| static void |
| pyxml_SetStartElementHandler(XML_Parser *parser, void *junk) |
| { |
| pyxml_UpdatePairedHandlers((xmlparseobject *)XML_GetUserData(parser), |
| StartElement, EndElement, |
| (pairsetter)XML_SetElementHandler); |
| } |
| |
| static void |
| pyxml_SetEndElementHandler(XML_Parser *parser, void *junk) |
| { |
| pyxml_UpdatePairedHandlers((xmlparseobject *)XML_GetUserData(parser), |
| StartElement, EndElement, |
| (pairsetter)XML_SetElementHandler); |
| } |
| |
| static void |
| pyxml_SetStartNamespaceDeclHandler(XML_Parser *parser, void *junk) |
| { |
| pyxml_UpdatePairedHandlers((xmlparseobject *)XML_GetUserData(parser), |
| StartNamespaceDecl, EndNamespaceDecl, |
| (pairsetter)XML_SetNamespaceDeclHandler); |
| } |
| |
| static void |
| pyxml_SetEndNamespaceDeclHandler(XML_Parser *parser, void *junk) |
| { |
| pyxml_UpdatePairedHandlers((xmlparseobject *)XML_GetUserData(parser), |
| StartNamespaceDecl, EndNamespaceDecl, |
| (pairsetter)XML_SetNamespaceDeclHandler); |
| } |
| |
| static void |
| pyxml_SetStartCdataSection(XML_Parser *parser, void *junk) |
| { |
| pyxml_UpdatePairedHandlers((xmlparseobject *)XML_GetUserData(parser), |
| StartCdataSection, EndCdataSection, |
| (pairsetter)XML_SetCdataSectionHandler); |
| } |
| |
| static void |
| pyxml_SetEndCdataSection(XML_Parser *parser, void *junk) |
| { |
| pyxml_UpdatePairedHandlers((xmlparseobject *)XML_GetUserData(parser), |
| StartCdataSection, EndCdataSection, |
| (pairsetter)XML_SetCdataSectionHandler); |
| } |
| |
| statichere struct HandlerInfo handler_info[] = { |
| {"StartElementHandler", |
| pyxml_SetStartElementHandler, |
| (xmlhandler)my_StartElementHandler}, |
| {"EndElementHandler", |
| pyxml_SetEndElementHandler, |
| (xmlhandler)my_EndElementHandler}, |
| {"ProcessingInstructionHandler", |
| (xmlhandlersetter)XML_SetProcessingInstructionHandler, |
| (xmlhandler)my_ProcessingInstructionHandler}, |
| {"CharacterDataHandler", |
| (xmlhandlersetter)XML_SetCharacterDataHandler, |
| (xmlhandler)my_CharacterDataHandler}, |
| {"UnparsedEntityDeclHandler", |
| (xmlhandlersetter)XML_SetUnparsedEntityDeclHandler, |
| (xmlhandler)my_UnparsedEntityDeclHandler }, |
| {"NotationDeclHandler", |
| (xmlhandlersetter)XML_SetNotationDeclHandler, |
| (xmlhandler)my_NotationDeclHandler }, |
| {"StartNamespaceDeclHandler", |
| pyxml_SetStartNamespaceDeclHandler, |
| (xmlhandler)my_StartNamespaceDeclHandler }, |
| {"EndNamespaceDeclHandler", |
| pyxml_SetEndNamespaceDeclHandler, |
| (xmlhandler)my_EndNamespaceDeclHandler }, |
| {"CommentHandler", |
| (xmlhandlersetter)XML_SetCommentHandler, |
| (xmlhandler)my_CommentHandler}, |
| {"StartCdataSectionHandler", |
| pyxml_SetStartCdataSection, |
| (xmlhandler)my_StartCdataSectionHandler}, |
| {"EndCdataSectionHandler", |
| pyxml_SetEndCdataSection, |
| (xmlhandler)my_EndCdataSectionHandler}, |
| {"DefaultHandler", |
| (xmlhandlersetter)XML_SetDefaultHandler, |
| (xmlhandler)my_DefaultHandler}, |
| {"DefaultHandlerExpand", |
| (xmlhandlersetter)XML_SetDefaultHandlerExpand, |
| (xmlhandler)my_DefaultHandlerExpandHandler}, |
| {"NotStandaloneHandler", |
| (xmlhandlersetter)XML_SetNotStandaloneHandler, |
| (xmlhandler)my_NotStandaloneHandler}, |
| {"ExternalEntityRefHandler", |
| (xmlhandlersetter)XML_SetExternalEntityRefHandler, |
| (xmlhandler)my_ExternalEntityRefHandler }, |
| |
| {NULL, NULL, NULL} /* sentinel */ |
| }; |