reactivated xsltMatchPattern() since this is really something one may want
authorDaniel Veillard <veillard@src.gnome.org>
Mon, 4 Feb 2002 18:51:53 +0000 (18:51 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Mon, 4 Feb 2002 18:51:53 +0000 (18:51 +0000)
* libxslt/pattern.[ch] doc/libxslt-api.xml doc/libxslt-refs.xml:
  reactivated xsltMatchPattern() since this is really something
  one may want to have access to in an extension function.
* Makefile.am configure.in python/Makefile.am python/generator.py
  python/libxml_wrap.h python/libxsl.py python/libxslt-python-api.xml
  python/libxslt.c python/libxslt_wrap.h python/libxsltclass.txt
  python/types.c: started working on the python bindings, borrowed
  most of the work done for libxml2, most of the generator code
  is similar. Commit at the point where this compiles cleanly and
  "import libxslt" doesn't yield any missing entry point.
Daniel

16 files changed:
ChangeLog
Makefile.am
configure.in
doc/libxslt-api.xml
doc/libxslt-refs.xml
libxslt/pattern.c
libxslt/pattern.h
python/Makefile.am [new file with mode: 0644]
python/generator.py [new file with mode: 0755]
python/libxml_wrap.h [new file with mode: 0644]
python/libxsl.py [new file with mode: 0644]
python/libxslt-python-api.xml [new file with mode: 0644]
python/libxslt.c [new file with mode: 0644]
python/libxslt_wrap.h [new file with mode: 0644]
python/libxsltclass.txt [new file with mode: 0644]
python/types.c [new file with mode: 0644]

index 587473f..3e19e65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Mon Feb  4 19:47:32 CET 2002 Daniel Veillard <daniel@veillard.com>
+
+       * libxslt/pattern.[ch] doc/libxslt-api.xml doc/libxslt-refs.xml:
+         reactivated xsltMatchPattern() since this is really something
+         one may want to have access to in an extension function.
+       * Makefile.am configure.in python/Makefile.am python/generator.py
+         python/libxml_wrap.h python/libxsl.py python/libxslt-python-api.xml
+         python/libxslt.c python/libxslt_wrap.h python/libxsltclass.txt
+         python/types.c: started working on the python bindings, borrowed
+         most of the work done for libxml2, most of the generator code
+         is similar. Commit at the point where this compiles cleanly and
+         "import libxslt" doesn't yield any missing entry point.
+
 Wed Jan 30 12:46:41 CET 2002 Daniel Veillard <daniel@veillard.com>
 
        * libxslt/pattern.c: patch from Charles Bozeman to support
index 2872282..19b7d07 100644 (file)
@@ -5,15 +5,17 @@ SUBDIRS = \
        breakpoint \
        libexslt \
        xsltproc \
-       tests \
-       doc
+       doc \
+       python \
+       tests
 else
 SUBDIRS = \
        libxslt \
        libexslt \
        xsltproc \
-       tests \
-       doc
+       doc \
+       python \
+       tests
 endif
 
 confexecdir=$(libdir)
index 9f573c7..7f296ec 100644 (file)
@@ -130,6 +130,54 @@ AC_CHECK_PROG(PERL, perl, perl, false)
 AM_CONDITIONAL(WITH_PERL, test "$PERL" != "false")
 
 dnl
+dnl check for python
+dnl
+
+PYTHON=
+PYTHON_VERSION=
+PYTHON_INCLUDES=
+PYTHON_SITE_PACKAGES=
+AC_ARG_WITH(python, [  --with-python[=DIR]    Build Python bindings if found])
+if test "$with_python" != "no" ; then
+    if test -x "$with_python/bin/python"
+    then
+        echo Found python in $with_python/bin/python
+        PYTHON="$with_python/bin/python"
+    else
+       AC_PATH_PROG(PYTHON, python python2.2 python2.1 python2.0 python1.6 python1.5)
+    fi
+    if test "$PYTHON" != ""
+    then
+        PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[[0:3]]"`
+       echo Found Python version $PYTHON_VERSION
+    fi
+    if test "$PYTHON_VERSION" != ""
+    then
+       if test -r $with_python/include/python$PYTHON_VERSION/Python.h -a \
+          -d $with_python/lib/python$PYTHON_VERSION/site-packages
+       then
+           PYTHON_INCLUDES=$with_python/include/python$PYTHON_VERSION
+           PYTHON_SITE_PACKAGES=$with_python/lib/python$PYTHON_VERSION/site-packages
+       else
+           if test -r $prefix/include/python$PYTHON_VERSION/Python.h
+           then
+               PYTHON_INCLUDES='$(prefix)/include/python$(PYTHON_VERSION)'
+               PYTHON_SITE_PACKAGES='$(prefix)/lib/python$(PYTHON_VERSION)/site-packages'
+           else
+               if test -r /usr/include/python$PYTHON_VERSION/Python.h
+               then
+                   PYTHON_INCLUDES=/usr/include/python$PYTHON_VERSION
+                   PYTHON_SITE_PACKAGES=/usr/lib/python$PYTHON_VERSION/site-packages
+               else
+                   echo could not find python$PYTHON_VERSION/Python.h
+               fi
+           fi
+       fi
+    fi
+fi
+AM_CONDITIONAL(WITH_PYTHON, test "$PYTHON_INCLUDES" != "")
+
+dnl
 dnl Debug for DV (-Wunreachable-code)
 dnl
 if test "${LOGNAME}" = "veillard" -a "`pwd`" = "/u/veillard/XSLT" ; then
@@ -292,6 +340,10 @@ AC_SUBST(XSLTPROCDV)
 AC_SUBST(XML_CONFIG)
 AC_SUBST(LIBXML_LIBS)
 AC_SUBST(LIBXML_CFLAGS)
+AC_SUBST(PYTHON)
+AC_SUBST(PYTHON_VERSION)
+AC_SUBST(PYTHON_INCLUDES)
+AC_SUBST(PYTHON_SITE_PACKAGES)
 
 XSLT_LIBDIR='-L${libdir}'
 
@@ -322,6 +374,7 @@ breakpoint/Makefile
 libexslt/Makefile
 libexslt/exsltconfig.h
 xsltproc/Makefile
+python/Makefile
 tests/Makefile
 tests/docs/Makefile
 tests/REC1/Makefile
index 73d93a5..88fcb49 100644 (file)
       <arg name='ctxt' type='xsltTransformContextPtr'/>
       <arg name='node' type='xmlNodePtr' info='a node in the source tree '/>
       <arg name='pattern' type='const xmlChar *' info='an XSLT pattern '/>
+      <arg name='ctxtdoc' type='xmlDocPtr'/>
+      <arg name='ctxtnode' type='xmlNodePtr'/>
     </function>
     <function name='xsltMessage' file='xsltutils'>
       <info>Process and xsl:message construct</info>
index 99b95a4..8335ddd 100644 (file)
       <ref name='xsltParseStylesheetDoc'/>
       <ref name='xsltLoadStylesheetPI'/>
       <ref name='xsltCompilePattern'/>
+      <ref name='xsltMatchPattern'/>
       <ref name='xsltNewTransformContext'/>
       <ref name='xsltApplyStylesheetUser'/>
       <ref name='xsltApplyStylesheet'/>
       <ref name='xsltTestCompMatchList'/>
       <ref name='xsltGetTemplate'/>
       <ref name='xsltMatchPattern'/>
+      <ref name='xsltMatchPattern'/>
       <ref name='xsltApplyStripSpaces'/>
       <ref name='xsltApplyOneTemplate'/>
       <ref name='xsltApplyOneTemplate'/>
index b5e4fd2..8396b57 100644 (file)
@@ -2036,24 +2036,27 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) {
         xsltFreeCompMatchList(style->commentMatch);
 }
 
