Working on variables implementation:
authorDaniel Veillard <veillard@src.gnome.org>
Sat, 20 Jan 2001 17:02:16 +0000 (17:02 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Sat, 20 Jan 2001 17:02:16 +0000 (17:02 +0000)
- libxslt/transform.c libxslt/variables.[ch] libxslt/xslt.c
  libxslt/xsltInternals.h libxslt/xsltutils.h: changed a few
  structure to add an execution stack with variables. Tree
  valued variables still missing.
- TODO: updated
Daniel

ChangeLog
TODO
libxslt/transform.c
libxslt/variables.c
libxslt/variables.h
libxslt/xslt.c
libxslt/xsltInternals.h
libxslt/xsltutils.h

index 98ac63b..6a865dc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Sat Jan 20 17:59:20 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+       * libxslt/transform.c libxslt/variables.[ch] libxslt/xslt.c
+         libxslt/xsltInternals.h libxslt/xsltutils.h: changed a few
+         structure to add an execution stack with variables. Tree
+         valued variables still missing.
+       * TODO: updated
+
 Fri Jan 19 13:16:57 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
 
        * libxslt/xslt.c: check version on stylesheets
diff --git a/TODO b/TODO
index c4ed219..ec37cfd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -2,6 +2,7 @@ Design:
   - should transforms for a given stylesheet be thread clean,
     or can a stylesheet be enriched with document specific
     informations and cleaned up later ?
+    => currently stylesheet manipulation is not reentrant.
   - seems that saving back XSLT stylesheet from a compiled form might
     be a bit ugly ...
     
index 99aaa26..991c8bc 100644 (file)
@@ -29,6 +29,7 @@
 #include "xsltutils.h"
 #include "pattern.h"
 #include "transform.h"
+#include "variables.h"
 
 #define DEBUG_PROCESS
 
 #define IS_BLANK_NODE(n)                                               \
     (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
 
-/*
- * Types are private:
- */
-
-typedef enum xsltOutputType {
-    XSLT_OUTPUT_XML = 0,
-    XSLT_OUTPUT_HTML,
-    XSLT_OUTPUT_TEXT
-} xsltOutputType;
-
-typedef struct _xsltTransformContext xsltTransformContext;
-typedef xsltTransformContext *xsltTransformContextPtr;
-struct _xsltTransformContext {
-    xsltStylesheetPtr style;           /* the stylesheet used */
-    xsltOutputType type;               /* the type of output */
-
-    xmlDocPtr doc;                     /* the current doc */
-    xmlNodePtr node;                   /* the current node */
-    xmlNodeSetPtr nodeList;            /* the current node list */
-
-    xmlDocPtr output;                  /* the resulting document */
-    xmlNodePtr insert;                 /* the insertion node */
-
-    xmlXPathContextPtr xpathCtxt;      /* the XPath context */
-};
 
 /************************************************************************
  *                                                                     *
@@ -104,6 +80,7 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
        return;
     if (ctxt->xpathCtxt != NULL)
        xmlXPathFreeContext(ctxt->xpathCtxt);
+    xsltFreeVariableHashes(ctxt);
     memset(ctxt, -1, sizeof(xsltTransformContext));
     xmlFree(ctxt);
 }
@@ -330,7 +307,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
        /* TODO: attribute value template */
        if (ns) {
 #if LIBXML_VERSION > 20211
-           attr = xmlSetNsProp(ctxt->insert, ncname, ns->href, value);
+           attr = xmlSetNsProp(ctxt->insert, ns, ncname, value);
 #else
            xsltGenericError(xsltGenericErrorContext,
                "xsl:attribute: recompile against newer libxml version\n");
@@ -403,6 +380,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
        if (ctxt->xpathCtxt == NULL)
            goto error;
+       XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
     }
     xpathParserCtxt =
        xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
@@ -643,6 +621,7 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
            ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
            if (ctxt->xpathCtxt == NULL)
                goto error;
+           XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
        }
        xpathParserCtxt =
            xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
@@ -775,6 +754,7 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
                     xmlNodePtr list) {
     xmlNodePtr cur, insert, copy;
     xmlNodePtr oldInsert;
+    int has_variables = 0;
 
     oldInsert = insert = ctxt->insert;
     /*
@@ -818,6 +798,11 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
                ctxt->insert = insert;
                xsltAttribute(ctxt, node, cur);
                ctxt->insert = oldInsert;
+           } else if (IS_XSLT_NAME(cur, "variable")) {
+               if (has_variables == 0) {
+                   xsltPushStack(ctxt);
+               }
+               xsltParseStylesheetVariable(ctxt, cur);
            } else {
 #ifdef DEBUG_PROCESS
                xsltGenericError(xsltGenericDebugContext,
@@ -889,6 +874,9 @@ skip_children:
            }
        } while (cur != NULL);
     }
+    if (has_variables != 0) {
+       xsltPopStack(ctxt);
+    }
 }
 
 /**
@@ -926,6 +914,7 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
        if (ctxt->xpathCtxt == NULL)
            goto error;
+       XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
     }
     xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
     if (xpathParserCtxt == NULL)
@@ -1008,6 +997,7 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
        ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
        if (ctxt->xpathCtxt == NULL)
            goto error;
+       XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
     }
     xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
     if (xpathParserCtxt == NULL)
index df51e89..63009e6 100644 (file)
  */
 
 
+typedef enum {
+    XSLT_ELEM_VARIABLE=1,
+    XSLT_ELEM_PARAM
+} xsltElem;
+
+typedef struct _xsltStackElem xsltStackElem;
+typedef xsltStackElem *xsltStackElemPtr;
+struct _xsltStackElem {
+    struct _xsltStackElem *next;/* chained list */
+    xsltElem elem;     /* type of the element */
+    int computed;      /* was the evaluation done */
+    xmlChar *name;     /* the local part of the name QName */
+    xmlChar *nameURI;  /* the URI part of the name QName */
+    xmlXPathObjectPtr value; /* The value if computed */
+    xmlChar *select;   /* the eval string */
+};
+
+typedef struct _xsltStack xsltStack;
+typedef xsltStack *xsltStackPtr;
+struct _xsltStack {
+    int cur;
+    int max;
+    xsltStackElemPtr elems[50];
+};
+
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewParserContext:
+ *
+ * Create a new XSLT ParserContext
+ *
+ * Returns the newly allocated xsltParserStackElem or NULL in case of error
+ */
+xsltStackElemPtr
+xsltNewStackElem(void) {
+    xsltStackElemPtr cur;
+
+    cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
+    if (cur == NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+               "xsltNewStackElem : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltStackElem));
+    cur->computed = 0;
+    return(cur);
+}
+
+/**
+ * xsltFreeStackElem:
+ * @elem:  an XSLT stack element
+ *
+ * Free up the memory allocated by @elem
+ */
+void
+xsltFreeStackElem(xsltStackElemPtr elem) {
+    if (elem == NULL)
+       return;
+    if (elem->name != NULL)
+       xmlFree(elem->name);
+    if (elem->nameURI != NULL)
+       xmlFree(elem->nameURI);
+    if (elem->select != NULL)
+       xmlFree(elem->select);
+    if (elem->value != NULL)
+       xmlXPathFreeObject(elem->value);
+
+    memset(elem, -1, sizeof(xsltStackElem));
+    xmlFree(elem);
+}
+
+/**
+ * xsltFreeStackElemList:
+ * @elem:  an XSLT stack element
+ *
+ * Free up the memory allocated by @elem
+ */
+void
+xsltFreeStackElemList(xsltStackElemPtr elem) {
+    xsltStackElemPtr next;
+
+    while(elem != NULL) {
+       next = elem->next;
+       xsltFreeStackElem(elem);
+       elem = next;
+    }
+}
+
+/**
+ * xsltAddStackElem:
+ * @ctxt:  xn XSLT transformation context
+ * @elem:  a stack element
+ *
+ * add a new element at this level of the stack.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+int
+xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
+    xsltStackPtr stack;
+
+    if ((ctxt == NULL) || (elem == NULL))
+       return(-1);
+
+    stack = ctxt->variablesHash;
+    if (stack == NULL) {
+       /* TODO make stack size dynamic !!! */
+       stack = xmlMalloc(sizeof (xsltStack));
+       if (stack == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+               "xsltPushStack : malloc failed\n");
+           return(-1);
+       }
+       memset(stack, 0, sizeof(xsltStack));
+       ctxt->variablesHash = stack;
+       stack->cur = 0;
+       stack->max = 50;
+    }
+    /* TODO: check that there is no conflict with existing values
+     * at that level */
+    elem->next = stack->elems[stack->cur];
+    stack->elems[stack->cur] = elem;
+    return(0);
+}
+
+/**
+ * xsltPushStack:
+ * @ctxt:  xn XSLT transformation context
+ *
+ * Push a new level on the ctxtsheet interprestation stack
+ */
+void
+xsltPushStack(xsltTransformContextPtr ctxt) {
+    xsltStackPtr stack;
+
+    if (ctxt == NULL)
+       return;
+
+    stack = ctxt->variablesHash;
+    if (stack == NULL) {
+       /* TODO make stack size dynamic !!! */
+       stack = xmlMalloc(sizeof (xsltStack));
+       if (stack == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+               "xsltPushStack : malloc failed\n");
+           return;
+       }
+       memset(stack, 0, sizeof(xsltStack));
+       ctxt->variablesHash = stack;
+       stack->cur = 0;
+       stack->max = 50;
+    }
+    if (stack->cur >= stack->max + 1) {
+       TODO /* make stack size dynamic !!! */
+       xsltGenericError(xsltGenericErrorContext,
+           "xsltPushStack : overflow\n");
+       return;
+    }
+    stack->cur++;
+    stack->elems[stack->cur] = NULL;
+}
+
+/**
+ * xsltPopStack:
+ * @ctxt:  an XSLT transformation context
+ *
+ * Pop a level on the ctxtsheet interprestation stack
+ */
+void
+xsltPopStack(xsltTransformContextPtr ctxt) {
+    xsltStackPtr stack;
+
+    if (ctxt == NULL)
+       return;
+
+    stack = ctxt->variablesHash;
+    if (stack == NULL)
+       return;
+
+    xsltFreeStackElemList(stack->elems[stack->cur]);
+    stack->elems[stack->cur] = NULL;
+    stack->cur--;
+}
+
+/**
+ * xsltStackLookup:
+ * @ctxt:  an XSLT transformation context
+ * @name:  the local part of the name
+ * @nameURI:  the URI part of the name
+ *
+ * Locate an element in the stack based on its name.
+ */
+xsltStackElemPtr
+xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
+               const xmlChar *nameURI) {
+    xsltStackPtr stack;
+    int i;
+    xsltStackElemPtr cur;
+
+    if ((ctxt == NULL) || (name == NULL))
+       return(NULL);
+
+    stack = ctxt->variablesHash;
+    if (stack == NULL)
+       return(NULL);
+
+    for (i = stack->cur;i >= 0;i--) {
+       cur = stack->elems[i];
+       while (cur != NULL) {
+           if (xmlStrEqual(cur->name, name)) {
+               if (nameURI == NULL) {
+                   if (cur->nameURI == NULL)
+                       return(cur);
+               } else {
+                   if ((cur->nameURI != NULL) &&
+                       (xmlStrEqual(cur->nameURI, nameURI)))
+                       return(cur);
+               }
+
+           }
+           cur = cur->next;
+       }
+    }
+    return(NULL);
+}
+
 /************************************************************************
  *                                                                     *
  *                     Module interfaces                               *
 
 /**
  * xsltRegisterVariable:
- * @style:  the XSLT stylesheet
+ * @ctxt:  the XSLT transformation context
  * @name:  the variable name
  * @ns_uri:  the variable namespace URI
- * @value:  the variable value or NULL
+ * @select:  the expression which need to be evaluated to generate a value
+ * @value:  the variable value if select is NULL
  *
  * Register a new variable value. If @value is NULL it unregisters
  * the variable
  * Returns 0 in case of success, -1 in case of error
  */
 int
