+Wed Jan 17 14:25:25 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+ * TODO: more stuff
+ * libxslt/transform.c: context position and size in for-each
+ * libxslt/xsltutils[ch] libxslt/makefile.am: added the util module
+ and put Error and Debug routines
+ * libxslt/xslt.c libxslt/transform.c libxslt/pattern.c: switched
+ to use the Debug calls, cleanup
+ * libxslt/xsltproc.c: added -v to enable debug printing
+
Tue Jan 16 17:17:17 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* TODO: started filling it :-(
- should transforms for a given stylesheet be thread clean,
or can a stylesheet be enriched with document specific
informations and cleaned up later ?
+ - seems that saving back XSLT stylesheet from a compiled form might
+ be a bit ugly ...
Import:
-> parse them
-> check the version stuff, design a separate module for error interfacing
and default handling, parsing vs. runtime, fatal / compat / warning,
and lack of optionnal features.
+
+Support Attribute value templates:
+ -> starts to be urgent. Design it in flexible ways but try to optimize
+ to handle most of it at the stylesheet parse time ...
libxslt_la_SOURCES = \
xslt.c \
xslt.h \
+ xsltutils.c \
+ xsltutils.h \
pattern.c \
pattern.h \
transform.c \
#include <libxml/parserInternals.h>
#include "xslt.h"
#include "xsltInternals.h"
+#include "xsltutils.h"
/* #define DEBUG_PARSING */
-#define TODO \
- xsltGenericError(xsltGenericErrorContext, \
- "Unimplemented block at %s:%d\n", \
- __FILE__, __LINE__);
-
-/*
- * To cleanup
- */
-xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
-
-/*
- * There is no XSLT specific error reporting module yet
- */
-#define xsltGenericError xmlGenericError
-#define xsltGenericErrorContext xmlGenericErrorContext
-
/*
* Types are private:
*/
}
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltCompilePattern : parsing '%s'\n", pattern);
#endif
return(-1);
}
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltAddTemplate: created template hash\n");
#endif
xmlHashAddEntry(style->templatesHash, name, pat);
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltAddTemplate: added new hash %s\n", name);
#endif
} else {
if (list == NULL) {
xmlHashAddEntry(style->templatesHash, name, pat);
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltAddTemplate: added new hash %s\n", name);
#endif
} else {
pat->next = list;
xmlHashUpdateEntry(style->templatesHash, name, pat, NULL);
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltAddTemplate: added head hash for %s\n", name);
#endif
} else {
list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
if (list == NULL) {
#ifdef DEBUG_MATCHING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltGetTemplate: empty set for %s\n", name);
#endif
return(NULL);
#include <libxml/HTMLtree.h>
#include "xslt.h"
#include "xsltInternals.h"
+#include "xsltutils.h"
#include "pattern.h"
#include "transform.h"
#define DEBUG_PROCESS
/*
- * To cleanup
- */
-xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
-void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
-
-/*
- * There is no XSLT specific error reporting module yet
- */
-#define xsltGenericError xmlGenericError
-#define xsltGenericErrorContext xmlGenericErrorContext
-
-/*
* Useful macros
*/
-#define TODO \
- xsltGenericError(xsltGenericErrorContext, \
- "Unimplemented block at %s:%d\n", \
- __FILE__, __LINE__);
-
-#define STRANGE \
- xsltGenericError(xsltGenericErrorContext, \
- "Internal error at %s:%d\n", \
- __FILE__, __LINE__);
-
-#define IS_XSLT_ELEM(n) \
- ((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE))
-
-#define IS_XSLT_NAME(n, val) \
- (xmlStrEqual((n)->name, (const xmlChar *) (val)))
-
#define IS_BLANK_NODE(n) \
(((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
return;
}
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltValueOf: select %s\n", prop);
#endif
}
#ifdef DEBUG_PROCESS
else
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltValueOf: result %s\n", res->stringval);
#endif
error:
break;
default:
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltDefaultProcessOneNode: skipping node type %d\n",
node->type);
#endif
node = node->next;
if (delete != NULL) {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltDefaultProcessOneNode: removing ignorable blank node\n");
#endif
xmlUnlinkNode(delete);
return;
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyTemplates: node: %s\n", node->name);
#endif
prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE);
*/
if (insert == NULL) {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyOneTemplate: insert == NULL !\n");
#endif
return;
*/
if (delete != NULL) {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyOneTemplate: removing ignorable blank node\n");
#endif
xmlUnlinkNode(delete);
ctxt->insert = insert;
xsltAttribute(ctxt, node, cur);
ctxt->insert = oldInsert;
+ } else if (IS_XSLT_NAME(cur, "element")) {
+ ctxt->insert = insert;
+ xsltAttribute(ctxt, node, cur);
+ ctxt->insert = oldInsert;
} else {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyOneTemplate: found xslt:%s\n", cur->name);
#endif
TODO
*/
if (!(IS_BLANK_NODE(cur))) {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyOneTemplate: copy text %s\n", cur->content);
#endif
copy = xmlCopyNode(cur, 0);
}
} else if (cur->type == XML_ELEMENT_NODE) {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltApplyOneTemplate: copy node %s\n", cur->name);
#endif
copy = xsltCopyNode(ctxt, cur, insert);
return;
}
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltIf: test %s\n", prop);
#endif
doit = res->boolval;
else {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltIf: test didn't evaluate to a boolean\n");
#endif
goto error;
}
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltIf: test evaluate to %d\n", doit);
#endif
if (doit) {
xmlNodePtr replacement;
xmlNodeSetPtr list = NULL, oldlist;
xmlXPathParserContextPtr xpathParserCtxt;
- int i;
+ int i, oldProximityPosition, oldContextSize;
if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
return;
return;
}
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltForEach: select %s\n", prop);
#endif
list = res->nodesetval;
else {
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltForEach: select didn't evaluate to a node list\n");
#endif
goto error;
}
#ifdef DEBUG_PROCESS
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltForEach: select evaluate to %d nodes\n", list->nodeNr);
#endif
/* TODO: handle and skip the xsl:sort */
oldlist = ctxt->nodeList;
ctxt->nodeList = list;
+ oldContextSize = ctxt->xpathCtxt->contextSize;
+ oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
+ ctxt->xpathCtxt->contextSize = list->nodeNr;
for (i = 0;i < list->nodeNr;i++) {
ctxt->node = list->nodeTab[i];
+ ctxt->xpathCtxt->proximityPosition = i + 1;
xsltApplyOneTemplate(ctxt, list->nodeTab[i], replacement);
}
ctxt->nodeList = oldlist;
+ ctxt->xpathCtxt->contextSize = oldContextSize;
+ ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
error:
if (xpathParserCtxt != NULL)
if (template == NULL) {
#ifdef DEBUG_PROCESS
if (node->type == XML_DOCUMENT_NODE)
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltProcessOneNode: no template found for /\n");
else
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltProcessOneNode: no template found for %s\n", node->name);
#endif
#include "xslt.h"
#include "xsltInternals.h"
#include "pattern.h"
+#include "xsltutils.h"
-/* #define DEBUG_PARSING */
-
-/*
- * To cleanup
- */
-xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
-
-/*
- * There is no XSLT specific error reporting module yet
- */
-#define xsltGenericError xmlGenericError
-#define xsltGenericErrorContext xmlGenericErrorContext
+#define DEBUG_PARSING
/*
* Useful macros
*/
-#define IS_XSLT_ELEM(n) \
- ((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE))
-
-#define IS_XSLT_NAME(n, val) \
- (xmlStrEqual((n)->name, (const xmlChar *) (val)))
-
#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
((c) == 0x0D))
#define IS_BLANK_NODE(n) \
(((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
-#define TODO \
- xsltGenericError(xsltGenericErrorContext, \
- "Unimplemented block at %s:%d\n", \
- __FILE__, __LINE__);
-
-#define STRANGE \
- xsltGenericError(xsltGenericErrorContext, \
- "Internal error at %s:%d\n", \
- __FILE__, __LINE__);
/************************************************************************
* *
element = xmlStrndup(element, end - element);
if (element) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"add cdata section output element %s\n", element);
#endif
xmlHashAddEntry(style->stripSpaces, element, "cdata");
element = xmlStrndup(element, end - element);
if (element) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"add preserved space element %s\n", element);
#endif
xmlHashAddEntry(style->stripSpaces, element, "preserve");
element = xmlStrndup(element, end - element);
if (element) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"add stripped space element %s\n", element);
#endif
xmlHashAddEntry(style->stripSpaces, element, "strip");
while (cur != NULL) {
if (delete != NULL) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTemplate: removing ignorable blank node\n");
#endif
xmlUnlinkNode(delete);
}
if (delete != NULL) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTemplate: removing ignorable blank node\n");
#endif
xmlUnlinkNode(delete);
}
if (!(IS_XSLT_ELEM(cur))) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTop : found foreign element %s\n",
cur->name);
#endif
}
if (!(IS_XSLT_ELEM(cur))) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTop : found foreign element %s\n",
cur->name);
#endif
cur = cur->next;
}
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"parsed %d templates\n", templates);
#endif
}
}
ret->doc = doc;
- if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "stylesheet"))) {
+ if ((IS_XSLT_ELEM(cur)) &&
+ ((IS_XSLT_NAME(cur, "stylesheet")) ||
+ (IS_XSLT_NAME(cur, "transform")))) {
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetDoc : found stylesheet\n");
#endif
}
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetDoc : document is stylesheet\n");
#endif
return(NULL);
#ifdef DEBUG_PARSING
- xsltGenericError(xsltGenericErrorContext,
+ xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetFile : parse %s\n", filename);
#endif
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
static int debug = 0;
LIBXML_TEST_VERSION
for (i = 1; i < argc ; i++) {
- if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
+ if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
debug++;
+ } else if ((!strcmp(argv[i], "-v")) ||
+ (!strcmp(argv[i], "-verbose")) ||
+ (!strcmp(argv[i], "--verbose"))) {
+ xsltSetGenericDebugFunc(stderr, NULL);
+ }
}
xmlSubstituteEntitiesDefault(1);
for (i = 1; i < argc ; i++) {
--- /dev/null
+/*
+ * xsltutils.c: Utilities for the XSL Transformation 1.0 engine
+ *
+ * Reference:
+ * http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@imag.fr
+ */
+
+#include "xsltconfig.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/xmlerror.h>
+#include "xsltutils.h"
+
+
+/************************************************************************
+ * *
+ * Handling of out of context errors *
+ * *
+ ************************************************************************/
+
+/**
+ * xsltGenericErrorDefaultFunc:
+ * @ctx: an error context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Default handler for out of context error messages.
+ */
+void
+xsltGenericErrorDefaultFunc(void *ctx, const char *msg, ...) {
+ va_list args;
+
+ if (xsltGenericErrorContext == NULL)
+ xsltGenericErrorContext = (void *) stderr;
+
+ va_start(args, msg);
+ vfprintf((FILE *)xsltGenericErrorContext, msg, args);
+ va_end(args);
+}
+
+xmlGenericErrorFunc xsltGenericError = xsltGenericErrorDefaultFunc;
+void *xsltGenericErrorContext = NULL;
+
+
+/**
+ * xsltSetGenericErrorFunc:
+ * @ctx: the new error handling context
+ * @handler: the new handler function
+ *
+ * Function to reset the handler and the error context for out of
+ * context error messages.
+ * This simply means that @handler will be called for subsequent
+ * error messages while not parsing nor validating. And @ctx will
+ * be passed as first argument to @handler
+ * One can simply force messages to be emitted to another FILE * than
+ * stderr by setting @ctx to this file handle and @handler to NULL.
+ */
+void
+xsltSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
+ xsltGenericErrorContext = ctx;
+ if (handler != NULL)
+ xsltGenericError = handler;
+ else
+ xsltGenericError = xsltGenericErrorDefaultFunc;
+}
+
+/**
+ * xsltGenericDebugDefaultFunc:
+ * @ctx: an error context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Default handler for out of context error messages.
+ */
+void
+xsltGenericDebugDefaultFunc(void *ctx, const char *msg, ...) {
+ va_list args;
+
+ if (xsltGenericDebugContext == NULL)
+ return;
+
+ va_start(args, msg);
+ vfprintf((FILE *)xsltGenericDebugContext, msg, args);
+ va_end(args);
+}
+
+xmlGenericErrorFunc xsltGenericDebug = xsltGenericDebugDefaultFunc;
+void *xsltGenericDebugContext = NULL;
+
+
+/**
+ * xsltSetGenericDebugFunc:
+ * @ctx: the new error handling context
+ * @handler: the new handler function
+ *
+ * Function to reset the handler and the error context for out of
+ * context error messages.
+ * This simply means that @handler will be called for subsequent
+ * error messages while not parsing nor validating. And @ctx will
+ * be passed as first argument to @handler
+ * One can simply force messages to be emitted to another FILE * than
+ * stderr by setting @ctx to this file handle and @handler to NULL.
+ */
+void
+xsltSetGenericDebugFunc(void *ctx, xmlGenericErrorFunc handler) {
+ xsltGenericDebugContext = ctx;
+ if (handler != NULL)
+ xsltGenericDebug = handler;
+ else
+ xsltGenericDebug = xsltGenericDebugDefaultFunc;
+}
+
--- /dev/null
+/*
+ * xsltutils.h: interfaces for the utilities module of the XSLT engine
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@w3.org
+ */
+
+#ifndef __XML_XSLTUTILS_H__
+#define __XML_XSLTUTILS_H__
+
+#include <libxml/xpath.h>
+#include <libxml/xmlerror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * To cleanup
+ */
+xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
+void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
+
+/*
+ * Useful macros
+ */
+
+#define TODO \
+ xsltGenericError(xsltGenericErrorContext, \
+ "Unimplemented block at %s:%d\n", \
+ __FILE__, __LINE__);
+
+#define STRANGE \
+ xsltGenericError(xsltGenericErrorContext, \
+ "Internal error at %s:%d\n", \
+ __FILE__, __LINE__);
+
+#define IS_XSLT_ELEM(n) \
+ ((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE))
+
+#define IS_XSLT_NAME(n, val) \
+ (xmlStrEqual((n)->name, (const xmlChar *) (val)))
+
+
+/*
+ * XSLT specific error and debug reporting functions
+ */
+extern xmlGenericErrorFunc xsltGenericError;
+extern void *xsltGenericErrorContext;
+extern xmlGenericErrorFunc xsltGenericDebug;
+extern void *xsltGenericDebugContext;
+
+void xsltSetGenericErrorFunc (void *ctx,
+ xmlGenericErrorFunc handler);
+void xsltSetGenericDebugFunc (void *ctx,
+ xmlGenericErrorFunc handler);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_XSLTUTILS_H__ */
+