diff --git a/ChangeLog b/ChangeLog index 9998026d..62500950 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Thu Feb 7 17:59:27 CET 2002 Daniel Veillard + + * xsltproc/xsltproc.c: small fix + * Makefile.am: cleanup + * python/tests/Makefile.am: avoid a problem with $(TESTS) + * python/generator.py python/libxml_wrap.h python/libxsl.py + python/libxslt.c python/libxsltclass.txt: augmented the + wrappers + * python/tests/pyxsltproc.py: rewrote xsltproc on top of the + libxslt-python API to get an estimate of what is missing + Wed Feb 6 23:34:10 CET 2002 Daniel Veillard * python/libxsl.py python/libxslt-python-api.xml python/libxslt.c diff --git a/Makefile.am b/Makefile.am index f578bc09..ef7ab876 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,8 +56,9 @@ tests: dummy cleantar: @(rm -f libxslt*.tar.gz) -rpm: cleantar dist - rpm -ta libxslt*.tar.gz +rpm: cleantar + @(unset CDPATH ; $(MAKE) dist && rpm -ta $(distdir).tar.gz) + pkgconfigdir=$(libdir)/pkgconfig pkgconfig_DATA = libxslt.pc diff --git a/python/generator.py b/python/generator.py index bf69805c..41c83bde 100755 --- a/python/generator.py +++ b/python/generator.py @@ -258,15 +258,18 @@ py_types = { '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_"), + '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_"), 'xsltStylesheetPtr': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"), 'xsltStylesheet *': ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"), + 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxslt_"), } py_return_types = { @@ -461,7 +464,10 @@ wrapper.close() print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap, failed, skipped); -print "Missing type converters: %s" % (unknown_types.keys()) +print "Missing type converters:" +for type in unknown_types.keys(): + print "%s:%d " % (type, len(unknown_types[type])), +print ####################################################################### # @@ -493,9 +499,9 @@ libxml2_classes_type = { "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"), + "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"), } classes_type = { @@ -503,15 +509,21 @@ classes_type = { "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": "xpathObjectRet(%s)", } -primary_classes = ["transformCtxt", "stylesheet"] +primary_classes = ["xpathParserContext", "xpathContext", "transformCtxt", "stylesheet"] classes_ancestor = { + "xpathContext" : "libxml2.xpathContext", + "xpathParserContext" : "libxml2.xpathParserContext", } classes_destructors = { "stylesheet": "xsltFreeStylesheet", @@ -737,7 +749,7 @@ if function_classes.has_key("None"): classes.write("\n"); elif libxml2_classes_type.has_key(ret[0]): classes.write(" if ret == None: return None\n"); - classes.write(" return "); + classes.write(" return libxml2."); classes.write(libxml2_classes_type[ret[0]][1] % ("ret")); classes.write("\n"); else: @@ -847,7 +859,7 @@ for classname in classes_list: classes.write("\n"); elif libxml2_classes_type.has_key(ret[0]): classes.write(" if ret == None: return None\n"); - classes.write(" return "); + classes.write(" return libxml2."); classes.write(libxml2_classes_type[ret[0]][1] % ("ret")); classes.write("\n"); elif converter_type.has_key(ret[0]): diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h index 679260a3..fb8b79e8 100644 --- a/python/libxml_wrap.h +++ b/python/libxml_wrap.h @@ -31,6 +31,14 @@ typedef struct { 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)) @@ -39,6 +47,17 @@ typedef struct { 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) ? NULL : (PyFile_AsFile(v)))) + PyObject * libxml_intWrap(int val); PyObject * libxml_longWrap(long val); PyObject * libxml_xmlCharPtrWrap(xmlChar *str); @@ -54,6 +73,8 @@ 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); xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj); diff --git a/python/libxsl.py b/python/libxsl.py index 85f24ddc..57e3d05b 100644 --- a/python/libxsl.py +++ b/python/libxsl.py @@ -1,6 +1,6 @@ import _libxml import _libxslt -from libxml2 import * +import libxml2 # # Everything below this point is automatically generated diff --git a/python/libxslt.c b/python/libxslt.c index f93dcf1e..7028c5ca 100644 --- a/python/libxslt.c +++ b/python/libxslt.c @@ -261,7 +261,7 @@ libxslt_xsltApplyStylesheet(PyObject *self, PyObject *args) { xmlDocPtr doc; PyObject *pyobj_doc; PyObject *pyobj_params; - const char **params; + const char **params = NULL; int len = 0, i = 0, j; PyObject *name; PyObject *value; @@ -305,20 +305,20 @@ libxslt_xsltApplyStylesheet(PyObject *self, PyObject *args) { Py_INCREF(Py_None); return(Py_None); } - } else { - params = NULL; } 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 (len > 0) { - for (i = 0;i < 2 * len;i++) { - if (params[i] != NULL) - xmlFree((char *)params[i]); + if (params != NULL) { + if (len > 0) { + for (i = 0;i < 2 * len;i++) { + if (params[i] != NULL) + xmlFree((char *)params[i]); + } + xmlFree(params); } - xmlFree(params); } return(py_retval); } @@ -354,5 +354,14 @@ void init_libxslt(void) { PyObject *m; m = Py_InitModule("_libxslt", libxsltMethods); /* libxslt_xmlErrorInitialize(); */ + /* + * Specific XSLT initializations + */ + /* xmlInitParser(); */ + xmlInitMemory(); + /* LIBXML_TEST_VERSION */ + xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + /* xmlDefaultSAXHandlerInit(); */ + xmlDefaultSAXHandler.cdataBlock = NULL; } diff --git a/python/libxsltclass.txt b/python/libxsltclass.txt index d3683ab2..0bb2798f 100644 --- a/python/libxsltclass.txt +++ b/python/libxsltclass.txt @@ -15,9 +15,6 @@ unregisterExtModuleTopLevel() # functions from module extra registerAllExtras() -# functions from module functions -registerAllFunctions() - # functions from module python cleanup() registerExtModuleFunction() @@ -46,6 +43,28 @@ xslDropCall() # Set of classes of the module # + + +Class xpathParserContext(libxml2.xpathParserContext) + + # functions from module extra + functionNodeSet() + + # functions from module functions + documentFunction() + elementAvailableFunction() + formatNumberFunction() + functionAvailableFunction() + generateIdFunction() + keyFunction() + systemPropertyFunction() + unparsedEntityURIFunction() + + +Class xpathContext(libxml2.xpathContext) + + # functions from module functions + registerAllFunctions() Class transformCtxt() # functions from module attributes @@ -98,6 +117,7 @@ Class transformCtxt() # functions from module xsltutils message() printErrorContext() + saveProfiling() Class stylesheet() # functions from module attributes @@ -152,4 +172,5 @@ Class stylesheet() # functions from module xsltutils saveResultToFd() + saveResultToFile() saveResultToFilename() diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am index 92fe6d23..df032649 100644 --- a/python/tests/Makefile.am +++ b/python/tests/Makefile.am @@ -1,6 +1,6 @@ EXAMPLE_DIR = $(prefix)/share/doc/libxslt-python-$(LIBXML_VERSION)/examples -TESTS= \ +TESTSPY= \ basic.py \ extfunc.py @@ -8,12 +8,15 @@ XMLS= \ test.xml \ test.xsl -EXTRA_DIST = $(TESTS) $(XMLS) +EXTRAS= \ + pyxsltproc.py + +EXTRA_DIST = $(TESTSPY) $(XMLS) if WITH_PYTHON -tests: $(TESTS) +tests: $(TESTSPY) -@(PYTHONPATH=".." ; export PYTHONPATH; \ - for test in $(TESTS) ; do echo "-- $$test" ; $(PYTHON) $$test ; done) + for test in $(TESTSPY) ; do echo "-- $$test" ; $(PYTHON) $$test ; done) else tests: endif @@ -23,6 +26,6 @@ clean: install-data-local: $(mkinstalldirs) $(DESTDIR)$(EXAMPLE_DIR) - -(for test in $(TESTS) $(XMLS); \ + -(for test in $(TESTSPY) $(XMLS); \ do @INSTALL@ -m 0644 $$test $(DESTDIR)$(EXAMPLE_DIR) ; done) diff --git a/python/tests/pyxsltproc.py b/python/tests/pyxsltproc.py new file mode 100755 index 00000000..fed201fd --- /dev/null +++ b/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 posix +import string +import libxml2 +import libxslt + +# Memory debug specific +libxml2.debugMemory(1) + +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 intput" + 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 = posix.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 + + cur = None + 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/xsltproc/xsltproc.c b/xsltproc/xsltproc.c index 4b68b216..16591e3e 100644 --- a/xsltproc/xsltproc.c +++ b/xsltproc/xsltproc.c @@ -114,7 +114,7 @@ static int errorno = 0; */ #if defined(HAVE_GETTIMEOFDAY) -static struct timeval begin, end; +static struct timeval begin, endtime; /* * startTimer: call where you want to start timing */ @@ -132,10 +132,10 @@ static void endTimer(const char *format, ...) long msec; va_list ap; - gettimeofday(&end, NULL); - msec = end.tv_sec - begin.tv_sec; + gettimeofday(&endtime, NULL); + msec = endtime.tv_sec - begin.tv_sec; msec *= 1000; - msec += (end.tv_usec - begin.tv_usec) / 1000; + msec += (endtime.tv_usec - begin.tv_usec) / 1000; #ifndef HAVE_STDARG_H #error "endTimer required stdarg functions" @@ -153,7 +153,7 @@ static void endTimer(const char *format, ...) * that. */ -clock_t begin, end; +clock_t begin, endtime; static void startTimer(void) { begin=clock(); @@ -163,8 +163,8 @@ static void endTimer(char *format, ...) long msec; va_list ap; - end=clock(); - msec = ((end-begin) * 1000) / CLOCKS_PER_SEC; + endtime=clock(); + msec = ((endtime-begin) * 1000) / CLOCKS_PER_SEC; #ifndef HAVE_STDARG_H #error "endTimer required stdarg functions" @@ -536,6 +536,11 @@ main(int argc, char **argv) i += 2; continue; } + if ((!strcmp(argv[i], "-stringparam")) || + (!strcmp(argv[i], "--stringparam"))) { + i += 2; + continue; + } if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { if (timing) startTimer();