-xsltRegisterVariable(xsltStylesheetPtr style, const xmlChar *name,
-                    const xmlChar *ns_uri, xmlXPathObjectPtr value) {
-    if (style == NULL)
+xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
+                    const xmlChar *ns_uri, const xmlChar *select,
+                    xmlXPathObjectPtr value) {
+    xsltStackElemPtr elem;
+    if (ctxt == NULL)
        return(-1);
     if (name == NULL)
        return(-1);
 
-    if (style->variablesHash == NULL)
-       style->variablesHash = xmlHashCreate(0);
-    if (style->variablesHash == NULL)
+    elem = xsltNewStackElem();
+    if (elem == NULL)
        return(-1);
-    return(xmlHashUpdateEntry2((xmlHashTablePtr) style->variablesHash,
-                              name, ns_uri,
-                              (void *) value,
-                              (xmlHashDeallocator) xmlXPathFreeObject));
+    elem->name = xmlStrdup(name);
+    elem->select = xmlStrdup(select);
+    if (ns_uri)
+       elem->nameURI = xmlStrdup(ns_uri);
+    elem->value = value;
+    xsltAddStackElem(ctxt, elem);
+    if (elem->select != NULL) {
+       xmlXPathObjectPtr result, tmp;
+       xmlXPathParserContextPtr xpathParserCtxt;
+
+       xpathParserCtxt = xmlXPathNewParserContext(elem->select,
+                                                  ctxt->xpathCtxt);
+       if (xpathParserCtxt == NULL)
+           goto error;
+       xmlXPathEvalExpr(xpathParserCtxt);
+       result = valuePop(xpathParserCtxt);
+       do {
+           tmp = valuePop(xpathParserCtxt);
+           if (tmp != NULL) {
+               xmlXPathFreeObject(tmp);
+           }
+       } while (tmp != NULL);
+
+       if (result == NULL) {
+#ifdef DEBUG_PROCESS
+           xsltGenericDebug(xsltGenericDebugContext,
+               "Evaluating variable %s failed\n");
+#endif
+       }
+       if (xpathParserCtxt != NULL)
+           xmlXPathFreeParserContext(xpathParserCtxt);
+       if (result != NULL) {
+           if (elem->value != NULL)
+               xmlXPathFreeObject(elem->value);
+           elem->value = result;
+           elem->computed = 1;
+       }
+    }
+error:
+    return(0);
 }
 
 /**
  * xsltVariableLookup:
- * @style:  the XSLT stylesheet
+ * @ctxt:  the XSLT transformation context
  * @name:  the variable name
  * @ns_uri:  the variable namespace URI
  *
@@ -80,32 +350,162 @@ xsltRegisterVariable(xsltStylesheetPtr style, const xmlChar *name,
  * Returns the value or NULL if not found
  */
 xmlXPathObjectPtr
