summaryrefslogtreecommitdiffstats
path: root/libxslt/python
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-19 18:25:21 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-19 18:25:21 (GMT)
commitd72feaf69933b069cff3c0cb20a5f5f03ecba77b (patch)
treebf51d2814f4be65c850dba86dc2a5db0ad38bedf /libxslt/python
parent34be72f9ed749a5c013d3f7f47d810e8caf652cb (diff)
parent49e8fbec2420ef55b3246aabd89328b13530810c (diff)
downloadblt-d72feaf69933b069cff3c0cb20a5f5f03ecba77b.zip
blt-d72feaf69933b069cff3c0cb20a5f5f03ecba77b.tar.gz
blt-d72feaf69933b069cff3c0cb20a5f5f03ecba77b.tar.bz2
Merge commit '49e8fbec2420ef55b3246aabd89328b13530810c' as 'libxslt'
Diffstat (limited to 'libxslt/python')
-rw-r--r--libxslt/python/Makefile.am77
-rw-r--r--libxslt/python/TODO0
-rwxr-xr-xlibxslt/python/generator.py924
-rw-r--r--libxslt/python/libxml_wrap.h86
-rw-r--r--libxslt/python/libxsl.py129
-rw-r--r--libxslt/python/libxslt-python-api.xml234
-rw-r--r--libxslt/python/libxslt.c1206
-rw-r--r--libxslt/python/libxslt_wrap.h49
-rw-r--r--libxslt/python/libxsltclass.txt238
-rw-r--r--libxslt/python/tests/Makefile.am34
-rwxr-xr-xlibxslt/python/tests/basic.py29
-rwxr-xr-xlibxslt/python/tests/exslt.py56
-rw-r--r--libxslt/python/tests/extelem.py89
-rwxr-xr-xlibxslt/python/tests/extfunc.py66
-rwxr-xr-xlibxslt/python/tests/pyxsltproc.py298
-rw-r--r--libxslt/python/tests/test.xml1
-rw-r--r--libxslt/python/tests/test.xsl9
-rw-r--r--libxslt/python/types.c602
18 files changed, 4127 insertions, 0 deletions
diff --git a/libxslt/python/Makefile.am b/libxslt/python/Makefile.am
new file mode 100644
index 0000000..fa58b78
--- /dev/null
+++ b/libxslt/python/Makefile.am
@@ -0,0 +1,77 @@
+# Makefile for libxml2 python library
+AUTOMAKE_OPTIONS = 1.4 foreign
+
+SUBDIRS= . tests
+
+AM_CFLAGS = $(LIBXML_CFLAGS)
+
+DOCS_DIR = $(datadir)/doc/libxslt-python-$(LIBXSLT_VERSION)
+# libxsltclass.txt is generated
+DOCS = TODO
+
+EXTRA_DIST = \
+ libxslt.c \
+ types.c \
+ generator.py \
+ libxml_wrap.h \
+ libxslt_wrap.h \
+ libxsl.py \
+ libxslt-python-api.xml \
+ $(DOCS)
+
+libxsltmod_la_LDFLAGS = $(WIN32_EXTRA_LDFLAGS) -module -avoid-version
+
+if WITH_PYTHON
+mylibs = \
+ $(top_builddir)/libxslt/libxslt.la \
+ $(top_builddir)/libexslt/libexslt.la
+
+all-local: libxslt.py
+
+python_LTLIBRARIES = libxsltmod.la
+
+libxsltmod_la_CPPFLAGS = \
+ -I$(PYTHON_INCLUDES) \
+ -I$(top_srcdir)/libxslt \
+ -I$(top_srcdir) \
+ -I../libexslt
+libxsltmod_la_SOURCES = libxslt.c types.c
+nodist_libxsltmod_la_SOURCES = libxslt-py.c
+libxsltmod_la_LIBADD = $(mylibs) $(PYTHON_LIBS)
+
+libxslt.py: $(srcdir)/libxsl.py libxsltclass.py
+ cat $(srcdir)/libxsl.py libxsltclass.py > $@
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(pythondir)
+ $(INSTALL) -m 0644 libxslt.py $(DESTDIR)$(pythondir)
+ $(MKDIR_P) $(DESTDIR)$(DOCS_DIR)
+ @(for doc in $(DOCS) ; \
+ do $(INSTALL) -m 0644 $(srcdir)/$$doc $(DESTDIR)$(DOCS_DIR) ; done)
+
+uninstall-local:
+ rm -f $(DESTDIR)$(pythondir)/libxslt.py
+ rm -rf $(DESTDIR)$(DOCS_DIR)
+
+GENERATE = generator.py
+API_DESC = $(top_srcdir)/doc/libxslt-api.xml $(srcdir)/libxslt-python-api.xml
+GENERATED= libxsltclass.py \
+ libxslt-export.c \
+ libxslt-py.c \
+ libxslt-py.h \
+ libxsltclass.txt
+
+$(GENERATED): gen_prog
+
+gen_prog: $(srcdir)/$(GENERATE) $(API_DESC)
+ SRCDIR=$(srcdir) $(PYTHON) $(srcdir)/$(GENERATE)
+ touch gen_prog
+
+$(libxsltmod_la_OBJECTS): $(GENERATED)
+
+endif
+
+tests test: all
+ cd tests && $(MAKE) tests
+
+CLEANFILES= $(GENERATED) *.o libxslt.so *.pyc libxslt.py gen_prog
diff --git a/libxslt/python/TODO b/libxslt/python/TODO
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libxslt/python/TODO
diff --git a/libxslt/python/generator.py b/libxslt/python/generator.py
new file mode 100755
index 0000000..c13c877
--- /dev/null
+++ b/libxslt/python/generator.py
@@ -0,0 +1,924 @@
+#!/usr/bin/python -u
+#
+# generate python wrappers from the XML API description
+#
+
+functions = {}
+enums = {} # { enumType: { enumConstant: enumValue } }
+
+import string
+
+#######################################################################
+#
+# That part if purely the API acquisition phase from the
+# XML API description
+#
+#######################################################################
+import os
+import xml.sax
+
+debug = 0
+srcdir = os.getenv("SRCDIR", ".")
+
+def getparser():
+ # Attach parser to an unmarshalling object. return both objects.
+ target = docParser()
+ parser = xml.sax.make_parser()
+ parser.setContentHandler(target)
+ return parser, target
+
+class docParser(xml.sax.handler.ContentHandler):
+ def __init__(self):
+ self._methodname = None
+ self._data = []
+ self.in_function = 0
+
+ self.startElement = self.start
+ self.endElement = self.end
+ self.characters = self.data
+
+ def close(self):
+ if debug:
+ print "close"
+
+ def getmethodname(self):
+ return self._methodname
+
+ def data(self, text):
+ if debug:
+ print "data %s" % text
+ self._data.append(text)
+
+ def start(self, tag, attrs):
+ if debug:
+ print "start %s, %s" % (tag, attrs)
+ if tag == 'function':
+ self._data = []
+ self.in_function = 1
+ self.function = None
+ self.function_args = []
+ self.function_descr = None
+ self.function_return = None
+ self.function_file = None
+ if attrs.has_key('name'):
+ self.function = attrs['name']
+ if attrs.has_key('file'):
+ self.function_file = attrs['file']
+ elif tag == 'info':
+ self._data = []
+ elif tag == 'arg':
+ if self.in_function == 1:
+ self.function_arg_name = None
+ self.function_arg_type = None
+ self.function_arg_info = None
+ if attrs.has_key('name'):
+ self.function_arg_name = attrs['name']
+ if attrs.has_key('type'):
+ self.function_arg_type = attrs['type']
+ if attrs.has_key('info'):
+ self.function_arg_info = attrs['info']
+ elif tag == 'return':
+ if self.in_function == 1:
+ self.function_return_type = None
+ self.function_return_info = None
+ self.function_return_field = None
+ if attrs.has_key('type'):
+ self.function_return_type = attrs['type']
+ if attrs.has_key('info'):
+ self.function_return_info = attrs['info']
+ if attrs.has_key('field'):
+ self.function_return_field = attrs['field']
+ elif tag == 'enum':
+ enum(attrs['type'],attrs['name'],attrs['value'])
+
+
+
+ def end(self, tag):
+ if debug:
+ print "end %s" % tag
+ if tag == 'function':
+ if self.function != None:
+ function(self.function, self.function_descr,
+ self.function_return, self.function_args,
+ self.function_file)
+ self.in_function = 0
+ elif tag == 'arg':
+ if self.in_function == 1:
+ self.function_args.append([self.function_arg_name,
+ self.function_arg_type,
+ self.function_arg_info])
+ elif tag == 'return':
+ if self.in_function == 1:
+ self.function_return = [self.function_return_type,
+ self.function_return_info,
+ self.function_return_field]
+ elif tag == 'info':
+ str = ''
+ for c in self._data:
+ str = str + c
+ if self.in_function == 1:
+ self.function_descr = str
+
+
+def function(name, desc, ret, args, file):
+ functions[name] = (desc, ret, args, file)
+
+def enum(type, name, value):
+ if not enums.has_key(type):
+ enums[type] = {}
+ enums[type][name] = value
+
+#######################################################################
+#
+# Some filtering rukes to drop functions/types which should not
+# be exposed as-is on the Python interface
+#
+#######################################################################
+
+skipped_modules = {
+ 'xmlmemory': None,
+ 'DOCBparser': None,
+ 'SAX': None,
+ 'hash': None,
+ 'list': None,
+ 'threads': None,
+ 'xpointer': None,
+ 'transform': None,
+}
+skipped_types = {
+ 'int *': "usually a return type",
+ 'xmlSAXHandlerPtr': "not the proper interface for SAX",
+ 'htmlSAXHandlerPtr': "not the proper interface for SAX",
+ 'xmlRMutexPtr': "thread specific, skipped",
+ 'xmlMutexPtr': "thread specific, skipped",
+ 'xmlGlobalStatePtr': "thread specific, skipped",
+ 'xmlListPtr': "internal representation not suitable for python",
+ 'xmlBufferPtr': "internal representation not suitable for python",
+ 'FILE *': None,
+}
+
+#######################################################################
+#
+# Table of remapping to/from the python type or class to the C
+# counterpart.
+#
+#######################################################################
+
+py_types = {
+ 'void': (None, None, None, None, None),
+ 'int': ('i', None, "int", "int", "libxml_"),
+ 'long': ('l', None, "long", "long", "libxml_"),
+ 'double': ('d', None, "double", "double", "libxml_"),
+ 'unsigned int': ('i', None, "int", "int", "libxml_"),
+ 'xmlChar': ('c', None, "int", "int", "libxml_"),
+ 'unsigned char *': ('z', None, "charPtr", "char *", "libxml_"),
+ 'char *': ('z', None, "charPtr", "char *", "libxml_"),
+ 'const char *': ('z', None, "charPtrConst", "const char *", "libxml_"),
+ 'xmlChar *': ('z', None, "xmlCharPtr", "xmlChar *", "libxml_"),
+ 'const xmlChar *': ('z', None, "xmlCharPtrConst", "const xmlChar *", "libxml_"),
+ 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
+ 'const xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
+ 'xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
+ 'const xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
+ 'xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
+ 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
+ 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
+ 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
+ 'xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
+ 'const xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
+ 'xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
+ 'const xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
+ 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
+ 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
+ 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxml_"),
+ 'xmlXPathParserContextPtr': ('O', "xmlXPathParserContext", "xmlXPathParserContextPtr", "xmlXPathParserContextPtr", "libxml_"),
+ 'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
+ 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
+ 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
+ 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
+ 'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"),
+ 'FILE *': ('O', "File", "FILEPtr", "FILE *", "libxml_"),
+ 'xsltTransformContextPtr': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
+ 'xsltTransformContext *': ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
+ 'xsltStylePreCompPtr': ('O', "compiledStyle", "xsltStylePreCompPtr", "xsltStylePreCompPtr", "libxslt_"),
+ 'xsltStylePreComp *': ('O', "compiledStyle", "xsltStylePreCompPtr", "xsltStylePreCompPtr", "libxslt_"),
+ 'xsltStylesheetPtr': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
+ 'xsltStylesheet *': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
+ 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxslt_"),
+}
+
+py_return_types = {
+ 'xmlXPathObjectPtr': ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr", "libxml_"),
+}
+
+unknown_types = {}
+
+#######################################################################
+#
+# This part writes the C <-> Python stubs libxslt-py.[ch] and
+# the table libxslt-export.c to add when registrering the Python module
+#
+#######################################################################
+
+def skip_function(name):
+ if name[0:12] == "xmlXPathWrap":
+ return 1
+ if name == "xsltMatchPattern":
+ return 1
+# if name[0:11] == "xmlXPathNew":
+# return 1
+ return 0
+
+def print_function_wrapper(name, output, export, include):
+ global py_types
+ global unknown_types
+ global functions
+ global skipped_modules
+
+ try:
+ (desc, ret, args, file) = functions[name]
+ except:
+ print "failed to get function %s infos"
+ return
+
+ if skipped_modules.has_key(file):
+ return 0
+ if skip_function(name) == 1:
+ return 0
+
+ c_call = ""
+ format=""
+ format_args=""
+ c_args=""
+ c_return=""
+ c_convert=""
+ for arg in args:
+ # This should be correct
+ if arg[1][0:6] == "const ":
+ arg[1] = arg[1][6:]
+ c_args = c_args + " %s %s;\n" % (arg[1], arg[0])
+ if py_types.has_key(arg[1]):
+ (f, t, n, c, p) = py_types[arg[1]]
+ if f != None:
+ format = format + f
+ if t != None:
+ format_args = format_args + ", &pyobj_%s" % (arg[0])
+ c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0])
+ c_convert = c_convert + \
+ " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
+ arg[1], t, arg[0])
+ else:
+ format_args = format_args + ", &%s" % (arg[0])
+ if c_call != "":
+ c_call = c_call + ", "
+ c_call = c_call + "%s" % (arg[0])
+ else:
+ if skipped_types.has_key(arg[1]):
+ return 0
+ if unknown_types.has_key(arg[1]):
+ lst = unknown_types[arg[1]]
+ lst.append(name)
+ else:
+ unknown_types[arg[1]] = [name]
+ return -1
+ if format != "":
+ format = format + ":%s" % (name)
+
+ if ret[0] == 'void':
+ if file == "python_accessor":
+ if args[1][1] == "char *" or args[1][1] == "xmlChar *":
+ c_call = "\n if (%s->%s != NULL) xmlFree(%s->%s);\n" % (
+ args[0][0], args[1][0], args[0][0], args[1][0])
+ c_call = c_call + " %s->%s = xmlStrdup((const xmlChar *)%s);\n" % (args[0][0],
+ args[1][0], args[1][0])
+ else:
+ c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0],
+ args[1][0])
+ else:
+ c_call = "\n %s(%s);\n" % (name, c_call)
+ ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n"
+ elif py_types.has_key(ret[0]):
+ (f, t, n, c, p) = py_types[ret[0]]
+ c_return = " %s c_retval;\n" % (ret[0])
+ if file == "python_accessor" and ret[2] != None:
+ c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2])
+ else:
+ c_call = "\n c_retval = %s(%s);\n" % (name, c_call)
+ ret_convert = " py_retval = %s%sWrap((%s) c_retval);\n" % (p,n,c)
+ ret_convert = ret_convert + " return(py_retval);\n"
+ elif py_return_types.has_key(ret[0]):
+ (f, t, n, c, p) = py_return_types[ret[0]]
+ c_return = " %s c_retval;\n" % (ret[0])
+ if file == "python_accessor" and ret[2] != None:
+ c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2])
+ else:
+ c_call = "\n c_retval = %s(%s);\n" % (name, c_call)
+ ret_convert = " py_retval = %s%sWrap((%s) c_retval);\n" % (p,n,c)
+ ret_convert = ret_convert + " return(py_retval);\n"
+ else:
+ if skipped_types.has_key(ret[0]):
+ return 0
+ if unknown_types.has_key(ret[0]):
+ lst = unknown_types[ret[0]]
+ lst.append(name)
+ else:
+ unknown_types[ret[0]] = [name]
+ return -1
+
+ include.write("PyObject * ")
+ include.write("libxslt_%s(PyObject *self, PyObject *args);\n" % (name))
+
+ export.write(" { (char *)\"%s\", libxslt_%s, METH_VARARGS, NULL },\n" % (name, name))
+
+ if file == "python":
+ # Those have been manually generated
+ return 1
+ if file == "python_accessor" and ret[0] != "void" and ret[2] == None:
+ # Those have been manually generated
+ return 1
+
+ output.write("PyObject *\n")
+ output.write("libxslt_%s(PyObject *self ATTRIBUTE_UNUSED," % (name))
+ output.write(" PyObject *args")
+ if format == "":
+ output.write(" ATTRIBUTE_UNUSED")
+ output.write(") {\n")
+ if ret[0] != 'void':
+ output.write(" PyObject *py_retval;\n")
+ if c_return != "":
+ output.write(c_return)
+ if c_args != "":
+ output.write(c_args)
+ if format != "":
+ output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" %
+ (format, format_args))
+ output.write(" return(NULL);\n")
+ if c_convert != "":
+ output.write(c_convert)
+
+ output.write(c_call)
+ output.write(ret_convert)
+ output.write("}\n\n")
+ return 1
+
+def buildStubs():
+ global py_types
+ global py_return_types
+ global unknown_types
+
+ try:
+ f = open("%s/libxslt-api.xml" % srcdir)
+ data = f.read()
+ (parser, target) = getparser()
+ parser.feed(data)
+ parser.close()
+ except IOError, msg:
+ try:
+ f = open("%s/../doc/libxslt-api.xml" % srcdir)
+ data = f.read()
+ (parser, target) = getparser()
+ parser.feed(data)
+ parser.close()
+ except IOError, msg:
+ print "../doc/libxslt-api.xml", ":", msg
+
+ n = len(functions.keys())
+ print "Found %d functions in libxslt-api.xml" % (n)
+
+ py_types['pythonObject'] = ('O', "pythonObject", "pythonObject",
+ "pythonObject", "libxml_")
+ try:
+ f = open("%s/libxslt-python-api.xml" % srcdir)
+ data = f.read()
+ (parser, target) = getparser()
+ parser.feed(data)
+ parser.close()
+ except IOError, msg:
+ print "libxslt-python-api.xml", ":", msg
+
+
+ print "Found %d functions in libxslt-python-api.xml" % (
+ len(functions.keys()) - n)
+ nb_wrap = 0
+ failed = 0
+ skipped = 0
+
+ include = open("libxslt-py.h", "w")
+ include.write("/* Generated */\n\n")
+ export = open("libxslt-export.c", "w")
+ export.write("/* Generated */\n\n")
+ wrapper = open("libxslt-py.c", "w")
+ wrapper.write("/* Generated */\n\n")
+# wrapper.write("#include \"config.h\"\n")
+ wrapper.write("#include <libxslt/xsltconfig.h>\n")
+ wrapper.write("#include \"libxslt_wrap.h\"\n")
+ wrapper.write("#include \"libxslt-py.h\"\n\n")
+ for function in functions.keys():
+ ret = print_function_wrapper(function, wrapper, export, include)
+ if ret < 0:
+ failed = failed + 1
+ del functions[function]
+ if ret == 0:
+ skipped = skipped + 1
+ del functions[function]
+ if ret == 1:
+ nb_wrap = nb_wrap + 1
+ include.close()
+ export.close()
+ wrapper.close()
+
+ print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
+ failed, skipped)
+ print "Missing type converters:"
+ for type in unknown_types.keys():
+ print "%s:%d " % (type, len(unknown_types[type])),
+ print
+
+#######################################################################
+#
+# This part writes part of the Python front-end classes based on
+# mapping rules between types and classes and also based on function
+# renaming to get consistent function names at the Python level
+#
+#######################################################################
+
+#
+# The type automatically remapped to generated classes
+#
+libxml2_classes_type = {
+ "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
+ "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
+ "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
+ "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
+ "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
+ "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
+ "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
+ "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
+ "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
+ "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
+ "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
+ "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
+ "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
+ "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
+ "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
+ "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
+ "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
+ "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
+ "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
+ "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
+ "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"),
+}
+
+classes_type = {
+ "xsltTransformContextPtr": ("._o", "transformCtxt(_obj=%s)", "transformCtxt"),
+ "xsltTransformContext *": ("._o", "transformCtxt(_obj=%s)", "transformCtxt"),
+ "xsltStylesheetPtr": ("._o", "stylesheet(_obj=%s)", "stylesheet"),
+ "xsltStylesheet *": ("._o", "stylesheet(_obj=%s)", "stylesheet"),
+ "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
+ "xmlXPathContext *": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
+ "xmlXPathParserContextPtr": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"),
+ "xmlXPathParserContext *": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"),
+}
+
+converter_type = {
+ "xmlXPathObjectPtr": "libxml2.xpathObjectRet(%s)",
+}
+
+primary_classes = ["xpathParserContext", "xpathContext", "transformCtxt", "stylesheet"]
+
+classes_ancestor = {
+ "xpathContext" : "libxml2.xpathContext",
+ "xpathParserContext" : "libxml2.xpathParserContext",
+ "transformCtxt": "transformCtxtBase",
+ "stylesheet": "stylesheetBase",
+}
+classes_destructors = {
+ "xpathContext" : "pass"
+}
+
+function_classes = {}
+ctypes = []
+classes_list = []
+
+
+def nameFixup(name, classe, type, file):
+ listname = classe + "List"
+ ll = len(listname)
+ l = len(classe)
+ if name[0:l] == listname:
+ func = name[l:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:12] == "xmlParserGet" and file == "python_accessor":
+ func = name[12:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:12] == "xmlParserSet" and file == "python_accessor":
+ func = name[12:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:10] == "xmlNodeGet" and file == "python_accessor":
+ func = name[10:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:18] == "xsltXPathParserGet" and file == "python_accessor":
+ func = name[18:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:12] == "xsltXPathGet" and file == "python_accessor":
+ func = name[12:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:16] == "xsltTransformGet" and file == "python_accessor":
+ func = name[16:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:16] == "xsltTransformSet" and file == "python_accessor":
+ func = name[13:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:17] == "xsltStylesheetGet" and file == "python_accessor":
+ func = name[17:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:17] == "xsltStylesheetSet" and file == "python_accessor":
+ func = name[14:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:l] == classe:
+ func = name[l:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:7] == "libxml_":
+ func = name[7:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:8] == "libxslt_":
+ func = name[8:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:6] == "xmlGet":
+ func = name[6:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:3] == "xml":
+ func = name[3:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:7] == "xsltGet":
+ func = name[7:]
+ func = string.lower(func[0:1]) + func[1:]
+ elif name[0:4] == "xslt":
+ func = name[4:]
+ func = string.lower(func[0:1]) + func[1:]
+ else:
+ func = name
+ if func[0:5] == "xPath":
+ func = "xpath" + func[5:]
+ elif func[0:4] == "xPtr":
+ func = "xpointer" + func[4:]
+ elif func[0:8] == "xInclude":
+ func = "xinclude" + func[8:]
+ elif func[0:2] == "iD":
+ func = "ID" + func[2:]
+ elif func[0:3] == "uRI":
+ func = "URI" + func[3:]
+ elif func[0:4] == "uTF8":
+ func = "UTF8" + func[4:]
+ return func
+
+def functionCompare(info1, info2):
+ (index1, func1, name1, ret1, args1, file1) = info1
+ (index2, func2, name2, ret2, args2, file2) = info2
+ if file1 == file2:
+ if func1 < func2:
+ return -1
+ if func1 > func2:
+ return 1
+ if file1 == "python_accessor":
+ return -1
+ if file2 == "python_accessor":
+ return 1
+ if file1 < file2:
+ return -1
+ if file1 > file2:
+ return 1
+ return 0
+
+def writeDoc(name, args, indent, output):
+ if functions[name][0] == None or functions[name][0] == "":
+ return
+ val = functions[name][0]
+ val = string.replace(val, "NULL", "None")
+ output.write(indent)
+ output.write('"""')
+ while len(val) > 60:
+ if val[0] == " ":
+ val = val[1:]
+ continue
+ str = val[0:60]
+ i = string.rfind(str, " ")
+ if i < 0:
+ i = 60
+ str = val[0:i]
+ val = val[i:]
+ output.write(str)
+ output.write('\n ')
+ output.write(indent)
+ output.write(val)
+ output.write('"""\n')
+
+def buildWrappers():
+ global ctypes
+ global py_types
+ global py_return_types
+ global unknown_types
+ global functions
+ global function_classes
+ global libxml2_classes_type
+ global classes_type
+ global classes_list
+ global converter_type
+ global primary_classes
+ global converter_type
+ global classes_ancestor
+ global converter_type
+ global primary_classes
+ global classes_ancestor
+ global classes_destructors
+
+ function_classes["None"] = []
+ for type in classes_type.keys():
+ function_classes[classes_type[type][2]] = []
+
+ #
+ # Build the list of C types to look for ordered to start with
+ # primary classes
+ #
+ ctypes_processed = {}
+ classes_processed = {}
+ for classe in primary_classes:
+ classes_list.append(classe)
+ classes_processed[classe] = ()
+ for type in classes_type.keys():
+ tinfo = classes_type[type]
+ if tinfo[2] == classe:
+ ctypes.append(type)
+ ctypes_processed[type] = ()
+ for type in classes_type.keys():
+ if ctypes_processed.has_key(type):
+ continue
+ tinfo = classes_type[type]
+ if not classes_processed.has_key(tinfo[2]):
+ classes_list.append(tinfo[2])
+ classes_processed[tinfo[2]] = ()
+
+ ctypes.append(type)
+ ctypes_processed[type] = ()
+
+ for name in functions.keys():
+ found = 0
+ (desc, ret, args, file) = functions[name]
+ for type in ctypes:
+ classe = classes_type[type][2]
+
+ if name[0:4] == "xslt" and len(args) >= 1 and args[0][1] == type:
+ found = 1
+ func = nameFixup(name, classe, type, file)
+ info = (0, func, name, ret, args, file)
+ function_classes[classe].append(info)
+ elif name[0:4] == "xslt" and len(args) >= 2 and args[1][1] == type:
+ found = 1
+ func = nameFixup(name, classe, type, file)
+ info = (1, func, name, ret, args, file)
+ function_classes[classe].append(info)
+ elif name[0:4] == "xslt" and len(args) >= 3 and args[2][1] == type:
+ found = 1
+ func = nameFixup(name, classe, type, file)
+ info = (2, func, name, ret, args, file)
+ function_classes[classe].append(info)
+ if found == 1:
+ continue
+ if name[0:8] == "xmlXPath":
+ continue
+ if name[0:6] == "xmlStr":
+ continue
+ if name[0:10] == "xmlCharStr":
+ continue
+ func = nameFixup(name, "None", file, file)
+ info = (0, func, name, ret, args, file)
+ function_classes['None'].append(info)
+
+ classes = open("libxsltclass.py", "w")
+ txt = open("libxsltclass.txt", "w")
+ txt.write(" Generated Classes for libxslt-python\n\n")
+
+ txt.write("#\n# Global functions of the module\n#\n\n")
+ if function_classes.has_key("None"):
+ flist = function_classes["None"]
+ flist.sort(functionCompare)
+ oldfile = ""
+ for info in flist:
+ (index, func, name, ret, args, file) = info
+ if file != oldfile:
+ classes.write("#\n# Functions from module %s\n#\n\n" % file)
+ txt.write("\n# functions from module %s\n" % file)
+ oldfile = file
+ classes.write("def %s(" % func)
+ txt.write("%s()\n" % func)
+ n = 0
+ for arg in args:
+ if n != 0:
+ classes.write(", ")
+ classes.write("%s" % arg[0])
+ n = n + 1
+ classes.write("):\n")
+ writeDoc(name, args, ' ', classes)
+
+ for arg in args:
+ if classes_type.has_key(arg[1]):
+ classes.write(" if %s == None: %s__o = None\n" %
+ (arg[0], arg[0]))
+ classes.write(" else: %s__o = %s%s\n" %
+ (arg[0], arg[0], classes_type[arg[1]][0]))
+ elif libxml2_classes_type.has_key(arg[1]):
+ classes.write(" if %s == None: %s__o = None\n" %
+ (arg[0], arg[0]))
+ classes.write(" else: %s__o = %s%s\n" %
+ (arg[0], arg[0], libxml2_classes_type[arg[1]][0]))
+ if ret[0] != "void":
+ classes.write(" ret = ")
+ else:
+ classes.write(" ")
+ classes.write("libxsltmod.%s(" % name)
+ n = 0
+ for arg in args:
+ if n != 0:
+ classes.write(", ")
+ classes.write("%s" % arg[0])
+ if classes_type.has_key(arg[1]):
+ classes.write("__o")
+ if libxml2_classes_type.has_key(arg[1]):
+ classes.write("__o")
+ n = n + 1
+ classes.write(")\n")
+ if ret[0] != "void":
+ if classes_type.has_key(ret[0]):
+ classes.write(" if ret == None: return None\n")
+ classes.write(" return ")
+ classes.write(classes_type[ret[0]][1] % ("ret"))
+ classes.write("\n")
+ elif libxml2_classes_type.has_key(ret[0]):
+ classes.write(" if ret == None: return None\n")
+ classes.write(" return libxml2.")
+ classes.write(libxml2_classes_type[ret[0]][1] % ("ret"))
+ classes.write("\n")
+ else:
+ classes.write(" return ret\n")
+ classes.write("\n")
+
+ txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
+ for classname in classes_list:
+ if classname == "None":
+ pass
+ else:
+ if classes_ancestor.has_key(classname):
+ txt.write("\n\nClass %s(%s)\n" % (classname,
+ classes_ancestor[classname]))
+ classes.write("class %s(%s):\n" % (classname,
+ classes_ancestor[classname]))
+ classes.write(" def __init__(self, _obj=None):\n")
+ classes.write(" self._o = None\n")
+ classes.write(" %s.__init__(self, _obj=_obj)\n\n" % (
+ classes_ancestor[classname]))
+ if classes_ancestor[classname] == "xmlCore" or \
+ classes_ancestor[classname] == "xmlNode":
+ classes.write(" def __repr__(self):\n")
+ format = "%s:%%s" % (classname)
+ classes.write(" return \"%s\" %% (self.name)\n\n" % (
+ format))
+ else:
+ txt.write("Class %s()\n" % (classname))
+ classes.write("class %s:\n" % (classname))
+ classes.write(" def __init__(self, _obj=None):\n")
+ classes.write(" if _obj != None:self._o = _obj;return\n")
+ classes.write(" self._o = None\n\n")
+ if classes_destructors.has_key(classname):
+ classes.write(" def __del__(self):\n")
+ if classes_destructors[classname] == "pass":
+ classes.write(" pass\n")
+ else:
+ classes.write(" if self._o != None:\n")
+ classes.write(" libxsltmod.%s(self._o)\n" %
+ classes_destructors[classname])
+ classes.write(" self._o = None\n\n")
+ flist = function_classes[classname]
+ flist.sort(functionCompare)
+ oldfile = ""
+ for info in flist:
+ (index, func, name, ret, args, file) = info
+ if file != oldfile:
+ if file == "python_accessor":
+ classes.write(" # accessors for %s\n" % (classname))
+ txt.write(" # accessors\n")
+ else:
+ classes.write(" #\n")
+ classes.write(" # %s functions from module %s\n" % (
+ classname, file))
+ txt.write("\n # functions from module %s\n" % file)
+ classes.write(" #\n\n")
+ oldfile = file
+ classes.write(" def %s(self" % func)
+ txt.write(" %s()\n" % func)
+ n = 0
+ for arg in args:
+ if n != index:
+ classes.write(", %s" % arg[0])
+ n = n + 1
+ classes.write("):\n")
+ writeDoc(name, args, ' ', classes)
+ n = 0
+ for arg in args:
+ if classes_type.has_key(arg[1]):
+ if n != index:
+ classes.write(" if %s == None: %s__o = None\n" %
+ (arg[0], arg[0]))
+ classes.write(" else: %s__o = %s%s\n" %
+ (arg[0], arg[0], classes_type[arg[1]][0]))
+ elif libxml2_classes_type.has_key(arg[1]):
+ classes.write(" if %s == None: %s__o = None\n" %
+ (arg[0], arg[0]))
+ classes.write(" else: %s__o = %s%s\n" %
+ (arg[0], arg[0],
+ libxml2_classes_type[arg[1]][0]))
+ n = n + 1
+ if ret[0] != "void":
+ classes.write(" ret = ")
+ else:
+ classes.write(" ")
+ classes.write("libxsltmod.%s(" % name)
+ n = 0
+ for arg in args:
+ if n != 0:
+ classes.write(", ")
+ if n != index:
+ classes.write("%s" % arg[0])
+ if classes_type.has_key(arg[1]):
+ classes.write("__o")
+ elif libxml2_classes_type.has_key(arg[1]):
+ classes.write("__o")
+ else:
+ classes.write("self")
+ if classes_type.has_key(arg[1]):
+ classes.write(classes_type[arg[1]][0])
+ elif libxml2_classes_type.has_key(arg[1]):
+ classes.write(libxml2_classes_type[arg[1]][0])
+ n = n + 1
+ classes.write(")\n")
+ if ret[0] != "void":
+ if classes_type.has_key(ret[0]):
+ classes.write(" if ret == None: return None\n")
+ classes.write(" return ")
+ classes.write(classes_type[ret[0]][1] % ("ret"))
+ classes.write("\n")
+ elif libxml2_classes_type.has_key(ret[0]):
+ classes.write(" if ret == None: return None\n")
+ classes.write(" return libxml2.")
+ classes.write(libxml2_classes_type[ret[0]][1] % ("ret"))
+ classes.write("\n")
+ elif converter_type.has_key(ret[0]):
+ classes.write(" if ret == None: return None\n")
+ classes.write(" return ")
+ classes.write(converter_type[ret[0]] % ("ret"))
+ classes.write("\n")
+ else:
+ classes.write(" return ret\n")
+ classes.write("\n")
+
+ #
+ # Generate enum constants
+ #
+ for type,enum in enums.items():
+ classes.write("# %s\n" % type)
+ items = enum.items()
+ items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1])))
+ for name,value in items:
+ classes.write("%s = %s\n" % (name,value))
+ classes.write("\n");
+
+ txt.close()
+ classes.close()
+
+buildStubs()
+buildWrappers()
diff --git a/libxslt/python/libxml_wrap.h b/libxslt/python/libxml_wrap.h
new file mode 100644
index 0000000..53777d9
--- /dev/null
+++ b/libxslt/python/libxml_wrap.h
@@ -0,0 +1,86 @@
+#include <Python.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/catalog.h>
+#include <libxml/threads.h>
+#include <libxml/nanoftp.h>
+#include <libxml/nanohttp.h>
+#include <libxml/uri.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xinclude.h>
+#include <libxml/xpointer.h>
+
+#define PyxmlNode_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlNode_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlNodePtr obj;
+} PyxmlNode_Object;
+
+#define PyxmlXPathContext_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlXPathContext_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlXPathContextPtr obj;
+} PyxmlXPathContext_Object;
+
+#define PyxmlXPathParserContext_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyxmlXPathParserContext_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlXPathParserContextPtr obj;
+} PyxmlXPathParserContext_Object;
+
+#define PyparserCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PyparserCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlParserCtxtPtr obj;
+} PyparserCtxt_Object;
+
+#define Pycatalog_Get(v) (((v) == Py_None) ? NULL : \
+ (((Pycatalog_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xmlCatalogPtr obj;
+} Pycatalog_Object;
+
+#define PyFile_Get(v) (((v) == Py_None) ? NULL : \
+ (PyFile_Check(v) ? (PyFile_AsFile(v)) : stdout))
+
+PyObject * libxml_intWrap(int val);
+PyObject * libxml_longWrap(long val);
+PyObject * libxml_xmlCharPtrWrap(xmlChar *str);
+PyObject * libxml_constxmlCharPtrWrap(const xmlChar *str);
+PyObject * libxml_charPtrWrap(char *str);
+PyObject * libxml_constcharPtrWrap(const char *str);
+PyObject * libxml_charPtrConstWrap(const char *str);
+PyObject * libxml_xmlCharPtrConstWrap(const xmlChar *str);
+PyObject * libxml_xmlDocPtrWrap(xmlDocPtr doc);
+PyObject * libxml_xmlNodePtrWrap(xmlNodePtr node);
+PyObject * libxml_xmlAttrPtrWrap(xmlAttrPtr attr);
+PyObject * libxml_xmlNsPtrWrap(xmlNsPtr ns);
+PyObject * libxml_xmlAttributePtrWrap(xmlAttributePtr ns);
+PyObject * libxml_xmlElementPtrWrap(xmlElementPtr ns);
+PyObject * libxml_doubleWrap(double val);
+PyObject * libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt);
+PyObject * libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt);
+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);
+PyObject * libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp);
+
+xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
diff --git a/libxslt/python/libxsl.py b/libxslt/python/libxsl.py
new file mode 100644
index 0000000..e8e86e4
--- /dev/null
+++ b/libxslt/python/libxsl.py
@@ -0,0 +1,129 @@
+#
+# Both libxml2mod and libxsltmod have a dependancy on libxml2.so
+# and they should share the same module, try to convince the python
+# loader to work in that mode if feasible
+#
+import sys
+if not hasattr(sys,'getdlopenflags'):
+ import libxml2mod
+ import libxsltmod
+ import libxml2
+else:
+ try:
+ from dl import RTLD_GLOBAL, RTLD_NOW
+ except ImportError:
+ RTLD_GLOBAL = -1
+ RTLD_NOW = -1
+ try:
+ import os
+ osname = os.uname()[0]
+ if osname == 'Linux' or osname == 'SunOS':
+ RTLD_GLOBAL = 0x00100
+ RTLD_NOW = 0x00002
+ elif osname == 'Darwin':
+ RTLD_GLOBAL = 0x8
+ RTLD_NOW = 0x2
+ #
+ # is there a better method ?
+ #
+# else:
+# print "libxslt could not guess RTLD_GLOBAL and RTLD_NOW " + \
+# "on this platform: %s" % (osname)
+ except:
+ pass
+# print "libxslt could not guess RTLD_GLOBAL and RTLD_NOW " + \
+# "on this platform: %s" % (osname)
+ except:
+ RTLD_GLOBAL = -1
+ RTLD_NOW = -1
+
+ if RTLD_GLOBAL != -1 and RTLD_NOW != -1:
+ try:
+ flags = sys.getdlopenflags()
+ sys.setdlopenflags(RTLD_GLOBAL | RTLD_NOW)
+ try:
+ import libxml2mod
+ import libxsltmod
+ import libxml2
+ finally:
+ sys.setdlopenflags(flags)
+ except:
+ import libxml2mod
+ import libxsltmod
+ import libxml2
+ else:
+ import libxml2mod
+ import libxsltmod
+ import libxml2
+
+
+class transformCtxtBase:
+ def __init__(self, _obj=None):
+ if _obj != None:
+ self._o = _obj;
+ return
+ self._o = None
+ def __hash__(self):
+ v = libxsltmod.xsltGetTransformContextHashCode(self._o)
+ return v
+ def __eq__(self, other):
+ if other == None:
+ return 0
+ v = libxsltmod.xsltCompareTransformContextsEqual(self._o, other._o)
+ return v
+
+class stylesheetBase:
+ def __init__(self, _obj=None):
+ if _obj != None:
+ self._o = _obj;
+ return
+ self._o = None
+ def __hash__(self):
+ v = libxsltmod.xsltGetStylesheetHashCode(self._o)
+ return v
+ def __eq__(self, other):
+ if other == None:
+ return 0
+ v = libxsltmod.xsltCompareStylesheetsEqual(self._o, other._o)
+ return v
+
+class extensionModule:
+ def _styleInit(self, style, URI):
+ return self.styleInit(stylesheet(_obj=style), URI)
+
+ def _styleShutdown(self, style, URI, data):
+ return self.styleShutdown(stylesheet(_obj=style), URI, data)
+
+ def _ctxtInit(self, ctxt, URI):
+ return self.ctxtInit(transformCtxt(_obj=ctxt), URI)
+
+ def _ctxtShutdown(self, ctxt, URI, data):
+ return self.ctxtShutdown(transformCtxt(_obj=ctxt), URI, data)
+
+ def styleInit(self, style, URI):
+ """Callback function when used in a newly compiled stylesheet,
+ the return value is passed in subsequent calls"""
+ pass
+
+ def styleShutdown(self, style, URI, data):
+ """Callback function when a stylesheet using it is destroyed"""
+ pass
+
+ def ctxtInit(self, ctxt, URI):
+ """Callback function when used in a new transformation process,
+ the return value is passed in subsequent calls"""
+ pass
+
+ def ctxtShutdown(self, ctxt, URI, data):
+ """Callback function when a transformation using it finishes"""
+ pass
+
+def cleanup():
+ """Cleanup all libxslt and libxml2 memory allocated"""
+ libxsltmod.xsltPythonCleanup()
+ libxml2.cleanupParser()
+
+#
+# Everything below this point is automatically generated
+#
+
diff --git a/libxslt/python/libxslt-python-api.xml b/libxslt/python/libxslt-python-api.xml
new file mode 100644
index 0000000..49491f3
--- /dev/null
+++ b/libxslt/python/libxslt-python-api.xml
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<api name='libxslt-python'>
+ <files>
+ <file name='python'>
+ </file>
+ </files>
+ <symbols>
+ <function name='xsltSaveResultToString' file='python'>
+ <info>Have the stylesheet serialize the result of a transformation to a python string</info>
+ <return type='char *' info='The result document as a string' />
+ <arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ <arg name='result' type='xmlDocPtr' info='The result document'/>
+ </function>
+ <function name='xsltSetLoaderFunc' file='python'>
+ <info>Set the function for controlling document loading</info>
+ <return type='long' info='0 for failure or 1 for success'/>
+ <arg name='loader' type='pythonObject' info='the loader function; should take: string URI, xsltParserContext, context, type; when type == 1 the context is a stylesheet, when type == 0 the context is a transformCtxt'/>
+ </function>
+ <function name='xsltGetLoaderFunc' file='python'>
+ <info>Get the function for controlling document loading</info>
+ <return type='pythonObject *' info='the function'/>
+ </function>
+ <function name='xsltNewTransformContext' file='python'>
+ <info>Create a new XSLT TransformContext</info>
+ <return type='xsltTransformContextPtr' info='an xslt TransformContext'/>
+ <arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ <arg name='doc' type='xmlDocPtr' info='the input document'/>
+ </function>
+ <function name='xsltFreeTransformContext' file='python'>
+ <info>Free up an existing XSLT TransformContext</info>
+ <return type='void' info='None'/>
+ <arg name='transformCtxt' type='xsltTransformContextPtr' info='an existing tranformCtxt'/>
+ </function>
+ <function name='xsltGetTransformContextHashCode' file='python'>
+ <info>Get the hash code of the transformContext</info>
+ <return type='int' info='the hash code' />
+ <arg name='transformCtxt' type='xsltTransformContextPtr' info='a parsed XSLT transformContext'/>
+ </function>
+ <function name='xsltGetStylesheetHashCode' file='python'>
+ <info>Get the hash code of the stylesheet</info>
+ <return type='int' info='the hash code' />
+ <arg name='stylesheet' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ </function>
+ <function name='xsltCompareTransformContextsEqual' file='python'>
+ <info>Compare one transformCtxt with another</info>
+ <return type='int' info='1 in case of success, 0 or -1 in error' />
+ <arg name='transformCtxt' type='xsltTransformContextPtr' info='a parsed XSLT transformContext'/>
+ <arg name='other' type='xsltTransformContextPtr' info='a parsed XSLT transformContext'/>
+ </function>
+ <function name='xsltCompareStylesheetsEqual' file='python'>
+ <info>Compare one stylesheet with another</info>
+ <return type='int' info='1 in case of success, 0 or -1 in error' />
+ <arg name='stylesheet' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ <arg name='other' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ </function>
+ <function name='xsltApplyStylesheetUser' file='python'>
+ <info>Apply the stylesheet to the document</info>
+ <return type='xmlDocPtr' info="the result document or NULL in case of error"/>
+ <arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ <arg name='doc' type='xmlDocPtr' info='a parsed XML document'/>
+ <arg name='params' type='pythonObject' info='the parameters dictionary'/>
+ <arg name='transformCtxt' type='xsltTransformContextPtr' info='transformation context'/>
+ </function>
+ <function name='xsltApplyStylesheet' file='python'>
+ <info>Apply the stylesheet to the document</info>
+ <return type='xmlDocPtr' info="the result document or NULL in case of error"/>
+ <arg name='style' type='xsltStylesheetPtr' info='a parsed XSLT stylesheet'/>
+ <arg name='doc' type='xmlDocPtr' info='a parsed XML document'/>
+ <arg name='params' type='pythonObject' info='the parameters dictionary'/>
+ </function>
+ <function name='xsltRegisterErrorHandler' file='python'>
+ <info>Register a Python written function to for error reporting. The function is called back as f(ctx, error).</info>
+ <return type='int' info="1 in case of success, 0 or -1 in case of error"/>
+ <arg name='f' type='pythonObject' info='the python function'/>
+ <arg name='ctx' type='pythonObject' info='a context for the callback'/>
+ </function>
+ <function name='xsltRegisterExtModuleElement' file='python'>
+ <info>Register a Python written element to the XSLT engine</info>
+ <return type='int' info="0 in case of success, -1 in case of error"/>
+ <arg name='name' type='xmlChar *' info='the element name'/>
+ <arg name='URI' type='xmlChar *' info='the namespace or NULL'/>
+ <arg name='precompile' type='pythonObject' info='method called when stylesheet is compiled'/>
+ <arg name='transform' type='pythonObject' info='method called during transform, must not modify stylesheet'/>
+ </function>
+ <function name='xsltRegisterExtModuleFunction' file='python'>
+ <info>Register a Python written function to the XSLT engine</info>
+ <return type='int' info="0 in case of success, -1 in case of error"/>
+ <arg name='name' type='xmlChar *' info='the function name'/>
+ <arg name='URI' type='xmlChar *' info='the namespace or NULL'/>
+ <arg name='f' type='pythonObject' info='the python function'/>
+ </function>
+ <function name='xsltRegisterExtensionClass' file='python'>
+ <info>Register a Python written extension class to the XSLT engine</info>
+ <return type='int' info="0 in case of success, -1 in case of error"/>
+ <arg name='URI' type='xmlChar *' info='the namespace or NULL'/>
+ <arg name='c' type='pythonObject' info='the python class instance'/>
+ </function>
+ <function name='xsltPythonCleanup' file='python'>
+ <info>Cleanup just libxslt (not libxml2) memory allocated</info>
+ <return type='void'/>
+ </function>
+ <!-- xmlXPathParserContextPtr accessors -->
+ <function name='xsltXPathParserGetContext' file='python_accessor'>
+ <info>Get the xpathContext from an xpathParserContext</info>
+ <return type='xmlXPathContextPtr' info="The XPath context" field="context"/>
+ <arg name='ctxt' type='xmlXPathParserContextPtr' info='the XPath parser context'/>
+ </function>
+ <!-- xmlXPathContextPtr accessors -->
+ <function name='xsltXPathGetTransformContext' file='python_accessor'>
+ <info>Get the transformation context from an xpathContext</info>
+ <return type='xsltTransformContextPtr' info="The node context" field="extra"/>
+ <arg name='ctxt' type='xmlXPathContextPtr' info='the XPath context'/>
+ </function>
+ <!-- xsltTransformContextPtr accessors -->
+ <function name='xsltTransformGetStyle' file='python_accessor'>
+ <info>Get the stylesheet from a transformation</info>
+ <return type='xsltStylesheetPtr' info="The stylesheet" field="style"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetCurrent' file='python_accessor'>
+ <info>Get the current() node of a transformation</info>
+ <return type='xmlNodePtr' info="The node" field="node"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetOutputDoc' file='python_accessor'>
+ <info>Get the output document of a transformation</info>
+ <return type='xmlDocPtr' info="The output doc" field="output"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetOutputURI' file='python_accessor'>
+ <info>Get the output URI of a transformation if known</info>
+ <return type='const char *' info="The output URI" field="outputFile"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetInsertNode' file='python_accessor'>
+ <info>Get the insertion node in the output document</info>
+ <return type='xmlNodePtr' info="The insertion node" field="insert"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetInstruction' file='python_accessor'>
+ <info>Get the instruction node in the stylesheet</info>
+ <return type='xmlNodePtr' info="The instruction node" field="inst"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetMode' file='python_accessor'>
+ <info>Get the mode of a transformation</info>
+ <return type='const xmlChar *' info="The mode" field="mode"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetModeURI' file='python_accessor'>
+ <info>Get the mode URI of a transformation</info>
+ <return type='const xmlChar *' info="The mode URI" field="modeURI"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetContext' file='python_accessor'>
+ <info>Get the XPath context of a transformation</info>
+ <return type='xmlXPathContextPtr' info="The XPath context" field="xpathCtxt"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformGetPrivate' file='python_accessor'>
+ <info>Get the private field of a transformation</info>
+ <return type='pythonObject *' info="The private field" field="_private"/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ </function>
+ <function name='xsltTransformSetPrivate' file='python_accessor'>
+ <info>Set the private field of a transformation</info>
+ <return type='void'/>
+ <arg name='ctxt' type='xsltTransformContextPtr' info='the transformation context'/>
+ <arg name='_private' type='pythonObject *' info='The private field'/>
+ </function>
+ <!-- xsltStylesheetPtr accessors -->
+ <function name='xsltStylesheetGetParent' file='python_accessor'>
+ <info>Get the parent of a stylesheet</info>
+ <return type='xsltStylesheetPtr' info="The parent" field="parent"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetNext' file='python_accessor'>
+ <info>Get the next sibling of a stylesheet</info>
+ <return type='xsltStylesheetPtr' info="The next sibling" field="next"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetImports' file='python_accessor'>
+ <info>Get the imports of a stylesheet</info>
+ <return type='xsltStylesheetPtr' info="The next sibling" field="imports"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetDoc' file='python_accessor'>
+ <info>Get the document of a stylesheet</info>
+ <return type='xmlDocPtr' info="The XML document" field="doc"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetMethod' file='python_accessor'>
+ <info>Get the output method of a stylesheet</info>
+ <return type='const xmlChar *' info="The output method" field="method"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetMethodURI' file='python_accessor'>
+ <info>Get the output method URI of a stylesheet</info>
+ <return type='const xmlChar *' info="The output method URI" field="methodURI"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetVersion' file='python_accessor'>
+ <info>Get the output version of a stylesheet</info>
+ <return type='const xmlChar *' info="The output version" field="version"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetEncoding' file='python_accessor'>
+ <info>Get the output encoding of a stylesheet</info>
+ <return type='const xmlChar *' info="The output encoding" field="encoding"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetDoctypePublic' file='python_accessor'>
+ <info>Get the output PUBLIC of a stylesheet</info>
+ <return type='const xmlChar *' info="The output PUBLIC" field="doctypePublic"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetDoctypeSystem' file='python_accessor'>
+ <info>Get the output SYSTEM of a stylesheet</info>
+ <return type='const xmlChar *' info="The output SYSTEM" field="doctypeSystem"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetGetPrivate' file='python_accessor'>
+ <info>Get the private field of a stylesheet</info>
+ <return type='pythonObject *' info="The private field" field="_private"/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ </function>
+ <function name='xsltStylesheetSetPrivate' file='python_accessor'>
+ <info>Set the private field of a stylesheet</info>
+ <return type='void'/>
+ <arg name='style' type='xsltStylesheetPtr' info='the stylesheet'/>
+ <arg name='_private' type='pythonObject *' info='The private field'/>
+ </function>
+ </symbols>
+</api>
diff --git a/libxslt/python/libxslt.c b/libxslt/python/libxslt.c
new file mode 100644
index 0000000..8dd6c78
--- /dev/null
+++ b/libxslt/python/libxslt.c
@@ -0,0 +1,1206 @@
+/*
+ libxslt.c: this module implements the main part of the glue of the
+ * libxslt library and the Python interpreter. It provides the
+ * entry points where an automatically generated stub is either
+ * unpractical or would not match cleanly the Python model.
+ *
+ * If compiled with MERGED_MODULES, the entry point will be used to
+ * initialize both the libxml2 and the libxslt wrappers
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+#include <Python.h>
+/* #include "config.h" */
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include "libexslt/exslt.h"
+#include "libxslt_wrap.h"
+#include "libxslt-py.h"
+
+#include <stdio.h>
+
+#if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(vsnprintf)
+#define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+#elif defined(XSLT_NEED_TRIO)
+#include "trio.h"
+#define vsnprintf trio_vsnprintf
+#endif
+
+/* #define DEBUG */
+/* #define DEBUG_XPATH */
+/* #define DEBUG_ERROR */
+/* #define DEBUG_MEMORY */
+/* #define DEBUG_EXTENSIONS */
+/* #define DEBUG_EXTENSIONS */
+
+void initlibxsltmod(void);
+
+/************************************************************************
+ * *
+ * Per type specific glue *
+ * *
+ ************************************************************************/
+
+PyObject *
+libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr style) {
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxslt_xsltStylesheetPtrWrap: style = %p\n", style);
+#endif
+ if (style == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ ret = PyCObject_FromVoidPtrAndDesc((void *) style,
+ (char *)"xsltStylesheetPtr", NULL);
+
+ return(ret);
+}
+
+PyObject *
+libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt) {
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxslt_xsltTransformContextPtrWrap: ctxt = %p\n", ctxt);
+#endif
+ if (ctxt == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt,
+ (char *)"xsltTransformContextPtr", NULL);
+ return(ret);
+}
+
+PyObject *
+libxslt_xsltElemPreCompPtrWrap(xsltElemPreCompPtr ctxt) {
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxslt_xsltElemPreCompPtrWrap: ctxt = %p\n", ctxt);
+#endif
+ if (ctxt == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt,
+ (char *)"xsltElemPreCompPtr", NULL);
+ return(ret);
+}
+
+PyObject *
+libxslt_xsltGetTransformContextHashCode(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_tctxt;
+ PyObject *ret;
+ long hash_code;
+ xsltTransformContextPtr tctxt;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:getTransformContextHashCode",
+ &py_tctxt))
+ return NULL;
+
+ tctxt = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt);
+ hash_code = (long) tctxt;
+
+ ret = PyInt_FromLong(hash_code);
+ return ret;
+}
+
+PyObject *
+libxslt_xsltCompareTransformContextsEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+
+ PyObject *py_tctxt1, *py_tctxt2;
+ xsltTransformContextPtr tctxt1, tctxt2;
+
+ if (!PyArg_ParseTuple(args, (char *)"OO:compareTransformContextsEqual",
+ &py_tctxt1, &py_tctxt2))
+ return NULL;
+
+ tctxt1 = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt1);
+ tctxt2 = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt2);
+
+ if ( tctxt1 == tctxt2 )
+ return Py_BuildValue((char *)"i", 1);
+ else
+ return Py_BuildValue((char *)"i", 0);
+}
+
+PyObject *
+libxslt_xsltGetStylesheetHashCode(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_style;
+ PyObject *ret;
+ long hash_code;
+ xsltStylesheetPtr style;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:getStylesheetHashCode",
+ &py_style))
+ return NULL;
+
+ style = (xsltStylesheetPtr) Pystylesheet_Get(py_style);
+ hash_code = (long) style;
+
+ ret = PyInt_FromLong(hash_code);
+ return ret;
+}
+
+
+PyObject *
+libxslt_xsltCompareStylesheetsEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+
+ PyObject *py_style1, *py_style2;
+ xsltStylesheetPtr style1, style2;
+
+ if (!PyArg_ParseTuple(args, (char *)"OO:compareStylesheetsEqual",
+ &py_style1, &py_style2))
+ return NULL;
+
+ style1 = (xsltStylesheetPtr) Pystylesheet_Get(py_style1);
+ style2 = (xsltStylesheetPtr) Pystylesheet_Get(py_style2);
+
+ if ( style1 == style2 )
+ return Py_BuildValue((char *)"i", 1);
+ else
+ return Py_BuildValue((char *)"i", 0);
+}
+
+/************************************************************************
+ * *
+ * Extending the API *
+ * *
+ ************************************************************************/
+
+static xmlHashTablePtr libxslt_extModuleFunctions = NULL;
+static xmlHashTablePtr libxslt_extModuleElements = NULL;
+static xmlHashTablePtr libxslt_extModuleElementPreComp = NULL;
+
+static void
+deallocateCallback(void *payload, xmlChar *name ATTRIBUTE_UNUSED) {
+ PyObject *function = (PyObject *) payload;
+
+#ifdef DEBUG_EXTENSIONS
+ printf("deallocateCallback(%s) called\n", name);
+#endif
+
+ Py_XDECREF(function);
+}
+
+static void
+deallocateClasse(void *payload, xmlChar *name ATTRIBUTE_UNUSED) {
+ PyObject *class = (PyObject *) payload;
+
+#ifdef DEBUG_EXTENSIONS
+ printf("deallocateClasse(%s) called\n", name);
+#endif
+
+ Py_XDECREF(class);
+}
+
+
+/**
+ * libxslt_xsltElementPreCompCallback
+ * @style: the stylesheet
+ * @inst: the instruction in the stylesheet
+ *
+ * Callback for preprocessing of a custom element
+ */
+static xsltElemPreCompPtr
+libxslt_xsltElementPreCompCallback(xsltStylesheetPtr style, xmlNodePtr inst,
+ xsltTransformFunction function) {
+ xsltElemPreCompPtr ret;
+ const xmlChar *name;
+ PyObject *args;
+ PyObject *result;
+ PyObject *pyobj_element_f;
+ PyObject *pyobj_precomp_f;
+
+ const xmlChar *ns_uri;
+
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltElementPreCompCallback called\n");
+#endif
+
+ if (style == NULL) {
+ xsltTransformError(NULL, NULL, inst,
+ "libxslt_xsltElementPreCompCallback: no transformation context\n");
+ return (NULL);
+ }
+
+ if (inst == NULL) {
+ xsltTransformError(NULL, style, inst,
+ "libxslt_xsltElementPreCompCallback: no instruction\n");
+ if (style != NULL) style->errors++;
+ return (NULL);
+ }
+
+ if (style == NULL)
+ return (NULL);
+
+ if (inst != NULL && inst->ns != NULL) {
+ name = inst->name;
+ ns_uri = inst->ns->href;
+ } else {
+ xsltTransformError(NULL, style, inst,
+ "libxslt_xsltElementPreCompCallback: internal error bad parameter\n");
+ printf("libxslt_xsltElementPreCompCallback: internal error bad parameter\n");
+ if (style != NULL) style->errors++;
+ return (NULL);
+ }
+
+ /*
+ * Find the functions, they should be there it was there at lookup
+ */
+ pyobj_precomp_f = xmlHashLookup2(libxslt_extModuleElementPreComp,
+ name, ns_uri);
+ if (pyobj_precomp_f == NULL) {
+ xsltTransformError(NULL, style, inst,
+ "libxslt_xsltElementPreCompCallback: internal error, could not find precompile python function!\n");
+ if (style != NULL) style->errors++;
+ return (NULL);
+ }
+
+ pyobj_element_f = xmlHashLookup2(libxslt_extModuleElements,
+ name, ns_uri);
+ if (pyobj_element_f == NULL) {
+ xsltTransformError(NULL, style, inst,
+ "libxslt_xsltElementPreCompCallback: internal error, could not find element python function!\n");
+ if (style != NULL) style->errors++;
+ return (NULL);
+ }
+
+ args = Py_BuildValue((char *)"(OOO)",
+ libxslt_xsltStylesheetPtrWrap(style),
+ libxml_xmlNodePtrWrap(inst),
+ pyobj_element_f);
+
+ Py_INCREF(pyobj_precomp_f); /* Protect refcount against reentrant manipulation of callback hash */
+ result = PyEval_CallObject(pyobj_precomp_f, args);
+ Py_DECREF(pyobj_precomp_f);
+ Py_DECREF(args);
+
+ /* FIXME allow callbacks to return meaningful information to modify compile process */
+ /* If error, do we need to check the result and throw exception? */
+
+ Py_XDECREF(result);
+
+ ret = xsltNewElemPreComp (style, inst, function);
+ return (ret);
+}
+
+
+static void
+libxslt_xsltElementTransformCallback(xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltElemPreCompPtr comp)
+{
+ PyObject *args, *result;
+ PyObject *func = NULL;
+ const xmlChar *name;
+ const xmlChar *ns_uri;
+
+ if (ctxt == NULL)
+ return;
+
+ if (inst != NULL && inst->name != NULL && inst->ns != NULL && inst->ns->href != NULL) {
+ name = inst->name;
+ ns_uri = inst->ns->href;
+ } else {
+ printf("libxslt_xsltElementTransformCallback: internal error bad parameter\n");
+ return;
+ }
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltElementTransformCallback called name %s URI %s\n", name, ns_uri);
+#endif
+
+ /*
+ * Find the function, it should be there it was there at lookup
+ */
+ func = xmlHashLookup2(libxslt_extModuleElements,
+ name, ns_uri);
+ if (func == NULL) {
+ printf("libxslt_xsltElementTransformCallback: internal error %s not found !\n",
+ name);
+ return;
+ }
+
+ args = Py_BuildValue((char *)"OOOO",
+ libxslt_xsltTransformContextPtrWrap(ctxt),
+ libxml_xmlNodePtrWrap(node),
+ libxml_xmlNodePtrWrap(inst),
+ libxslt_xsltElemPreCompPtrWrap(comp));
+
+ Py_INCREF(func); /* Protect refcount against reentrant manipulation of callback hash */
+ result = PyEval_CallObject(func, args);
+ Py_DECREF(func);
+ Py_DECREF(args);
+
+ /* FIXME Check result of callobject and set exception if fail */
+
+ Py_XDECREF(result);
+}
+
+PyObject *
+libxslt_xsltRegisterExtModuleElement(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ PyObject *py_retval;
+ int ret = 0;
+ xmlChar *name;
+ xmlChar *ns_uri;
+ PyObject *pyobj_element_f;
+ PyObject *pyobj_precomp_f;
+
+ if (!PyArg_ParseTuple(args, (char *)"szOO:registerExtModuleElement",
+ &name, &ns_uri, &pyobj_precomp_f, &pyobj_element_f))
+ return(NULL);
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltRegisterExtModuleElement called: %s %s\n",
+ name, ns_uri);
+#endif
+
+ if ((name == NULL) || (pyobj_element_f == NULL) || (pyobj_precomp_f == NULL)) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltRegisterExtModuleElement(%s, %s) called\n",
+ name, ns_uri);
+#endif
+
+ if (libxslt_extModuleElements == NULL)
+ libxslt_extModuleElements = xmlHashCreate(10);
+
+ if (libxslt_extModuleElementPreComp == NULL)
+ libxslt_extModuleElementPreComp = xmlHashCreate(10);
+
+ if (libxslt_extModuleElements == NULL || libxslt_extModuleElementPreComp == NULL) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+
+ ret = xmlHashAddEntry2(libxslt_extModuleElements, name, ns_uri, pyobj_element_f);
+ if (ret != 0) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ Py_XINCREF(pyobj_element_f);
+
+ ret = xmlHashAddEntry2(libxslt_extModuleElementPreComp, name, ns_uri, pyobj_precomp_f);
+ if (ret != 0) {
+ xmlHashRemoveEntry2(libxslt_extModuleElements, name, ns_uri, deallocateCallback);
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ Py_XINCREF(pyobj_precomp_f);
+
+ ret = xsltRegisterExtModuleElement(name, ns_uri,
+ libxslt_xsltElementPreCompCallback,
+ libxslt_xsltElementTransformCallback);
+ py_retval = libxml_intWrap((int) ret);
+ return(py_retval);
+}
+static void
+libxslt_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs) {
+ PyObject *list, *cur, *result;
+ xmlXPathObjectPtr obj;
+ xmlXPathContextPtr rctxt;
+ PyObject *current_function = NULL;
+ const xmlChar *name;
+ const xmlChar *ns_uri;
+ int i;
+
+ if (ctxt == NULL)
+ return;
+ rctxt = ctxt->context;
+ if (rctxt == NULL)
+ return;
+ name = rctxt->function;
+ ns_uri = rctxt->functionURI;
+#ifdef DEBUG_XPATH
+ printf("libxslt_xmlXPathFuncCallback called name %s URI %s\n", name, ns_uri);
+#endif
+
+ /*
+ * Find the function, it should be there it was there at lookup
+ */
+ current_function = xmlHashLookup2(libxslt_extModuleFunctions,
+ name, ns_uri);
+ if (current_function == NULL) {
+ printf("libxslt_xmlXPathFuncCallback: internal error %s not found !\n",
+ name);
+ return;
+ }
+
+ list = PyTuple_New(nargs + 1);
+ PyTuple_SetItem(list, 0, libxml_xmlXPathParserContextPtrWrap(ctxt));
+ for (i = nargs - 1;i >= 0;i--) {
+ obj = valuePop(ctxt);
+ cur = libxml_xmlXPathObjectPtrWrap(obj);
+ PyTuple_SetItem(list, i + 1, cur);
+ }
+
+ Py_INCREF(current_function);
+ result = PyEval_CallObject(current_function, list);
+ Py_DECREF(current_function);
+ Py_DECREF(list);
+
+ /* Check for null in case of exception */
+ if (result != NULL) {
+ obj = libxml_xmlXPathObjectPtrConvert(result);
+ valuePush(ctxt, obj);
+ }
+}
+
+PyObject *
+libxslt_xsltRegisterExtModuleFunction(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ PyObject *py_retval;
+ int ret = 0;
+ xmlChar *name;
+ xmlChar *ns_uri;
+ PyObject *pyobj_f;
+
+ if (!PyArg_ParseTuple(args, (char *)"szO:registerExtModuleFunction",
+ &name, &ns_uri, &pyobj_f))
+ return(NULL);
+
+ if ((name == NULL) || (pyobj_f == NULL)) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+
+#ifdef DEBUG_XPATH
+ printf("libxslt_xsltRegisterExtModuleFunction(%s, %s) called\n",
+ name, ns_uri);
+#endif
+
+ if (libxslt_extModuleFunctions == NULL)
+ libxslt_extModuleFunctions = xmlHashCreate(10);
+ if (libxslt_extModuleFunctions == NULL) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ ret = xmlHashAddEntry2(libxslt_extModuleFunctions, name, ns_uri, pyobj_f);
+ if (ret != 0) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ Py_XINCREF(pyobj_f);
+
+ ret = xsltRegisterExtModuleFunction(name, ns_uri,
+ libxslt_xmlXPathFuncCallback);
+ py_retval = libxml_intWrap((int) ret);
+ return(py_retval);
+}
+
+
+/************************************************************************
+ * *
+ * Document loading front-ends *
+ * *
+ ************************************************************************/
+
+static PyObject *pythonDocLoaderObject = NULL;
+
+static xmlDocPtr
+pythonDocLoaderFuncWrapper(const xmlChar * URI, xmlDictPtr dict, int options,
+ void *ctxt ATTRIBUTE_UNUSED,
+ xsltLoadType type ATTRIBUTE_UNUSED)
+{
+ xmlParserCtxtPtr pctxt;
+ xmlDocPtr doc=NULL;
+
+ pctxt = xmlNewParserCtxt();
+ if (pctxt == NULL)
+ return(NULL);
+ if ((dict != NULL) && (pctxt->dict != NULL)) {
+ xmlDictFree(pctxt->dict);
+ pctxt->dict = NULL;
+ }
+ if (dict != NULL) {
+ pctxt->dict = dict;
+ xmlDictReference(pctxt->dict);
+#ifdef WITH_XSLT_DEBUG
+ xsltGenericDebug(xsltGenericDebugContext,
+ "Reusing dictionary for document\n");
+#endif
+ }
+ xmlCtxtUseOptions(pctxt, options);
+
+ /*
+ * Now pass to python the URI, the xsltParserContext and the context
+ * (either a transformContext or a stylesheet) and get back an xmlDocPtr
+ */
+ if (pythonDocLoaderObject != NULL) {
+ PyObject *ctxtobj, *pctxtobj, *result;
+ pctxtobj = libxml_xmlParserCtxtPtrWrap(pctxt);
+
+ if (type == XSLT_LOAD_DOCUMENT) {
+ ctxtobj = libxslt_xsltTransformContextPtrWrap(ctxt);
+ result = PyObject_CallFunction(pythonDocLoaderObject,
+ (char *) "(sOOi)", URI, pctxtobj, ctxtobj, 0);
+ }
+ else {
+ ctxtobj = libxslt_xsltStylesheetPtrWrap(ctxt);
+ result = PyObject_CallFunction(pythonDocLoaderObject,
+ (char *) "(sOOi)", URI, pctxtobj, ctxtobj, 1);
+ }
+
+ Py_XDECREF(pctxtobj);
+
+ if (result != NULL) {
+ /*
+ * The return value should be the document
+ * Should we test it somehow before getting the C object from it?
+ */
+ PyObject *py_doc = PyObject_GetAttrString(result, (char *) "_o");
+ doc = (xmlDocPtr) PyxmlNode_Get(py_doc);
+ /* do we have to DECCREF the result?? */
+ }
+ }
+
+ if (! pctxt->wellFormed) {
+ if (doc != NULL) {
+ xmlFreeDoc(doc);
+ doc = NULL;
+ }
+ if (pctxt->myDoc != NULL) {
+ xmlFreeDoc(pctxt->myDoc);
+ pctxt->myDoc = NULL;
+ }
+ }
+ /*
+ * xmlFreeParserCtxt(pctxt);
+ * libc complains about double free-ing with this line
+ */
+
+ return(doc);
+}
+
+
+PyObject *
+libxslt_xsltSetLoaderFunc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval;
+ PyObject *loader;
+
+ if (!PyArg_ParseTuple(args, (char *)"O:libxslt_xsltSetLoaderFunc",
+ &loader))
+ return(NULL);
+
+ pythonDocLoaderObject = loader;
+ xsltSetLoaderFunc(pythonDocLoaderFuncWrapper);
+
+ py_retval = PyInt_FromLong(0);
+ return(py_retval);
+}
+
+PyObject *
+libxslt_xsltGetLoaderFunc(void) {
+ PyObject *py_retval;
+
+ py_retval = pythonDocLoaderObject;
+ return(py_retval);
+}
+
+
+/************************************************************************
+ * *
+ * Some customized front-ends *
+ * *
+ ************************************************************************/
+
+PyObject *
+libxslt_xsltNewTransformContext(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval;
+ PyObject *pyobj_style;
+ PyObject *pyobj_doc;
+ xsltStylesheetPtr style;
+ xmlDocPtr doc;
+ xsltTransformContextPtr c_retval;
+
+ if (!PyArg_ParseTuple(args, (char *) "OO:xsltNewTransformContext",
+ &pyobj_style, &pyobj_doc))
+ return(NULL);
+
+ style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
+ doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
+
+ c_retval = xsltNewTransformContext(style, doc);
+ py_retval = libxslt_xsltTransformContextPtrWrap((xsltTransformContextPtr) c_retval);
+ return (py_retval);
+}
+
+PyObject *
+libxslt_xsltFreeTransformContext(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_tctxt;
+ xsltTransformContextPtr tctxt;
+
+ if (!PyArg_ParseTuple(args, (char *) "O:xsltFreeTransformContext", &py_tctxt))
+ return(NULL);
+
+ tctxt = (xsltTransformContextPtr) PytransformCtxt_Get(py_tctxt);
+ xsltFreeTransformContext(tctxt);
+
+ /* Return None */
+ Py_INCREF(Py_None);
+ return(Py_None);
+}
+
+PyObject *
+libxslt_xsltApplyStylesheetUser(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval;
+ xmlDocPtr c_retval;
+ xsltStylesheetPtr style;
+ PyObject *pyobj_style;
+ xmlDocPtr doc;
+ xsltTransformContextPtr transformCtxt;
+ PyObject *pyobj_doc;
+ PyObject *pyobj_params;
+ PyObject *pyobj_transformCtxt;
+ const char **params = NULL;
+ int len = 0, i, j;
+ ssize_t ppos = 0;
+ PyObject *name;
+ PyObject *value;
+
+ if (!PyArg_ParseTuple(args, (char *) "OOOO:xsltApplyStylesheetUser",
+ &pyobj_style, &pyobj_doc, &pyobj_params, &pyobj_transformCtxt))
+ return(NULL);
+
+ if (pyobj_params != Py_None) {
+ if (PyDict_Check(pyobj_params)) {
+ len = PyDict_Size(pyobj_params);
+ if (len > 0) {
+ params = (const char **) xmlMalloc((len + 1) * 2 *
+ sizeof(char *));
+ if (params == NULL) {
+ printf("libxslt_xsltApplyStylesheet: out of memory\n");
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ j = 0;
+ while (PyDict_Next(pyobj_params, &ppos, &name, &value)) {
+ const char *tmp;
+ int size;
+
+ tmp = PyString_AS_STRING(name);
+ size = PyString_GET_SIZE(name);
+ params[j * 2] = (char *) xmlCharStrndup(tmp, size);
+ if (PyString_Check(value)) {
+ tmp = PyString_AS_STRING(value);
+ size = PyString_GET_SIZE(value);
+ params[(j * 2) + 1] = (char *)
+ xmlCharStrndup(tmp, size);
+ } else {
+ params[(j * 2) + 1] = NULL;
+ }
+ j = j + 1;
+ }
+ params[j * 2] = NULL;
+ params[(j * 2) + 1] = NULL;
+ }
+ } else {
+ printf("libxslt_xsltApplyStylesheet: parameters not a dict\n");
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ }
+ style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
+ doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
+ transformCtxt = (xsltTransformContextPtr) PytransformCtxt_Get(pyobj_transformCtxt);
+
+ c_retval = xsltApplyStylesheetUser(style, doc, params, NULL, NULL, transformCtxt);
+ py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval);
+ if (params != NULL) {
+ if (len > 0) {
+ for (i = 0;i < 2 * len;i++) {
+ if (params[i] != NULL)
+ xmlFree((char *)params[i]);
+ }
+ xmlFree(params);
+ }
+ }
+ return(py_retval);
+}
+
+PyObject *
+libxslt_xsltApplyStylesheet(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval;
+ xmlDocPtr c_retval;
+ xsltStylesheetPtr style;
+ PyObject *pyobj_style;
+ xmlDocPtr doc;
+ PyObject *pyobj_doc;
+ PyObject *pyobj_params;
+ const char **params = NULL;
+ int len = 0, i, j, params_size;
+ ssize_t ppos = 0;
+ PyObject *name;
+ PyObject *value;
+
+ if (!PyArg_ParseTuple(args, (char *) "OOO:xsltApplyStylesheet",
+ &pyobj_style, &pyobj_doc, &pyobj_params))
+ return(NULL);
+
+ if (pyobj_params != Py_None) {
+ if (PyDict_Check(pyobj_params)) {
+ len = PyDict_Size(pyobj_params);
+ if (len > 0) {
+ params_size = (len + 1) * 2 * sizeof(char *);
+ params = (const char **) xmlMalloc(params_size);
+ if (params == NULL) {
+ printf("libxslt_xsltApplyStylesheet: out of memory\n");
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ memset(params, 0, params_size);
+ j = 0;
+ while (PyDict_Next(pyobj_params, &ppos, &name, &value)) {
+ const char *tmp;
+ int size;
+
+ tmp = PyString_AS_STRING(name);
+ size = PyString_GET_SIZE(name);
+ params[j * 2] = (char *) xmlCharStrndup(tmp, size);
+ if (PyString_Check(value)) {
+ tmp = PyString_AS_STRING(value);
+ size = PyString_GET_SIZE(value);
+ params[(j * 2) + 1] = (char *)
+ xmlCharStrndup(tmp, size);
+ } else {
+ params[(j * 2) + 1] = NULL;
+ }
+ j = j + 1;
+ }
+ params[j * 2] = NULL;
+ params[(j * 2) + 1] = NULL;
+ }
+ } else {
+ printf("libxslt_xsltApplyStylesheet: parameters not a dict\n");
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ }
+ style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
+ doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
+
+ c_retval = xsltApplyStylesheet(style, doc, params);
+ py_retval = libxml_xmlDocPtrWrap((xmlDocPtr) c_retval);
+ if (params != NULL) {
+ if (len > 0) {
+ for (i = 0;i < 2 * len;i++) {
+ if (params[i] != NULL)
+ xmlFree((char *)params[i]);
+ }
+ xmlFree(params);
+ }
+ }
+ return(py_retval);
+}
+
+PyObject *
+libxslt_xsltSaveResultToString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+ PyObject *py_retval; /* our final return value, a python string */
+ xmlChar *buffer;
+ int size = 0;
+ int emitted = 0;
+ xmlDocPtr result;
+ PyObject *pyobj_result;
+ xsltStylesheetPtr style;
+ PyObject *pyobj_style;
+
+ if (!PyArg_ParseTuple(args, (char *)"OO:xsltSaveResultToString", &pyobj_style, &pyobj_result))
+ goto FAIL;
+ result = (xmlDocPtr) PyxmlNode_Get(pyobj_result);
+ style = (xsltStylesheetPtr) Pystylesheet_Get(pyobj_style);
+
+
+ /* FIXME: We should probably add more restrictive error checking
+ * and raise an error instead of "just" returning NULL.
+ * FIXME: Documentation and code for xsltSaveResultToString diff
+ * -> emmitted will never be positive non-null.
+ */
+ emitted = xsltSaveResultToString(&buffer, &size, result, style);
+ if(!buffer || emitted < 0)
+ goto FAIL;
+ /* We haven't tested the aberrant case of a transformation that
+ * renders to an empty string. For now we try to play it safe.
+ */
+ if(size)
+ {
+ buffer[size] = '\0';
+ py_retval = PyString_FromString((char *) buffer);
+ xmlFree(buffer);
+ }
+ else
+ py_retval = PyString_FromString("");
+ return(py_retval);
+ FAIL:
+ return(0);
+}
+
+
+/************************************************************************
+ * *
+ * Error message callback *
+ * *
+ ************************************************************************/
+
+static PyObject *libxslt_xsltPythonErrorFuncHandler = NULL;
+static PyObject *libxslt_xsltPythonErrorFuncCtxt = NULL;
+
+static void
+libxslt_xsltErrorFuncHandler(void *ctx ATTRIBUTE_UNUSED, const char *msg,
+ ...)
+{
+ int size;
+ int chars;
+ char *larger;
+ va_list ap;
+ char *str;
+ PyObject *list;
+ PyObject *message;
+ PyObject *result;
+
+#ifdef DEBUG_ERROR
+ printf("libxslt_xsltErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
+#endif
+
+
+ if (libxslt_xsltPythonErrorFuncHandler == NULL) {
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+ } else {
+ str = (char *) xmlMalloc(150);
+ if (str == NULL)
+ return;
+
+ size = 150;
+
+ while (1) {
+ va_start(ap, msg);
+ chars = vsnprintf(str, size, msg, ap);
+ va_end(ap);
+ if ((chars > -1) && (chars < size))
+ break;
+ if (chars > -1)
+ size += chars + 1;
+ else
+ size += 100;
+ if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
+ xmlFree(str);
+ return;
+ }
+ str = larger;
+ }
+
+ list = PyTuple_New(2);
+ PyTuple_SetItem(list, 0, libxslt_xsltPythonErrorFuncCtxt);
+ Py_XINCREF(libxslt_xsltPythonErrorFuncCtxt);
+ message = libxml_charPtrWrap(str);
+ PyTuple_SetItem(list, 1, message);
+ result = PyEval_CallObject(libxslt_xsltPythonErrorFuncHandler, list);
+ Py_XDECREF(list);
+ Py_XDECREF(result);
+ }
+}
+
+static void
+libxslt_xsltErrorInitialize(void)
+{
+#ifdef DEBUG_ERROR
+ printf("libxslt_xsltErrorInitialize() called\n");
+#endif
+ xmlSetGenericErrorFunc(NULL, libxslt_xsltErrorFuncHandler);
+ xsltSetGenericErrorFunc(NULL, libxslt_xsltErrorFuncHandler);
+}
+
+PyObject *
+libxslt_xsltRegisterErrorHandler(PyObject * self ATTRIBUTE_UNUSED,
+ PyObject * args)
+{
+ PyObject *py_retval;
+ PyObject *pyobj_f;
+ PyObject *pyobj_ctx;
+
+ if (!PyArg_ParseTuple
+ (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f,
+ &pyobj_ctx))
+ return (NULL);
+
+#ifdef DEBUG_ERROR
+ printf("libxml_registerXPathFunction(%p, %p) called\n", pyobj_ctx,
+ pyobj_f);
+#endif
+
+ if (libxslt_xsltPythonErrorFuncHandler != NULL) {
+ Py_XDECREF(libxslt_xsltPythonErrorFuncHandler);
+ }
+ if (libxslt_xsltPythonErrorFuncCtxt != NULL) {
+ Py_XDECREF(libxslt_xsltPythonErrorFuncCtxt);
+ }
+
+ Py_XINCREF(pyobj_ctx);
+ Py_XINCREF(pyobj_f);
+
+ /* TODO: check f is a function ! */
+ libxslt_xsltPythonErrorFuncHandler = pyobj_f;
+ libxslt_xsltPythonErrorFuncCtxt = pyobj_ctx;
+
+ py_retval = libxml_intWrap(1);
+ return (py_retval);
+}
+
+/************************************************************************
+ * *
+ * Extension classes *
+ * *
+ ************************************************************************/
+
+static xmlHashTablePtr libxslt_extModuleClasses = NULL;
+
+static void *
+libxslt_xsltPythonExtModuleStyleInit(xsltStylesheetPtr style,
+ const xmlChar * URI) {
+ PyObject *result = NULL;
+ PyObject *class = NULL;
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltPythonExtModuleStyleInit(%p, %s) called\n",
+ style, URI);
+#endif
+
+ if ((style == NULL) || (URI == NULL))
+ return(NULL);
+
+ /*
+ * Find the function, it should be there it was there at lookup
+ */
+ class = xmlHashLookup(libxslt_extModuleClasses, URI);
+ if (class == NULL) {
+ fprintf(stderr, "libxslt_xsltPythonExtModuleStyleInit: internal error %s not found !\n", URI);
+ return(NULL);
+ }
+
+ if (PyObject_HasAttrString(class, (char *) "_styleInit")) {
+ result = PyObject_CallMethod(class, (char *) "_styleInit",
+ (char *) "Os", libxslt_xsltStylesheetPtrWrap(style), URI);
+ }
+ return((void *)result);
+}
+static void
+libxslt_xsltPythonExtModuleStyleShutdown(xsltStylesheetPtr style,
+ const xmlChar * URI, void *data) {
+ PyObject *class = NULL;
+ PyObject *result;
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltPythonExtModuleStyleShutdown(%p, %s, %p) called\n",
+ style, URI, data);
+#endif
+
+ if ((style == NULL) || (URI == NULL))
+ return;
+
+ /*
+ * Find the function, it should be there it was there at lookup
+ */
+ class = xmlHashLookup(libxslt_extModuleClasses, URI);
+ if (class == NULL) {
+ fprintf(stderr, "libxslt_xsltPythonExtModuleStyleShutdown: internal error %s not found !\n", URI);
+ return;
+ }
+
+ if (PyObject_HasAttrString(class, (char *) "_styleShutdown")) {
+ result = PyObject_CallMethod(class, (char *) "_styleShutdown",
+ (char *) "OsO", libxslt_xsltStylesheetPtrWrap(style),
+ URI, (PyObject *) data);
+ Py_XDECREF(result);
+ Py_XDECREF((PyObject *)data);
+ }
+}
+
+static void *
+libxslt_xsltPythonExtModuleCtxtInit(xsltTransformContextPtr ctxt,
+ const xmlChar * URI) {
+ PyObject *result = NULL;
+ PyObject *class = NULL;
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltPythonExtModuleCtxtInit(%p, %s) called\n",
+ ctxt, URI);
+#endif
+
+ if ((ctxt == NULL) || (URI == NULL))
+ return(NULL);
+
+ /*
+ * Find the function, it should be there it was there at lookup
+ */
+ class = xmlHashLookup(libxslt_extModuleClasses, URI);
+ if (class == NULL) {
+ fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtInit: internal error %s not found !\n", URI);
+ return(NULL);
+ }
+
+ if (PyObject_HasAttrString(class, (char *) "_ctxtInit")) {
+ result = PyObject_CallMethod(class, (char *) "_ctxtInit",
+ (char *) "Os", libxslt_xsltTransformContextPtrWrap(ctxt),
+ URI);
+ }
+ return((void *)result);
+}
+static void
+libxslt_xsltPythonExtModuleCtxtShutdown(xsltTransformContextPtr ctxt,
+ const xmlChar * URI, void *data) {
+ PyObject *class = NULL;
+ PyObject *result;
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltPythonExtModuleCtxtShutdown(%p, %s, %p) called\n",
+ ctxt, URI, data);
+#endif
+
+ if ((ctxt == NULL) || (URI == NULL))
+ return;
+
+ /*
+ * Find the function, it should be there it was there at lookup
+ */
+ class = xmlHashLookup(libxslt_extModuleClasses, URI);
+ if (class == NULL) {
+ fprintf(stderr, "libxslt_xsltPythonExtModuleCtxtShutdown: internal error %s not found !\n", URI);
+ return;
+ }
+
+ if (PyObject_HasAttrString(class, (char *) "_ctxtShutdown")) {
+ result = PyObject_CallMethod(class, (char *) "_ctxtShutdown",
+ (char *) "OsO", libxslt_xsltTransformContextPtrWrap(ctxt),
+ URI, (PyObject *) data);
+ Py_XDECREF(result);
+ Py_XDECREF((PyObject *)data);
+ }
+}
+
+PyObject *
+libxslt_xsltRegisterExtensionClass(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args) {
+ PyObject *py_retval;
+ int ret = 0;
+ xmlChar *ns_uri;
+ PyObject *pyobj_c;
+
+ if (!PyArg_ParseTuple(args, (char *)"zO:registerExtensionClass",
+ &ns_uri, &pyobj_c))
+ return(NULL);
+
+ if ((ns_uri == NULL) || (pyobj_c == NULL)) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+
+#ifdef DEBUG_EXTENSIONS
+ printf("libxslt_xsltRegisterExtensionClass(%s) called\n", ns_uri);
+#endif
+
+ if (libxslt_extModuleClasses == NULL)
+ libxslt_extModuleClasses = xmlHashCreate(10);
+ if (libxslt_extModuleClasses == NULL) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ ret = xmlHashAddEntry(libxslt_extModuleClasses, ns_uri, pyobj_c);
+ if (ret != 0) {
+ py_retval = libxml_intWrap(-1);
+ return(py_retval);
+ }
+ Py_XINCREF(pyobj_c);
+
+ ret = xsltRegisterExtModuleFull(ns_uri,
+ (xsltExtInitFunction) libxslt_xsltPythonExtModuleCtxtInit,
+ (xsltExtShutdownFunction) libxslt_xsltPythonExtModuleCtxtShutdown,
+ (xsltStyleExtInitFunction) libxslt_xsltPythonExtModuleStyleInit,
+ (xsltStyleExtShutdownFunction) libxslt_xsltPythonExtModuleStyleShutdown);
+ py_retval = libxml_intWrap((int) ret);
+ if (ret < 0) {
+ Py_XDECREF(pyobj_c);
+ }
+ return(py_retval);
+}
+
+/************************************************************************
+ * *
+ * Integrated cleanup *
+ * *
+ ************************************************************************/
+
+PyObject *
+libxslt_xsltPythonCleanup(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args ATTRIBUTE_UNUSED) {
+
+ if (libxslt_extModuleFunctions != NULL) {
+ xmlHashFree(libxslt_extModuleFunctions, deallocateCallback);
+ }
+ if (libxslt_extModuleElements != NULL) {
+ xmlHashFree(libxslt_extModuleElements, deallocateCallback);
+ }
+ if (libxslt_extModuleElementPreComp != NULL) {
+ xmlHashFree(libxslt_extModuleElementPreComp, deallocateCallback);
+ }
+ if (libxslt_extModuleClasses != NULL) {
+ xmlHashFree(libxslt_extModuleClasses, deallocateClasse);
+ }
+ xsltCleanupGlobals();
+ Py_INCREF(Py_None);
+ return(Py_None);
+}
+
+/************************************************************************
+ * *
+ * The registration stuff *
+ * *
+ ************************************************************************/
+static PyMethodDef libxsltMethods[] = {
+#include "libxslt-export.c"
+ { NULL, NULL, 0, NULL }
+};
+
+#ifdef MERGED_MODULES
+extern void initlibxml2mod(void);
+#endif
+
+void initlibxsltmod(void) {
+ static int initialized = 0;
+ PyObject *m;
+
+#ifdef MERGED_MODULES
+ initlibxml2mod();
+#endif
+
+ if (initialized != 0)
+ return;
+ m = Py_InitModule((char *)"libxsltmod", libxsltMethods);
+ initialized = 1;
+ /*
+ * Specific XSLT initializations
+ */
+ libxslt_xsltErrorInitialize();
+ xmlInitMemory();
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
+ xmlDefaultSAXHandler.cdataBlock = NULL;
+ /*
+ * Register the EXSLT extensions and the test module
+ */
+ exsltRegisterAll();
+}
+
+
diff --git a/libxslt/python/libxslt_wrap.h b/libxslt/python/libxslt_wrap.h
new file mode 100644
index 0000000..d1c7907
--- /dev/null
+++ b/libxslt/python/libxslt_wrap.h
@@ -0,0 +1,49 @@
+#include "libxml_wrap.h"
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/attributes.h>
+#include <libxslt/documents.h>
+#include <libxslt/extensions.h>
+#include <libxslt/extra.h>
+#include <libxslt/functions.h>
+#include <libxslt/imports.h>
+#include <libxslt/keys.h>
+#include <libxslt/namespaces.h>
+#include <libxslt/numbersInternals.h>
+#include <libxslt/pattern.h>
+#include <libxslt/preproc.h>
+#include <libxslt/templates.h>
+#include <libxslt/transform.h>
+#include <libxslt/variables.h>
+#include <libxslt/xsltconfig.h>
+
+#define Pystylesheet_Get(v) (((v) == Py_None) ? NULL : \
+ (((Pystylesheet_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xsltStylesheetPtr obj;
+} Pystylesheet_Object;
+
+#define PytransformCtxt_Get(v) (((v) == Py_None) ? NULL : \
+ (((PytransformCtxt_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xsltTransformContextPtr obj;
+} PytransformCtxt_Object;
+
+#define PycompiledStyle_Get(v) (((v) == Py_None) ? NULL : \
+ (((PycompiledStyle_Object *)(v))->obj))
+
+typedef struct {
+ PyObject_HEAD
+ xsltTransformContextPtr obj;
+} PycompiledStyle_Object;
+
+
+PyObject * libxslt_xsltStylesheetPtrWrap(xsltStylesheetPtr ctxt);
+PyObject * libxslt_xsltTransformContextPtrWrap(xsltTransformContextPtr ctxt);
+PyObject * libxslt_xsltStylePreCompPtrWrap(xsltStylePreCompPtr comp);
+PyObject * libxslt_xsltElemPreCompPtrWrap(xsltElemPreCompPtr comp);
diff --git a/libxslt/python/libxsltclass.txt b/libxslt/python/libxsltclass.txt
new file mode 100644
index 0000000..e1ffdb6
--- /dev/null
+++ b/libxslt/python/libxsltclass.txt
@@ -0,0 +1,238 @@
+ Generated Classes for libxslt-python
+
+#
+# Global functions of the module
+#
+
+
+# functions from module extensions
+debugDumpExtensions()
+initGlobals()
+registerTestModule()
+unregisterExtModule()
+unregisterExtModuleElement()
+unregisterExtModuleFunction()
+unregisterExtModuleTopLevel()
+
+# functions from module extra
+registerAllExtras()
+
+# functions from module python
+pythonCleanup()
+registerErrorHandler()
+registerExtModuleElement()
+registerExtModuleFunction()
+registerExtensionClass()
+setLoaderFunc()
+
+# functions from module xslt
+cleanupGlobals()
+init()
+
+# functions from module xsltInternals
+isBlank()
+loadStylesheetPI()
+newStylesheet()
+parseStylesheetDoc()
+parseStylesheetFile()
+uninit()
+
+# functions from module xsltlocale
+freeLocales()
+
+# functions from module xsltutils
+calibrateAdjust()
+debuggerStatus()
+nsProp()
+setDebuggerStatus()
+timestamp()
+xslDropCall()
+
+
+#
+# Set of classes of the module
+#
+
+
+
+Class xpathParserContext(libxml2.xpathParserContext)
+ # accessors
+ context()
+
+ # functions from module extra
+ functionNodeSet()
+
+ # functions from module functions
+ documentFunction()
+ elementAvailableFunction()
+ formatNumberFunction()
+ functionAvailableFunction()
+ generateIdFunction()
+ keyFunction()
+ systemPropertyFunction()
+ unparsedEntityURIFunction()
+
+
+Class xpathContext(libxml2.xpathContext)
+ # accessors
+ transformContext()
+
+ # functions from module functions
+ registerAllFunctions()
+
+
+Class transformCtxt(transformCtxtBase)
+ # accessors
+ context()
+ current()
+ insertNode()
+ instruction()
+ mode()
+ modeURI()
+ outputDoc()
+ outputURI()
+ style()
+
+ # functions from module attributes
+ applyAttributeSet()
+
+ # functions from module documents
+ freeDocuments()
+
+ # functions from module extensions
+ freeCtxtExts()
+ initCtxtExts()
+ shutdownCtxtExts()
+
+ # functions from module extra
+ debug()
+ registerExtras()
+
+ # functions from module imports
+ findElemSpaceHandling()
+ needElemSpaceHandling()
+
+ # functions from module namespaces
+ copyNamespace()
+ copyNamespaceList()
+ namespace()
+ plainNamespace()
+ specialNamespace()
+
+ # functions from module python
+ compareTransformContextsEqual()
+ freeTransformContext()
+ transformContextHashCode()
+
+ # functions from module templates
+ attrListTemplateProcess()
+ attrTemplateProcess()
+ attrTemplateValueProcess()
+ attrTemplateValueProcessNode()
+ evalAttrValueTemplate()
+ evalTemplateString()
+
+ # functions from module variables
+ evalGlobalVariables()
+ evalOneUserParam()
+ freeGlobalVariables()
+ parseStylesheetParam()
+ parseStylesheetVariable()
+ quoteOneUserParam()
+ variableLookup()
+
+ # functions from module xsltInternals
+ allocateExtraCtxt()
+ createRVT()
+ extensionInstructionResultFinalize()
+ freeRVTs()
+ initAllDocKeys()
+ registerLocalRVT()
+ registerPersistRVT()
+ registerTmpRVT()
+ releaseRVT()
+
+ # functions from module xsltutils
+ message()
+ printErrorContext()
+ profileInformation()
+ saveProfiling()
+ setCtxtParseOptions()
+
+
+Class stylesheet(stylesheetBase)
+ # accessors
+ doc()
+ doctypePublic()
+ doctypeSystem()
+ encoding()
+ imports()
+ method()
+ methodURI()
+ next()
+ parent()
+ version()
+
+ # functions from module attributes
+ freeAttributeSetsHashes()
+ parseStylesheetAttributeSet()
+ resolveStylesheetAttributeSet()
+
+ # functions from module documents
+ freeStyleDocuments()
+
+ # functions from module extensions
+ checkExtPrefix()
+ checkExtURI()
+ freeExts()
+ registerExtPrefix()
+ shutdownExts()
+
+ # functions from module imports
+ nextImport()
+ parseStylesheetImport()
+ parseStylesheetInclude()
+
+ # functions from module keys
+ addKey()
+ freeKeys()
+
+ # functions from module namespaces
+ freeNamespaceAliasHashes()
+ namespaceAlias()
+
+ # functions from module pattern
+ cleanupTemplates()
+ freeTemplateHashes()
+
+ # functions from module preproc
+ freeStylePreComps()
+ stylePreCompute()
+
+ # functions from module python
+ applyStylesheet()
+ applyStylesheetUser()
+ compareStylesheetsEqual()
+ newTransformContext()
+ saveResultToString()
+ stylesheetHashCode()
+
+ # functions from module variables
+ parseGlobalParam()
+ parseGlobalVariable()
+
+ # functions from module xsltInternals
+ allocateExtra()
+ compileAttr()
+ freeStylesheet()
+ parseStylesheetImportedDoc()
+ parseStylesheetOutput()
+ parseStylesheetProcess()
+ parseTemplateContent()
+
+ # functions from module xsltutils
+ cNsProp()
+ printErrorContext()
+ saveResultToFd()
+ saveResultToFile()
+ saveResultToFilename()
diff --git a/libxslt/python/tests/Makefile.am b/libxslt/python/tests/Makefile.am
new file mode 100644
index 0000000..f757774
--- /dev/null
+++ b/libxslt/python/tests/Makefile.am
@@ -0,0 +1,34 @@
+EXAMPLE_DIR = $(datadir)/doc/libxslt-python-$(LIBXSLT_VERSION)/examples
+
+TESTSPY= \
+ basic.py \
+ exslt.py \
+ extelem.py \
+ extfunc.py
+
+XMLS= \
+ test.xml \
+ test.xsl
+
+EXTRAS= \
+ pyxsltproc.py
+
+EXTRA_DIST = $(TESTSPY) $(XMLS) $(EXTRAS)
+
+CLEANFILES = *.pyc core
+
+if WITH_PYTHON
+tests: $(TESTSPY)
+ -@(PYTHONPATH="`pwd`/..:`pwd`/../.libs:$(srcdir)/.."; \
+ if test "x$(LIBXML_SRC)" != "x" ; then PYTHONPATH="$$PYTHONPATH:$(LIBXML_SRC)/python:$(LIBXML_SRC)/python/.libs"; fi; \
+ export PYTHONPATH; \
+ for test in $(TESTSPY) ; do echo "-- $$test" ; (cd $(srcdir) && $(PYTHON) $$test ); done)
+else
+tests:
+endif
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(EXAMPLE_DIR)
+ -(for test in $(TESTSPY) $(XMLS) $(EXTRAS); \
+ do $(INSTALL) -m 0644 $(srcdir)/$$test $(DESTDIR)$(EXAMPLE_DIR) ; done)
+
diff --git a/libxslt/python/tests/basic.py b/libxslt/python/tests/basic.py
new file mode 100755
index 0000000..89a57ac
--- /dev/null
+++ b/libxslt/python/tests/basic.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python -u
+import sys
+import libxml2
+# Memory debug specific
+libxml2.debugMemory(1)
+import libxslt
+
+
+
+styledoc = libxml2.parseFile("test.xsl")
+style = libxslt.parseStylesheetDoc(styledoc)
+doc = libxml2.parseFile("test.xml")
+result = style.applyStylesheet(doc, None)
+style.saveResultToFilename("foo", result, 0)
+stringval = style.saveResultToString(result)
+if (len(stringval) != 68):
+ print "Error in saveResultToString"
+ sys.exit(255)
+style.freeStylesheet()
+doc.freeDoc()
+result.freeDoc()
+
+# Memory debug specific
+libxslt.cleanup()
+if libxml2.debugMemory(1) == 0:
+ print "OK"
+else:
+ print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+ libxml2.dumpMemory()
diff --git a/libxslt/python/tests/exslt.py b/libxslt/python/tests/exslt.py
new file mode 100755
index 0000000..c64b2e4
--- /dev/null
+++ b/libxslt/python/tests/exslt.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python -u
+import sys
+import libxml2
+# Memory debug specific
+libxml2.debugMemory(1)
+import libxslt
+
+
+styledoc = libxml2.parseDoc(
+"""<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://exslt.org/strings"
+ exclude-result-prefixes="str">
+
+<xsl:template match="/">
+<out>;
+ str:tokenize('2001-06-03T11:40:23', '-T:')
+ <xsl:copy-of select="str:tokenize('2001-06-03T11:40:23', '-T:')"/>;
+
+ str:tokenize('date math str')
+ <xsl:copy-of select="str:tokenize('date math str')"/>;
+</out>
+</xsl:template>
+
+</xsl:stylesheet>
+""")
+style = libxslt.parseStylesheetDoc(styledoc)
+doc = libxml2.parseDoc("<doc/>")
+result = style.applyStylesheet(doc, None)
+stringval = style.saveResultToString(result)
+style.freeStylesheet()
+doc.freeDoc()
+result.freeDoc()
+
+expect="""<?xml version="1.0"?>
+<out>;
+ str:tokenize('2001-06-03T11:40:23', '-T:')
+ <token>2001</token><token>06</token><token>03</token><token>11</token><token>40</token><token>23</token>;
+
+ str:tokenize('date math str')
+ <token>date</token><token>math</token><token>str</token>;
+</out>
+"""
+
+if stringval != expect:
+ print "Exslt processing failed"
+ sys.exit(255)
+
+# Memory debug specific
+libxslt.cleanup()
+if libxml2.debugMemory(1) == 0:
+ print "OK"
+else:
+ print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+ libxml2.dumpMemory()
diff --git a/libxslt/python/tests/extelem.py b/libxslt/python/tests/extelem.py
new file mode 100644
index 0000000..3364d01
--- /dev/null
+++ b/libxslt/python/tests/extelem.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python -u
+import sys
+import string
+import StringIO
+import libxml2
+# Memory debug specific
+libxml2.debugMemory(1)
+import libxslt
+
+EXT_URL="http://example.com/foo"
+
+insertNodeName = None
+transformNodeName = None
+
+def compile_test(style, inst, func):
+ pass
+
+def transform_test(ctx, node, inst, comp):
+ global insertNodeName
+
+ #
+ # Small check to verify the context is correcly accessed
+ #
+ try:
+ #
+ # FIXME add some more sanity checks
+ #
+ tctxt = libxslt.transformCtxt(_obj=ctx)
+ insertNodeName = tctxt.insertNode().name
+
+ # FIXME find and confirm the note being replaced is called 'test'
+ # transformNodeName = libxml2.xmlNode(inst).name
+ except:
+ pass
+
+ tctxt.insertNode().addContent('SUCCESS')
+
+
+
+styledoc = libxml2.parseDoc("""
+<xsl:stylesheet version='1.0'
+ xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+ xmlns:foo='%s'
+ extension-element-prefixes='foo'>
+
+ <xsl:template match='/'>
+ <article><foo:test>FAILURE</foo:test></article>
+ <deeper><article><foo:test>something<foo:test>nested</foo:test>even</foo:test></article></deeper>
+ </xsl:template>
+</xsl:stylesheet>
+""" % EXT_URL)
+
+style = libxslt.parseStylesheetDoc(styledoc)
+libxslt.registerExtModuleElement("test", EXT_URL, compile_test, transform_test)
+doc = libxml2.parseDoc("<doc/>")
+result = style.applyStylesheet(doc, None)
+style.freeStylesheet()
+doc.freeDoc()
+
+
+extensions = StringIO.StringIO()
+libxslt.debugDumpExtensions(extensions)
+
+if 0 and extensions.buf.find(EXT_URL) < 0:
+ print "Element extension not registered (or dumping broken)"
+ sys.exit(1)
+
+root = result.children
+
+if root.name != "article":
+ print "Unexpected root node name"
+ sys.exit(1)
+if root.content != "SUCCESS":
+ print "Unexpected root node content, extension function failed"
+ sys.exit(1)
+if insertNodeName != 'article':
+ print "The function callback failed to access its context"
+ sys.exit(1)
+
+result.dump(sys.stdout)
+result.freeDoc()
+
+# Memory debug specific
+libxslt.cleanup()
+if libxml2.debugMemory(1) == 0:
+ print "OK"
+else:
+ print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+ libxml2.dumpMemory()
diff --git a/libxslt/python/tests/extfunc.py b/libxslt/python/tests/extfunc.py
new file mode 100755
index 0000000..0a55953
--- /dev/null
+++ b/libxslt/python/tests/extfunc.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python -u
+import sys
+import string
+import libxml2
+# Memory debug specific
+libxml2.debugMemory(1)
+import libxslt
+
+nodeName = None
+
+def f(ctx, str):
+ global nodeName
+
+ #
+ # Small check to verify the context is correcly accessed
+ #
+ try:
+ pctxt = libxslt.xpathParserContext(_obj=ctx)
+ ctxt = pctxt.context()
+ tctxt = ctxt.transformContext()
+ nodeName = tctxt.insertNode().name
+ except:
+ pass
+
+ return string.upper(str)
+
+libxslt.registerExtModuleFunction("foo", "http://example.com/foo", f)
+
+styledoc = libxml2.parseDoc("""
+<xsl:stylesheet version='1.0'
+ xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+ xmlns:foo='http://example.com/foo'
+ exclude-result-prefixes='foo'>
+
+ <xsl:param name='bar'>failure</xsl:param>
+ <xsl:template match='/'>
+ <article><xsl:value-of select='foo:foo($bar)'/></article>
+ </xsl:template>
+</xsl:stylesheet>
+""")
+style = libxslt.parseStylesheetDoc(styledoc)
+doc = libxml2.parseDoc("<doc/>")
+result = style.applyStylesheet(doc, { "bar": "'success'" })
+style.freeStylesheet()
+doc.freeDoc()
+
+root = result.children
+if root.name != "article":
+ print "Unexpected root node name"
+ sys.exit(1)
+if root.content != "SUCCESS":
+ print "Unexpected root node content, extension function failed"
+ sys.exit(1)
+if nodeName != 'article':
+ print "The function callback failed to access its context"
+ sys.exit(1)
+
+result.freeDoc()
+
+# Memory debug specific
+libxslt.cleanup()
+if libxml2.debugMemory(1) == 0:
+ print "OK"
+else:
+ print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+ libxml2.dumpMemory()
diff --git a/libxslt/python/tests/pyxsltproc.py b/libxslt/python/tests/pyxsltproc.py
new file mode 100755
index 0000000..238fa5b
--- /dev/null
+++ b/libxslt/python/tests/pyxsltproc.py
@@ -0,0 +1,298 @@
+#!/usr/bin/python -u
+#
+# The exercise of rewriting xsltproc on top of the python
+# bindings, not complete yet and shows up the things missing
+# from the existing python interfaces
+#
+import sys
+import time
+import os
+import string
+import libxml2
+# Memory debug specific
+libxml2.debugMemory(1)
+import libxslt
+
+debug = 0
+repeat = 0
+timing = 0
+novalid = 0
+noout = 0
+docbook = 0
+html = 0
+xinclude = 0
+profile = 0
+params = {}
+output = None
+errorno = 0
+
+#
+# timing
+#
+begin = 0
+endtime = 0
+def startTimer():
+ global begin
+
+ begin = time.time()
+
+def endTimer(msg):
+ global begin
+ global endtime
+
+ endtime = time.time()
+ print "%s took %d ms" % (msg, (endtime - begin) * 1000)
+
+def xsltProcess(doc, cur, filename):
+ global timing
+ global xinclude
+ global params
+ global html
+
+ if xinclude:
+ if timing:
+ startTimer()
+ doc.XIncludeProcess()
+ if timing:
+ endTimer("XInclude processing %s" % (filename))
+
+ if timing:
+ startTimer()
+ if output == None:
+ if repeat != 0:
+ for j in range(1, repeat):
+ res = cur.applyStylesheet(doc, params)
+ res.freeDoc()
+ doc.freeDoc()
+ if html == 1:
+ doc = libxml2.htmlParseFile(filename, None)
+ else:
+ doc = libxml2.parseFile(filename, None)
+# ctxt = libxslt.newTransformContext(doc)
+# if ctxt == None:
+# return
+ if profile:
+ print "TODO: Profiling not yet supported"
+ else:
+ res = cur.applyStylesheet(doc, params)
+ if timing:
+ if repeat != 0:
+ endTimer("Applying stylesheet %d times" % (repeat))
+ else:
+ endTimer("Applying stylesheet")
+ doc.freeDoc()
+ if res == None:
+ print "no result for %s" % (filename)
+ return
+ if noout != 0:
+ res.freeDoc()
+ return
+ if debug == 1:
+ res.debugDumpDocument(None)
+ else:
+ if timing:
+ startTimer()
+ cur.saveResultToFilename("-", res, 0)
+ if timing:
+ endTimer("Saving result")
+ res.freeDoc()
+ else:
+ print "TODO: xsltRunStylesheet not yet mapped"
+
+def usage(name = 'pyxsltproc'):
+ print "Usage: %s [options] stylesheet file [file ...]" % (name)
+ print "a reimplementation of xsltproc(1) on top of libxslt-python"
+ print " Options:"
+ print "\t--version or -V: show the version of libxml and libxslt used"
+ print "\t--verbose or -v: show logs of what's happening"
+ print "\t--output file or -o file: save to a given file"
+ print "\t--timing: display the time used"
+ print "\t--repeat: run the transformation 20 times"
+ print "\t--debug: dump the tree of the result instead"
+ print "\t--novalid skip the Dtd loading phase"
+ print "\t--noout: do not dump the result"
+ print "\t--maxdepth val : increase the maximum depth"
+ print "\t--html: the input document is(are) an HTML file(s)"
+ print "\t--param name value : pass a (parameter,value) pair"
+ print "\t value is an XPath expression."
+ print "\t string values must be quoted like \"'string'\""
+ print "\t or use stringparam to avoid it"
+ print "\t--stringparam name value : pass a (parameter,string value) pair"
+ print "\t--nonet refuse to fetch DTDs or entities over network"
+ print "\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES"
+ print "\t otherwise XML Catalogs starting from "
+ print "\t file:///etc/xml/catalog are activated by default"
+ print "\t--xinclude : do XInclude processing on document input"
+ print "\t--profile or --norman : dump profiling informations "
+ print "\nProject libxslt home page: http://xmlsoft.org/XSLT/"
+ print "To report bugs and get help: http://xmlsoft.org/XSLT/bugs.html"
+
+def main(args = None):
+ global debug
+ global repeat
+ global timing
+ global novalid
+ global noout
+ global docbook
+ global html
+ global xinclude
+ global profile
+ global params
+ global output
+ global errorno
+
+ done = 0
+ cur = None
+
+ if not args:
+ args = sys.argv[1:]
+ if len(args) <= 0:
+ usage(sys.argv[0])
+
+
+ i = 0
+ while i < len(args):
+ if args[i] == "-":
+ break
+ if args[i][0] != '-':
+ i = i + 1
+ continue
+ if args[i] == "-timing" or args[i] == "--timing":
+ timing = 1
+ elif args[i] == "-debug" or args[i] == "--debug":
+ debug = 1
+ elif args[i] == "-verbose" or args[i] == "--verbose" or \
+ args[i] == "-v":
+ print "TODO: xsltSetGenericDebugFunc() mapping missing"
+ elif args[i] == "-version" or args[i] == "--version" or \
+ args[i] == "-V":
+ print "TODO: version informations mapping missing"
+ elif args[i] == "-verbose" or args[i] == "--verbose" or \
+ args[i] == "-v":
+ if repeat == 0:
+ repeat = 20
+ else:
+ repeat = 100
+ elif args[i] == "-novalid" or args[i] == "--novalid":
+ print "TODO: xmlLoadExtDtdDefaultValue mapping missing"
+ novalid = 1
+ elif args[i] == "-noout" or args[i] == "--noout":
+ noout = 1
+ elif args[i] == "-html" or args[i] == "--html":
+ html = 1
+ elif args[i] == "-nonet" or args[i] == "--nonet":
+ print "TODO: xmlSetExternalEntityLoader mapping missing"
+ nonet = 1
+ elif args[i] == "-catalogs" or args[i] == "--catalogs":
+ try:
+ catalogs = os.environ['SGML_CATALOG_FILES']
+ except:
+ catalogs = None
+ if catalogs != none:
+ libxml2.xmlLoadCatalogs(catalogs)
+ else:
+ print "Variable $SGML_CATALOG_FILES not set"
+ elif args[i] == "-xinclude" or args[i] == "--xinclude":
+ xinclude = 1
+ libxslt.setXIncludeDefault(1)
+ elif args[i] == "-param" or args[i] == "--param":
+ i = i + 1
+ params[args[i]] = args[i + 1]
+ i = i + 1
+ elif args[i] == "-stringparam" or args[i] == "--stringparam":
+ i = i + 1
+ params[args[i]] = "'%s'" % (args[i + 1])
+ i = i + 1
+ elif args[i] == "-maxdepth" or args[i] == "--maxdepth":
+ print "TODO: xsltMaxDepth mapping missing"
+ else:
+ print "Unknown option %s" % (args[i])
+ usage()
+ return(3)
+
+
+
+
+ i = i + 1
+
+ libxml2.lineNumbersDefault(1)
+ libxml2.substituteEntitiesDefault(1)
+ # TODO: xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS
+ # if novalid:
+ # TODO: xmlLoadExtDtdDefaultValue = 0
+
+ # TODO libxslt.exsltRegisterAll();
+ libxslt.registerTestModule()
+
+ i = 0
+ while i < len(args) and done == 0:
+ if args[i] == "-maxdepth" or args[i] == "--maxdepth":
+ i = i + 2
+ continue
+ if args[i] == "-o" or args[i] == "-output" or args[i] == "--output":
+ i = i + 2
+ continue
+ if args[i] == "-param" or args[i] == "--param":
+ i = i + 3
+ continue
+ if args[i] == "-stringparam" or args[i] == "--stringparam":
+ i = i + 3
+ continue
+ if args[i] != "-" and args[i][0] == '-':
+ i = i + 1
+ continue
+ if timing:
+ startTimer()
+ style = libxml2.parseFile(args[i])
+ if timing:
+ endTimer("Parsing stylesheet %s" % (args[i]))
+ if style == None:
+ print "cannot parse %s" % (args[i])
+ cur = None
+ errorno = 4
+ done = 1
+ else:
+ cur = libxslt.loadStylesheetPI(style)
+ if cur != None:
+ xsltProcess(style, cur, args[i])
+ cur = None
+ else:
+ cur = libxslt.parseStylesheetDoc(style)
+ if cur == None:
+ style.freeDoc()
+ errorno = 5
+ done = 1
+ i = i + 1
+ break
+
+ while i < len(args) and done == 0 and cur != None:
+ if timing:
+ startTimer()
+ if html:
+ doc = libxml2.htmlParseFile(args[i], None)
+ else:
+ doc = libxml2.parseFile(args[i])
+ if doc == None:
+ print "unable to parse %s" % (args[i])
+ errorno = 6
+ i = i + 1
+ continue
+ if timing:
+ endTimer("Parsing document %s" % (args[i]))
+ xsltProcess(doc, cur, args[i])
+ i = i + 1
+
+ if cur != None:
+ cur.freeStylesheet()
+ params = None
+
+if __name__ == "__main__":
+ main()
+
+# Memory debug specific
+libxslt.cleanup()
+if libxml2.debugMemory(1) != 0:
+ print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+ libxml2.dumpMemory()
+
+sys.exit(errorno)
diff --git a/libxslt/python/tests/test.xml b/libxslt/python/tests/test.xml
new file mode 100644
index 0000000..24110d9
--- /dev/null
+++ b/libxslt/python/tests/test.xml
@@ -0,0 +1 @@
+<test/>
diff --git a/libxslt/python/tests/test.xsl b/libxslt/python/tests/test.xsl
new file mode 100644
index 0000000..8d6ae3f
--- /dev/null
+++ b/libxslt/python/tests/test.xsl
@@ -0,0 +1,9 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:template match="/">
+ <article>
+ <title>Hello World</title>
+ </article>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/libxslt/python/types.c b/libxslt/python/types.c
new file mode 100644
index 0000000..1beee75
--- /dev/null
+++ b/libxslt/python/types.c
@@ -0,0 +1,602 @@
+/*
+xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL,
+ const char *ID,
+ xmlParserCtxtPtr ctxt);
+
+ * types.c: converter functions between the internal representation
+ * and the Python objects
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+#include "libxml_wrap.h"
+#include <libxml/xpathInternals.h>
+
+PyObject *
+libxml_intWrap(int val)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_intWrap: val = %d\n", val);
+#endif
+ ret = PyInt_FromLong((long) val);
+ return (ret);
+}
+
+PyObject *
+libxml_longWrap(long val)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_longWrap: val = %ld\n", val);
+#endif
+ ret = PyInt_FromLong(val);
+ return (ret);
+}
+
+PyObject *
+libxml_doubleWrap(double val)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_doubleWrap: val = %f\n", val);
+#endif
+ ret = PyFloat_FromDouble((double) val);
+ return (ret);
+}
+
+PyObject *
+libxml_charPtrWrap(char *str)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlcharPtrWrap: str = %s\n", str);
+#endif
+ if (str == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret = PyString_FromString(str);
+ xmlFree(str);
+ return (ret);
+}
+
+PyObject *
+libxml_charPtrConstWrap(const char *str)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlcharPtrWrap: str = %s\n", str);
+#endif
+ if (str == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret = PyString_FromString(str);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlCharPtrWrap(xmlChar * str)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlCharPtrWrap: str = %s\n", str);
+#endif
+ if (str == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret = PyString_FromString((char *) str);
+ xmlFree(str);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlCharPtrConstWrap(const xmlChar * str)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlCharPtrWrap: str = %s\n", str);
+#endif
+ if (str == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret = PyString_FromString((char *) str);
+ return (ret);
+}
+
+PyObject *
+libxml_constcharPtrWrap(const char *str)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlcharPtrWrap: str = %s\n", str);
+#endif
+ if (str == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret = PyString_FromString(str);
+ return (ret);
+}
+
+PyObject *
+libxml_constxmlCharPtrWrap(const xmlChar * str)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlCharPtrWrap: str = %s\n", str);
+#endif
+ if (str == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret = PyString_FromString((char *) str);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlDocPtrWrap(xmlDocPtr doc)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlDocPtrWrap: doc = %p\n", doc);
+#endif
+ if (doc == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ /* TODO: look at deallocation */
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) doc, (char *) "xmlDocPtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlNodePtrWrap(xmlNodePtr node)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlNodePtrWrap: node = %p\n", node);
+#endif
+ if (node == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) node, (char *) "xmlNodePtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlURIPtrWrap(xmlURIPtr uri)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlURIPtrWrap: uri = %p\n", uri);
+#endif
+ if (uri == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) uri, (char *) "xmlURIPtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlNsPtrWrap(xmlNsPtr ns)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlNsPtrWrap: node = %p\n", ns);
+#endif
+ if (ns == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) ns, (char *) "xmlNsPtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlAttrPtrWrap(xmlAttrPtr attr)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlAttrNodePtrWrap: attr = %p\n", attr);
+#endif
+ if (attr == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) attr, (char *) "xmlAttrPtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlAttributePtrWrap(xmlAttributePtr attr)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlAttributePtrWrap: attr = %p\n", attr);
+#endif
+ if (attr == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) attr,
+ (char *) "xmlAttributePtr", NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlElementPtrWrap(xmlElementPtr elem)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlElementNodePtrWrap: elem = %p\n", elem);
+#endif
+ if (elem == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) elem,
+ (char *) "xmlElementPtr", NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlXPathContextPtrWrap: ctxt = %p\n", ctxt);
+#endif
+ if (ctxt == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) ctxt,
+ (char *) "xmlXPathContextPtr", NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlXPathParserContextPtrWrap: ctxt = %p\n", ctxt);
+#endif
+ if (ctxt == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt,
+ (char *) "xmlXPathParserContextPtr",
+ NULL);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlParserCtxtPtrWrap: ctxt = %p\n", ctxt);
+#endif
+ if (ctxt == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) ctxt,
+ (char *) "xmlParserCtxtPtr", NULL);
+ return (ret);
+}
+
+/**
+ * libxml_xmlXPathDestructNsNode:
+ * cobj: xmlNsPtr namespace node
+ * desc: ignored string
+ *
+ * This function is called if and when a namespace node returned in
+ * an XPath node set is to be destroyed. That's the only kind of
+ * object returned in node set not directly linked to the original
+ * xmlDoc document, see xmlXPathNodeSetDupNs.
+ */
+static void
+libxml_xmlXPathDestructNsNode(void *cobj, void *desc ATTRIBUTE_UNUSED) {
+#ifdef DEBUG
+ fprintf(stderr, "libxml_xmlXPathDestructNsNode called %p\n", cobj);
+#endif
+ xmlXPathNodeSetFreeNs((xmlNsPtr) cobj);
+}
+
+PyObject *
+libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlXPathObjectPtrWrap: ctxt = %p\n", obj);
+#endif
+ if (obj == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ switch (obj->type) {
+ case XPATH_XSLT_TREE: {
+ if ((obj->nodesetval == NULL) ||
+ (obj->nodesetval->nodeNr == 0) ||
+ (obj->nodesetval->nodeTab == NULL)) {
+ ret = PyList_New(0);
+ } else {
+ int i, len = 0;
+ xmlNodePtr node;
+
+ node = obj->nodesetval->nodeTab[0]->children;
+ while (node != NULL) {
+ len++;
+ node = node->next;
+ }
+ ret = PyList_New(len);
+ node = obj->nodesetval->nodeTab[0]->children;
+ for (i = 0;i < len;i++) {
+ PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
+ node = node->next;
+ }
+ }
+ /*
+ * Return now, do not free the object passed down
+ */
+ return (ret);
+ }
+ case XPATH_NODESET:
+ if ((obj->nodesetval == NULL)
+ || (obj->nodesetval->nodeNr == 0)) {
+ ret = PyList_New(0);
+ } else {
+ int i;
+ xmlNodePtr node;
+
+ ret = PyList_New(obj->nodesetval->nodeNr);
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ node = obj->nodesetval->nodeTab[i];
+ if (node->type == XML_NAMESPACE_DECL) {
+ PyObject *ns =
+ PyCObject_FromVoidPtrAndDesc((void *) node,
+ (char *) "xmlNsPtr",
+ libxml_xmlXPathDestructNsNode);
+ PyList_SetItem(ret, i, ns);
+ /* make sure the xmlNsPtr is not destroyed now */
+ obj->nodesetval->nodeTab[i] = NULL;
+ } else {
+ PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
+ }
+ }
+ }
+ break;
+ case XPATH_BOOLEAN:
+ ret = PyInt_FromLong((long) obj->boolval);
+ break;
+ case XPATH_NUMBER:
+ ret = PyFloat_FromDouble(obj->floatval);
+ break;
+ case XPATH_STRING:
+ ret = PyString_FromString((char *) obj->stringval);
+ break;
+ case XPATH_POINT:
+ case XPATH_RANGE:
+ case XPATH_LOCATIONSET:
+ default:
+#ifdef DEBUG
+ printf("Unable to convert XPath object type %d\n", obj->type);
+#endif
+ Py_INCREF(Py_None);
+ ret = Py_None;
+ }
+ xmlXPathFreeObject(obj);
+ return (ret);
+}
+
+xmlXPathObjectPtr
+libxml_xmlXPathObjectPtrConvert(PyObject * obj)
+{
+ xmlXPathObjectPtr ret = NULL;
+
+#ifdef DEBUG
+ printf("libxml_xmlXPathObjectPtrConvert: obj = %p\n", obj);
+#endif
+ if (obj == NULL) {
+ return (NULL);
+ }
+ if PyFloat_Check
+ (obj) {
+ ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj));
+ } else if PyInt_Check(obj) {
+
+ ret = xmlXPathNewFloat((double) PyInt_AS_LONG(obj));
+
+ } else if PyBool_Check (obj) {
+
+ if (obj == Py_True) {
+ ret = xmlXPathNewBoolean(1);
+ }
+ else {
+ ret = xmlXPathNewBoolean(0);
+ }
+
+ } else if PyString_Check
+ (obj) {
+ xmlChar *str;
+
+ str = xmlStrndup((const xmlChar *) PyString_AS_STRING(obj),
+ PyString_GET_SIZE(obj));
+ ret = xmlXPathWrapString(str);
+ } else if PyList_Check
+ (obj) {
+ int i;
+ PyObject *node;
+ xmlNodePtr cur;
+ xmlNodeSetPtr set;
+
+ set = xmlXPathNodeSetCreate(NULL);
+
+ for (i = 0; i < PyList_Size(obj); i++) {
+ node = PyList_GetItem(obj, i);
+ if ((node == NULL) || (node->ob_type == NULL))
+ continue;
+
+ cur = NULL;
+ if (PyCObject_Check(node)) {
+#ifdef DEBUG
+ printf("Got a CObject\n");
+#endif
+ cur = PyxmlNode_Get(node);
+ } else if (PyInstance_Check(node)) {
+ PyInstanceObject *inst = (PyInstanceObject *) node;
+ PyObject *name = inst->in_class->cl_name;
+
+ if PyString_Check
+ (name) {
+ char *type = PyString_AS_STRING(name);
+ PyObject *wrapper;
+
+ if (!strcmp(type, "xmlNode")) {
+ wrapper =
+ PyObject_GetAttrString(node, (char *) "_o");
+ if (wrapper != NULL) {
+ cur = PyxmlNode_Get(wrapper);
+ }
+ }
+ }
+ } else {
+#ifdef DEBUG
+ printf("Unknown object in Python return list\n");
+#endif
+ }
+ if (cur != NULL) {
+ xmlXPathNodeSetAdd(set, cur);
+ }
+ }
+ ret = xmlXPathWrapNodeSet(set);
+ } else {
+#ifdef DEBUG
+ printf("Unable to convert Python Object to XPath");
+#endif
+ }
+ Py_DECREF(obj);
+ return (ret);
+}
+
+PyObject *
+libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlNodePtrWrap: catal = %p\n", catal);
+#endif
+ if (catal == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) 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);
+}
+
+PyObject *
+libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp)
+{
+ PyObject *ret;
+
+#ifdef DEBUG
+ printf("libxml_xmlRegexpPtrWrap: regexp = %p\n", regexp);
+#endif
+ if (regexp == NULL) {
+ Py_INCREF(Py_None);
+ return (Py_None);
+ }
+ ret =
+ PyCObject_FromVoidPtrAndDesc((void *) regexp,
+ (char *) "xmlRegexpPtr", NULL);
+ return (ret);
+}