-#if 0
 /**
  * xsltMatchPattern
  * @node: a node in the source tree
  * @pattern: an XSLT pattern
+ * @ctxtdoc:  context document (for namespaces)
+ * @ctxtnode:  context node (for namespaces)
  *
  * Determine if a node matches a pattern.
  */
 int
 xsltMatchPattern(xsltTransformContextPtr context,
                 xmlNodePtr node,
-                const xmlChar *pattern)
+                const xmlChar *pattern,
+                xmlDocPtr ctxtdoc,
+                xmlNodePtr ctxtnode)
 {
     int match = 0;
     xsltCompMatchPtr first, comp;
 
     if ((context != NULL) && (pattern != NULL)) {
-       first = xsltCompilePattern(pattern);
+       first = xsltCompilePattern(pattern, ctxtdoc, ctxtnode);
        for (comp = first; comp != NULL; comp = comp->next) {
            match = xsltTestCompMatch(context, comp, node, NULL, NULL);
            if (match)
@@ -2064,4 +2067,3 @@ xsltMatchPattern(xsltTransformContextPtr context,
     }
     return match;
 }
-#endif
index 3a382d5..f49c9f9 100644 (file)
@@ -49,11 +49,11 @@ xsltTemplatePtr     xsltGetTemplate         (xsltTransformContextPtr ctxt,
 void           xsltFreeTemplateHashes  (xsltStylesheetPtr style);
 void           xsltCleanupTemplates    (xsltStylesheetPtr style);
 
-#if 0
 int            xsltMatchPattern        (xsltTransformContextPtr ctxt,
                                         xmlNodePtr node,
-                                        const xmlChar *pattern);
-#endif
+                                        const xmlChar *pattern,
+                                        xmlDocPtr ctxtdoc,
+                                        xmlNodePtr ctxtnode);
 #ifdef __cplusplus
 }
 #endif
diff --git a/python/Makefile.am b/python/Makefile.am
new file mode 100644 (file)
index 0000000..bf0d6ff
--- /dev/null
@@ -0,0 +1,65 @@
+# SUBDIRS= . tests
+
+LIBS=-L../libxslt/.libs -L../libxslt -lxslt -L../libexslt/.libs -L../libexslt -lexslt $(PYTHON_SITE_PACKAGES)/_libxml.so $(LIBXML_LIBS)
+INCLUDES=-I/usr/include/python$(PYTHON_VERSION) -I$(PYTHON_INCLUDES) $(LIBXML_CFLAGS) -I$(top_srcdir)
+SHCFLAGS=$(INCLUDES) -Wall -fPIC -g
+LINK_FLAGS= -shared
+DOCS_DIR = $(prefix)/share/doc/libxslt-python-$(LIBXML_VERSION)
+
+DOCS = TODO libxsltclass.txt
+
+EXTRA_DIST =                   \
+       libxslt.c               \
+       types.c                 \
+       generator.py            \
+       libxml_wrap.h           \
+       libxslt_wrap.h          \
+       libxsl.py               \
+       libxslt-python-api.xml  \
+       $(DOCS)
+
+if WITH_PYTHON
+all: _libxslt.so libxslt.py
+
+libxslt.py: $(srcdir)/libxsl.py libxsltclass.py
+       cat $(srcdir)/libxsl.py libxsltclass.py > libxslt.py
+
+_libxslt.so: libxslt.o libxslt-py.o types.o
+       $(CC) $(LINK_FLAGS) libxslt.o libxslt-py.o types.o $(LIBS) -o _libxslt.so
+else
+all: 
+endif
+
+libxslt.o: libxslt.c libxslt-export.c libxslt_wrap.h
+       $(CC) $(SHCFLAGS) -c -o libxslt.o $(srcdir)/libxslt.c
+
+types.o: types.c libxslt_wrap.h
+       $(CC) $(SHCFLAGS) -c -o types.o $(srcdir)/types.c
+
+libxslt-py.o: libxslt-py.c libxslt-py.h libxslt_wrap.h
+       $(CC) $(SHCFLAGS) -c -o libxslt-py.o $(srcdir)/libxslt-py.c
+
+GENERATE = generator.py
+API_DESC = $(top_srcdir)/doc/libxslt-api.xml $(srcdir)/libxslt-python-api.xml
+GENERATED= $(srcdir)/libxsltclass.py \
+           $(srcdir)/libxslt-export.c \
+          $(srcdir)/libxslt-py.c \
+          $(srcdir)/libxslt-py.h
+
+$(GENERATED): $(srcdir)/$(GENERATE) $(API_DESC)
+       cd $(srcdir) && $(PYTHON) $(GENERATE)
+
+tests: all
+       cd tests && $(MAKE) tests
+
+clean:
+       rm -f $(GENERATED) *.o _libxslt.so *.pyc libxslt.py
+
+install-data-local:
+       $(mkinstalldirs) $(DESTDIR)$(PYTHON_SITE_PACKAGES)
+       -@INSTALL@ -m 0644 libxslt.py $(DESTDIR)$(PYTHON_SITE_PACKAGES)
+       -@INSTALL@ -m 0755 _libxslt.so $(DESTDIR)$(PYTHON_SITE_PACKAGES)
+       $(mkinstalldirs) $(DESTDIR)$(DOCS_DIR)
+       -@(for doc in $(DOCS) ; \
+          do @INSTALL@ -m 0644 $$doc $(DESTDIR)$(DOCS_DIR) ; done)
+
diff --git a/python/generator.py b/python/generator.py
new file mode 100755 (executable)
index 0000000..f9a3651
--- /dev/null
@@ -0,0 +1,876 @@
+#!/usr/bin/python -u
+#
+# generate python wrappers from the XML API description
+#
+
+functions = {}
+
+import string
+
+#######################################################################
+#
+#  That part if purely the API acquisition phase from the
+#  XML API description
+#
+#######################################################################
+import os
+import xmllib
+try:
+    import sgmlop
+except ImportError:
+    sgmlop = None # accelerator not available
+
+debug = 0
+
+if sgmlop:
+    class FastParser:
+       """sgmlop based XML parser.  this is typically 15x faster
+          than SlowParser..."""
+
+       def __init__(self, target):
+
+           # setup callbacks
+           self.finish_starttag = target.start
+           self.finish_endtag = target.end
+           self.handle_data = target.data
+
+           # activate parser
+           self.parser = sgmlop.XMLParser()
+           self.parser.register(self)
+           self.feed = self.parser.feed
+           self.entity = {
+               "amp": "&", "gt": ">", "lt": "<",
+               "apos": "'", "quot": '"'
+               }
+
+       def close(self):
+           try:
+               self.parser.close()
+           finally:
+               self.parser = self.feed = None # nuke circular reference
+
+       def handle_entityref(self, entity):
+           # <string> entity
+           try:
+               self.handle_data(self.entity[entity])
+           except KeyError:
+               self.handle_data("&%s;" % entity)
+
+else:
+    FastParser = None
+
+
+class SlowParser(xmllib.XMLParser):
+    """slow but safe standard parser, based on the XML parser in
+       Python's standard library."""
+
+    def __init__(self, target):
+       self.unknown_starttag = target.start
+       self.handle_data = target.data
+       self.unknown_endtag = target.end
+       xmllib.XMLParser.__init__(self)
+
+def getparser(target = None):
+    # get the fastest available parser, and attach it to an
+    # unmarshalling object.  return both objects.
+    if target == None:
+       target = docParser()
+    if FastParser:
+       return FastParser(target), target
+    return SlowParser(target), target
+
+class docParser:
+    def __init__(self):
+        self._methodname = None
+       self._data = []
+       self.in_function = 0
+
+    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']
+
+
+    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):
+    global functions
+
+    functions[name] = (desc, ret, args, file)
+
+#######################################################################
+#
+#  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,
+}
+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':  ('i', None, "int", "int", "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, "charPtr", "char *", "libxml_"),
+    'xmlChar *':  ('z', None, "xmlCharPtr", "xmlChar *", "libxml_"),
+    'const xmlChar *':  ('z', None, "xmlCharPtr", "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_"),
+    'xmlXPathContext *':  ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "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_"),
+    'xsltTransformContextPtr':  ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
+    'xsltTransformContext *':  ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "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[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":
+           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])
+        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("    { \"%s\", libxslt_%s, METH_VARARGS },\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, PyObject *args) {\n" % (name))
+    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, \"%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
+
+try:
+    f = open("../doc/libxslt-api.xml")
+    data = f.read()
+    (parser, target)  = getparser()
+    parser.feed(data)
+    parser.close()
+except IOError, msg:
+    print file, ":", 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("libxslt-python-api.xml")
+    data = f.read()
+    (parser, target)  = getparser()
+    parser.feed(data)
+    parser.close()
+except IOError, msg:
+    print file, ":", 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 \"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: %s" % (unknown_types.keys())
+
+#######################################################################
+#
+#  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"),
+    "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
+    "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
+    "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
+}
+
+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"),
+}
+
+converter_type = {
+    "xmlXPathObjectPtr": "xpathObjectRet(%s)",
+}
+
+primary_classes = []
+
+classes_ancestor = {
+}
+classes_destructors = {
+    "xpathContext": "xmlXPathFreeContext",
+    "parserCtxt": "xmlFreeParserCtxt",
+}
+
+function_classes = {}
+
+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 = []
+classes_list = []
+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] = ()
+
+def nameFixup(function, 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: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
+
+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:3] == "xml" 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:3] == "xml" 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] == "html" 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] == "html" 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) >= 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)
+       if found == 1:
+           break
+    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")
+
+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:
+         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')
+
+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("_libxslt.%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 ");
+               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")
+           classes.write("        if self._o != None:\n")
+           classes.write("            _libxslt.%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("_libxslt.%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 ");
+                   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");
+
+txt.close()
+classes.close()
diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h
new file mode 100644 (file)
index 0000000..679260a
--- /dev/null
@@ -0,0 +1,59 @@
+#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 PyparserCtxt_Get(v) (((v) == Py_None) ? NULL : \
+        (((PyparserCtxt_Object *)(v))->obj))
+
+typedef struct {
+    PyObject_HEAD
+    xmlParserCtxtPtr obj;
+} PyparserCtxt_Object;
+
+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_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_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj);
+
+xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
diff --git a/python/libxsl.py b/python/libxsl.py
new file mode 100644 (file)
index 0000000..2d33b7f
--- /dev/null
@@ -0,0 +1,7 @@
+import libxml2
+import _libxslt
+
+#
+# Everything below this point is automatically generated
+#
+
diff --git a/python/libxslt-python-api.xml b/python/libxslt-python-api.xml
new file mode 100644 (file)
index 0000000..bd0f219
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<api name='libxslt-python'>
+  <files>
+    <file name='python'>
+    </file>
+  </files>
+  <symbols>
+  <!--
+    <function name='xsltRegisterXPathFunction' file='python'>
+      <info>Register a Python written function to the XPath interpreter</info>
+      <return type='int' info="1 in case of success, 0 or -1 in case of error"/>
+      <arg name='ctx' type='xmlXPathContextPtr' info='the xpathContext'/>
+      <arg name='name' type='xmlChar *' info='the function name'/>
+      <arg name='ns_uri' type='xmlChar *' info='the namespace or NULL'/>
+      <arg name='f' type='pythonObject' info='the python function'/>
+    </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>
+    -->
+  </symbols>
+</api>
diff --git a/python/libxslt.c b/python/libxslt.c
new file mode 100644 (file)
index 0000000..4c36794
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * libxslt.c: this modules 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.
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+#include <Python.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include "libxslt_wrap.h"
+#include "libxslt-py.h"
+
+/* #define DEBUG */
+/* #define DEBUG_XPATH */
+/* #define DEBUG_ERROR */
+/* #define DEBUG_MEMORY */
+
+/************************************************************************
+ *                                                                     *
+ *             Memory debug interface                                  *
+ *                                                                     *
+ ************************************************************************/
+
+extern void xmlMemFree(void *ptr);
+extern void *xmlMemMalloc(size_t size);
+extern void *xmlMemRealloc(void *ptr,size_t size);
+extern char *xmlMemoryStrdup(const char *str);
+
+static int libxsltMemoryDebugActivated = 0;
+static long libxsltMemoryAllocatedBase = 0;
+
+static int libxsltMemoryDebug = 0;
+static xmlFreeFunc freeFunc = NULL;
+static xmlMallocFunc mallocFunc = NULL;
+static xmlReallocFunc reallocFunc = NULL;
+static xmlStrdupFunc strdupFunc = NULL;
+
+PyObject *
+libxslt_xmlDebugMemory(PyObject *self, PyObject *args) {
+    int activate;
+    PyObject *py_retval;
+    long ret;
+
+    if (!PyArg_ParseTuple(args, "i:xmlDebugMemory", &activate))
+        return(NULL);
+
+#ifdef DEBUG_MEMORY
+    printf("libxslt_xmlDebugMemory(%d) called\n", activate);
+#endif
+
+    if (activate != 0) {
+       if (libxsltMemoryDebug == 0) {
+           /*
+            * First initialize the library and grab the old memory handlers
+            * and switch the library to memory debugging
+            */
+           xmlMemGet((xmlFreeFunc *) &freeFunc,
+                     (xmlMallocFunc *)&mallocFunc,
+                     (xmlReallocFunc *)&reallocFunc,
+                     (xmlStrdupFunc *) &strdupFunc);
+           if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) &&
+               (reallocFunc == xmlMemRealloc) &&
+               (strdupFunc == xmlMemoryStrdup)) {
+               libxsltMemoryAllocatedBase = xmlMemUsed();
+           } else {
+               ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc,
+                                        xmlMemRealloc, xmlMemoryStrdup);
+               if (ret < 0)
+                   goto error;
+               libxsltMemoryAllocatedBase = xmlMemUsed();
+           }
+           xmlInitParser();
+           ret = 0;
+       } else if (libxsltMemoryDebugActivated == 0) {
+           libxsltMemoryAllocatedBase = xmlMemUsed();
+           ret = 0;
+       } else {
+           ret = xmlMemUsed() - libxsltMemoryAllocatedBase;
+       }
+       libxsltMemoryDebug = 1;
+       libxsltMemoryDebugActivated = 1;
+    } else {
+       if (libxsltMemoryDebugActivated == 1)
+           ret = xmlMemUsed() - libxsltMemoryAllocatedBase;
+       else
+           ret = 0;
+       libxsltMemoryDebugActivated = 0;
+    }
+error:
+    py_retval = libxml_longWrap(ret);
+    return(py_retval);
+}
+
+PyObject *
+libxslt_xmlDumpMemory(PyObject *self, PyObject *args) {
+
+    if (libxsltMemoryDebug != 0)
+       xmlMemoryDump();
+    Py_INCREF(Py_None);
+    return(Py_None);
+}
+
+
+/************************************************************************
+ *                                                                     *
+ *                     The registration stuff                          *
+ *                                                                     *
+ ************************************************************************/
+static PyMethodDef libxsltMethods[] = {
+#include "libxslt-export.c"
+};
+
+void init_libxslt(void) {
+    PyObject *m;
+    m = Py_InitModule("_libxslt", libxsltMethods);
+    /* libxslt_xmlErrorInitialize(); */
+}
+
diff --git a/python/libxslt_wrap.h b/python/libxslt_wrap.h
new file mode 100644 (file)
index 0000000..b03b633
--- /dev/null
@@ -0,0 +1,38 @@
+#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;
+
+PyObject * libxslt_xsltTransformContextPtr(xsltTransformContextPtr ctxt);
+PyObject * libxslt_xsltStylesheetPtr(xsltStylesheetPtr ctxt);
diff --git a/python/libxsltclass.txt b/python/libxsltclass.txt
new file mode 100644 (file)
index 0000000..ce1f27b
--- /dev/null
@@ -0,0 +1,93 @@
+          Generated Classes for libxslt-python
+
+#
+# Global functions of the module
+#
+
+
+# functions from module extensions
+registerTestModule()
+unregisterExtModule()
+unregisterExtModuleElement()
+unregisterExtModuleFunction()
+unregisterExtModuleTopLevel()
+
+# functions from module extra
+registerAllExtras()
+
+# functions from module functions
+registerAllFunctions()
+
+# functions from module transform
+setXIncludeDefault()
+xincludeDefault()
+
+# functions from module xslt
+cleanupGlobals()
+
+# functions from module xsltInternals
+isBlank()
+
+# functions from module xsltutils
+calibrateAdjust()
+nsProp()
+timestamp()
+xslDropCall()
+
+
+#
+# Set of classes of the module
+#
+
+Class transformCtxt()
+
+    # functions from module attributes
+    applyAttributeSet()
+
+    # functions from module documents
+    freeDocuments()
+
+    # functions from module extensions
+    freeCtxtExts()
+    initCtxtExts()
+    shutdownCtxtExts()
+
+    # functions from module extra
+    registerExtras()
+
+    # functions from module imports
+    findElemSpaceHandling()
+    needElemSpaceHandling()
+
+    # functions from module namespaces
+    copyNamespace()
+    copyNamespaceList()
+    namespace()
+    specialNamespace()
+
+    # functions from module pattern
+    matchPattern()
+
+    # functions from module templates
+    attrListTemplateProcess()
+    attrTemplateProcess()
+    evalAttrValueTemplate()
+    evalTemplateString()
+
+    # functions from module transform
+    applyStripSpaces()
+    freeTransformContext()
+    registerAllElement()
+
+    # functions from module variables
+    evalGlobalVariables()
+    evalOneUserParam()
+    freeGlobalVariables()
+    parseStylesheetParam()
+    parseStylesheetVariable()
+    quoteOneUserParam()
+    variableLookup()
+
+    # functions from module xsltutils
+    message()
+Class stylesheet()
diff --git a/python/types.c b/python/types.c
new file mode 100644 (file)
index 0000000..29fe84f
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * types.c: converter functions between the internal representation
+ *          and the Python objects
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+#include "libxslt_wrap.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_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(str);
+    xmlFree(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(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, "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, "xmlNodePtr", 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, "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, "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, "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, "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, "xmlXPathContextPtr",
+                                      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, "xmlParserCtxtPtr",
+                                      NULL);
+    return(ret);
+}
+
+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:
+           /* TODO !!!! Allocation problems */
+        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];
+                   /* TODO: try to cast directly to the proper node type */
+                   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(obj->stringval);
+           break;
+        case XPATH_POINT:
+        case XPATH_RANGE:
+        case XPATH_LOCATIONSET:
+       default:
+           printf("Unable to convert XPath object type %d\n", obj->type);
+           Py_INCREF(Py_None);
+           ret = Py_None;
+    }
+    xmlXPathFreeObject(obj);
+    return(ret);
+}
+
+xmlXPathObjectPtr
+libxml_xmlXPathObjectPtrConvert(PyObject * obj) {
+    xmlXPathObjectPtr ret;
+
+#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 PyString_Check(obj) {
+       xmlChar *str;
+
+       str = xmlStrndup((const xmlChar *)PyString_AS_STRING(obj),
+                        PyString_GET_SIZE(obj));
+       ret = xmlXPathWrapString(str);
+    } else {
+       printf("Unable to convert Python Object to XPath");
+    }
+    Py_DECREF(obj);
+    return(ret);
+}
+
+