-xsltVariableLookup(xsltStylesheetPtr style, const xmlChar *name,
+xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
                   const xmlChar *ns_uri) {
-    if (style == NULL)
-       return(NULL);
+    xsltStackElemPtr elem;
 
-    if (style->variablesHash == NULL)
-       return(NULL);
-    if (name == NULL)
+    if (ctxt == NULL)
        return(NULL);
 
-    return((xmlXPathObjectPtr)
-          xmlHashLookup2((xmlHashTablePtr) style->variablesHash,
-                         name, ns_uri));
+    elem = xsltStackLookup(ctxt, name, ns_uri);
+    if (elem == NULL) {
+       TODO /* searching on other ctxtsheets ? */
+       return(NULL);
+    }
+    if (!elem->computed) {
+#ifdef DEBUG_VARIABLE
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "uncomputed variable %s\n", name);
+#endif
+           TODO /* Variable value computation needed */
+    }
+error:
+    if (elem->value != NULL)
+       return(xmlXPathObjectCopy(elem->value));
+    return(NULL);
 }
 
 
 /**
  * xsltFreeVariableHashes:
- * @style: an XSLT stylesheet
+ * @ctxt: an XSLT transformation context
  *
  * Free up the memory used by xsltAddVariable/xsltGetVariable mechanism
  */
 void
-xsltFreeVariableHashes(xsltStylesheetPtr style) {
-    if (style->variablesHash != NULL)
-       xmlHashFree((xmlHashTablePtr) style->variablesHash,
-                   (xmlHashDeallocator) xmlXPathFreeObject);
+xsltFreeVariableHashes(xsltTransformContextPtr ctxt) {
+    xsltStackPtr stack;
+    int i;
+
+    if (ctxt == NULL)
+       return;
+
+    stack = ctxt->variablesHash;
+    if (stack == NULL)
+       return;
+
+    for (i = 0; i <= stack->cur;i++) {
+       xsltFreeStackElemList(stack->elems[i]);
+    }
+    xmlFree(stack);
+}
+
+/**
+ * xsltParseStylesheetVariable:
+ * @ctxt:  the XSLT transformation context
+ * @template:  the "variable" name
+ *
+ * parse an XSLT transformation context variable name and record
+ * its value.
+ */
+
+void
+xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
+    xmlChar *name, *ncname, *prefix;
+    xmlChar *select;
+    xmlXPathObjectPtr value = NULL;
+
+    if ((cur == NULL) || (ctxt == NULL))
+       return;
+
+    name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
+    if (name == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsl:variable : missing name attribute\n");
+       return;
+    }
+
+#ifdef DEBUG_VARIABLE
+    if (ret != NULL)
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Parsing variable %s\n", name);
+#endif
+
+    select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
+    if (select == NULL) {
+       if (cur->children == NULL)
+           value = xmlXPathNewCString("");
+       else
+           value = xmlXPathNewNodeSet(cur->children);
+    } else {
+       if (cur->children != NULL)
+           xsltGenericError(xsltGenericErrorContext,
+           "xsl:variable : content shuld be empty since select is present \n");
+    }
+
+    ncname = xmlSplitQName2(name, &prefix);
+
+    if (ncname != NULL) {
+       if (prefix != NULL) {
+           xmlNsPtr ns;
+
+           ns = xmlSearchNs(cur->doc, cur, prefix);
+           if (ns == NULL) {
+               xsltGenericError(xsltGenericErrorContext,
+                   "xsl:variable : no namespace bound to prefix %s\n", prefix);
+           } else {
+               xsltRegisterVariable(ctxt, ncname, ns->href, select, value);
+           }
+           xmlFree(prefix);
+       } else {
+           xsltRegisterVariable(ctxt, ncname, NULL, select, value);
+       }
+       xmlFree(ncname);
+    } else {
+       xsltRegisterVariable(ctxt, name, NULL, select, value);
+    }
+
+    xmlFree(name);
+    if (select != NULL)
+       xmlFree(select);
+
+}
+
+/**
+ * xsltVariableLookup:
+ * @ctxt:  a void * but the the XSLT transformation context actually
+ * @name:  the variable name
+ * @ns_uri:  the variable namespace URI
+ *
+ * This is the entry point when a varibale is needed by the XPath
+ * interpretor.
+ *
+ * Returns the value or NULL if not found
+ */
+xmlXPathObjectPtr
+xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
+                       const xmlChar *ns_uri) {
+    xsltTransformContextPtr context;
+    xmlXPathObjectPtr ret;
+
+    if ((ctxt == NULL) || (name == NULL))
+       return(NULL);
+
+#ifdef DEBUG_VARIABLE
+    xsltGenericDebug(xsltGenericDebugContext,
+           "Lookup variable %s\n", name);
+#endif
+    context = (xsltTransformContextPtr) ctxt;
+    ret = xsltVariableLookup(context, name, ns_uri);
+    if (ret == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "unregistered variable %s\n", name);
+    }
+#ifdef DEBUG_VARIABLE
+    if (ret != NULL)
+       xsltGenericDebug(xsltGenericDebugContext,
+           "found variable %s\n", name);
+#endif
+    return(ret);
 }
 
index a815adb..a063362 100644 (file)
 #define __XML_XSLT_VARIABLES_H__
 
 #include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
 #include "xsltInternals.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-void                   xsltFreeVariableHashes  (xsltStylesheetPtr style);
-xmlXPathObjectPtr      xsltVariableLookup      (xsltStylesheetPtr style,
+#define XSLT_REGISTER_VARIABLE_LOOKUP(ctxt)                    \
+    xmlXPathRegisterVariableLookup((ctxt)->xpathCtxt,          \
+              xsltXPathVariableLookup, (void *)(ctxt)) 
+
+/*
+ * Interfaces for the variable module.
+ */
+
+void           xsltPushStack                   (xsltTransformContextPtr ctxt);
+void           xsltPopStack                    (xsltTransformContextPtr ctxt);
+void           xsltParseStylesheetVariable     (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr cur);
+void                   xsltFreeVariableHashes  (xsltTransformContextPtr ctxt);
+xmlXPathObjectPtr      xsltVariableLookup      (xsltTransformContextPtr ctxt,
                                                 const xmlChar *name,
                                                 const xmlChar *ns_uri);
-int                    xsltRegisterVariable    (xsltStylesheetPtr style,
+int                    xsltRegisterVariable    (xsltTransformContextPtr ctxt,
                                                 const xmlChar *name,
                                                 const xmlChar *ns_uri,
+                                                const xmlChar *select,
                                                 xmlXPathObjectPtr value);
+xmlXPathObjectPtr      xsltXPathVariableLookup (void *ctxt,
+                                                const xmlChar *name,
+                                                const xmlChar *ns_uri);
 #ifdef __cplusplus
 }
 #endif
index 1204a2b..537da78 100644 (file)
@@ -162,7 +162,6 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet) {
        return;
 
     xsltFreeTemplateHashes(sheet);
-    xsltFreeVariableHashes(sheet);
     xsltFreeTemplateList(sheet->templates);
     if (sheet->doc != NULL)
        xmlFreeDoc(sheet->doc);
index 1a3d637..f4bcbc4 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <libxml/tree.h>
 #include <libxml/hash.h>
+#include <libxml/xpath.h>
 #include <libxslt/xslt.h>
 
 #ifdef __cplusplus
@@ -65,12 +66,6 @@ struct _xsltStylesheet {
     void *templatesHash;       /* hash table or wherever compiled templates
                                   informations are stored */
     /*
-     * Variable descriptions
-     */
-    void *variablesHash;       /* hash table or wherever variables
-                                  informations are stored */
-
-    /*
      * Output related stuff.
      */
     xmlChar *method;           /* the output method */
@@ -87,6 +82,33 @@ struct _xsltStylesheet {
 
 
 /*
+ * The in-memory structure corresponding to an XSLT Transformation
+ */
+typedef enum xsltOutputType {
+    XSLT_OUTPUT_XML = 0,
+    XSLT_OUTPUT_HTML,
+    XSLT_OUTPUT_TEXT
+} xsltOutputType;
+
+typedef struct _xsltTransformContext xsltTransformContext;
+typedef xsltTransformContext *xsltTransformContextPtr;
+struct _xsltTransformContext {
+    xsltStylesheetPtr style;           /* the stylesheet used */
+    xsltOutputType type;               /* the type of output */
+
+    xmlDocPtr doc;                     /* the current doc */
+    xmlNodePtr node;                   /* the current node */
+    xmlNodeSetPtr nodeList;            /* the current node list */
+
+    xmlDocPtr output;                  /* the resulting document */
+    xmlNodePtr insert;                 /* the insertion node */
+
+    xmlXPathContextPtr xpathCtxt;      /* the XPath context */
+    void *variablesHash;               /* hash table or wherever variables
+                                          informations are stored */
+};
+
+/*
  * Functions associated to the internal types
  */
 xsltStylesheetPtr      xsltParseStylesheetFile (const xmlChar* filename);
index 9f37477..c3246be 100644 (file)
@@ -24,6 +24,10 @@ xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
 void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
 xmlAttrPtr xmlSetNsProp        (xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
                         const xmlChar *value);
+/*********
+void xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
+                    xmlXPathVariableLookupFunc f, void *data)
+ *********/
 
 /*
  * Useful macros