mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
Working on variables implementation:
- 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
This commit is contained in:
@@ -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>
|
Fri Jan 19 13:16:57 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* libxslt/xslt.c: check version on stylesheets
|
* libxslt/xslt.c: check version on stylesheets
|
||||||
|
|||||||
1
TODO
1
TODO
@@ -2,6 +2,7 @@ Design:
|
|||||||
- should transforms for a given stylesheet be thread clean,
|
- should transforms for a given stylesheet be thread clean,
|
||||||
or can a stylesheet be enriched with document specific
|
or can a stylesheet be enriched with document specific
|
||||||
informations and cleaned up later ?
|
informations and cleaned up later ?
|
||||||
|
=> currently stylesheet manipulation is not reentrant.
|
||||||
- seems that saving back XSLT stylesheet from a compiled form might
|
- seems that saving back XSLT stylesheet from a compiled form might
|
||||||
be a bit ugly ...
|
be a bit ugly ...
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "xsltutils.h"
|
#include "xsltutils.h"
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
#include "variables.h"
|
||||||
|
|
||||||
#define DEBUG_PROCESS
|
#define DEBUG_PROCESS
|
||||||
|
|
||||||
@@ -39,31 +40,6 @@
|
|||||||
#define IS_BLANK_NODE(n) \
|
#define IS_BLANK_NODE(n) \
|
||||||
(((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
|
(((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;
|
return;
|
||||||
if (ctxt->xpathCtxt != NULL)
|
if (ctxt->xpathCtxt != NULL)
|
||||||
xmlXPathFreeContext(ctxt->xpathCtxt);
|
xmlXPathFreeContext(ctxt->xpathCtxt);
|
||||||
|
xsltFreeVariableHashes(ctxt);
|
||||||
memset(ctxt, -1, sizeof(xsltTransformContext));
|
memset(ctxt, -1, sizeof(xsltTransformContext));
|
||||||
xmlFree(ctxt);
|
xmlFree(ctxt);
|
||||||
}
|
}
|
||||||
@@ -330,7 +307,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
/* TODO: attribute value template */
|
/* TODO: attribute value template */
|
||||||
if (ns) {
|
if (ns) {
|
||||||
#if LIBXML_VERSION > 20211
|
#if LIBXML_VERSION > 20211
|
||||||
attr = xmlSetNsProp(ctxt->insert, ncname, ns->href, value);
|
attr = xmlSetNsProp(ctxt->insert, ns, ncname, value);
|
||||||
#else
|
#else
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsl:attribute: recompile against newer libxml version\n");
|
"xsl:attribute: recompile against newer libxml version\n");
|
||||||
@@ -403,6 +380,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
if (ctxt->xpathCtxt == NULL)
|
if (ctxt->xpathCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
}
|
}
|
||||||
xpathParserCtxt =
|
xpathParserCtxt =
|
||||||
xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
||||||
@@ -643,6 +621,7 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
if (ctxt->xpathCtxt == NULL)
|
if (ctxt->xpathCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
}
|
}
|
||||||
xpathParserCtxt =
|
xpathParserCtxt =
|
||||||
xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
||||||
@@ -775,6 +754,7 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
xmlNodePtr list) {
|
xmlNodePtr list) {
|
||||||
xmlNodePtr cur, insert, copy;
|
xmlNodePtr cur, insert, copy;
|
||||||
xmlNodePtr oldInsert;
|
xmlNodePtr oldInsert;
|
||||||
|
int has_variables = 0;
|
||||||
|
|
||||||
oldInsert = insert = ctxt->insert;
|
oldInsert = insert = ctxt->insert;
|
||||||
/*
|
/*
|
||||||
@@ -818,6 +798,11 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
ctxt->insert = insert;
|
ctxt->insert = insert;
|
||||||
xsltAttribute(ctxt, node, cur);
|
xsltAttribute(ctxt, node, cur);
|
||||||
ctxt->insert = oldInsert;
|
ctxt->insert = oldInsert;
|
||||||
|
} else if (IS_XSLT_NAME(cur, "variable")) {
|
||||||
|
if (has_variables == 0) {
|
||||||
|
xsltPushStack(ctxt);
|
||||||
|
}
|
||||||
|
xsltParseStylesheetVariable(ctxt, cur);
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
xsltGenericError(xsltGenericDebugContext,
|
xsltGenericError(xsltGenericDebugContext,
|
||||||
@@ -889,6 +874,9 @@ skip_children:
|
|||||||
}
|
}
|
||||||
} while (cur != NULL);
|
} while (cur != NULL);
|
||||||
}
|
}
|
||||||
|
if (has_variables != 0) {
|
||||||
|
xsltPopStack(ctxt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -926,6 +914,7 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
if (ctxt->xpathCtxt == NULL)
|
if (ctxt->xpathCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
}
|
}
|
||||||
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
||||||
if (xpathParserCtxt == NULL)
|
if (xpathParserCtxt == NULL)
|
||||||
@@ -1008,6 +997,7 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
if (ctxt->xpathCtxt == NULL)
|
if (ctxt->xpathCtxt == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
}
|
}
|
||||||
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
|
||||||
if (xpathParserCtxt == NULL)
|
if (xpathParserCtxt == NULL)
|
||||||
|
|||||||
@@ -32,6 +32,238 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
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 *
|
* Module interfaces *
|
||||||
@@ -40,10 +272,11 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltRegisterVariable:
|
* xsltRegisterVariable:
|
||||||
* @style: the XSLT stylesheet
|
* @ctxt: the XSLT transformation context
|
||||||
* @name: the variable name
|
* @name: the variable name
|
||||||
* @ns_uri: the variable namespace URI
|
* @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
|
* Register a new variable value. If @value is NULL it unregisters
|
||||||
* the variable
|
* the variable
|
||||||
@@ -51,26 +284,63 @@
|
|||||||
* Returns 0 in case of success, -1 in case of error
|
* Returns 0 in case of success, -1 in case of error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xsltRegisterVariable(xsltStylesheetPtr style, const xmlChar *name,
|
xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
const xmlChar *ns_uri, xmlXPathObjectPtr value) {
|
const xmlChar *ns_uri, const xmlChar *select,
|
||||||
if (style == NULL)
|
xmlXPathObjectPtr value) {
|
||||||
|
xsltStackElemPtr elem;
|
||||||
|
if (ctxt == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
if (style->variablesHash == NULL)
|
elem = xsltNewStackElem();
|
||||||
style->variablesHash = xmlHashCreate(0);
|
if (elem == NULL)
|
||||||
if (style->variablesHash == NULL)
|
|
||||||
return(-1);
|
return(-1);
|
||||||
return(xmlHashUpdateEntry2((xmlHashTablePtr) style->variablesHash,
|
elem->name = xmlStrdup(name);
|
||||||
name, ns_uri,
|
elem->select = xmlStrdup(select);
|
||||||
(void *) value,
|
if (ns_uri)
|
||||||
(xmlHashDeallocator) xmlXPathFreeObject));
|
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:
|
* xsltVariableLookup:
|
||||||
* @style: the XSLT stylesheet
|
* @ctxt: the XSLT transformation context
|
||||||
* @name: the variable name
|
* @name: the variable name
|
||||||
* @ns_uri: the variable namespace URI
|
* @ns_uri: the variable namespace URI
|
||||||
*
|
*
|
||||||
@@ -80,32 +350,162 @@ xsltRegisterVariable(xsltStylesheetPtr style, const xmlChar *name,
|
|||||||
* Returns the value or NULL if not found
|
* Returns the value or NULL if not found
|
||||||
*/
|
*/
|
||||||
xmlXPathObjectPtr
|
xmlXPathObjectPtr
|
||||||
xsltVariableLookup(xsltStylesheetPtr style, const xmlChar *name,
|
xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
const xmlChar *ns_uri) {
|
const xmlChar *ns_uri) {
|
||||||
if (style == NULL)
|
xsltStackElemPtr elem;
|
||||||
|
|
||||||
|
if (ctxt == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
if (style->variablesHash == NULL)
|
elem = xsltStackLookup(ctxt, name, ns_uri);
|
||||||
|
if (elem == NULL) {
|
||||||
|
TODO /* searching on other ctxtsheets ? */
|
||||||
return(NULL);
|
return(NULL);
|
||||||
if (name == 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);
|
return(NULL);
|
||||||
|
|
||||||
return((xmlXPathObjectPtr)
|
|
||||||
xmlHashLookup2((xmlHashTablePtr) style->variablesHash,
|
|
||||||
name, ns_uri));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltFreeVariableHashes:
|
* xsltFreeVariableHashes:
|
||||||
* @style: an XSLT stylesheet
|
* @ctxt: an XSLT transformation context
|
||||||
*
|
*
|
||||||
* Free up the memory used by xsltAddVariable/xsltGetVariable mechanism
|
* Free up the memory used by xsltAddVariable/xsltGetVariable mechanism
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xsltFreeVariableHashes(xsltStylesheetPtr style) {
|
xsltFreeVariableHashes(xsltTransformContextPtr ctxt) {
|
||||||
if (style->variablesHash != NULL)
|
xsltStackPtr stack;
|
||||||
xmlHashFree((xmlHashTablePtr) style->variablesHash,
|
int i;
|
||||||
(xmlHashDeallocator) xmlXPathFreeObject);
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,20 +10,37 @@
|
|||||||
#define __XML_XSLT_VARIABLES_H__
|
#define __XML_XSLT_VARIABLES_H__
|
||||||
|
|
||||||
#include <libxml/xpath.h>
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
#include "xsltInternals.h"
|
#include "xsltInternals.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void xsltFreeVariableHashes (xsltStylesheetPtr style);
|
#define XSLT_REGISTER_VARIABLE_LOOKUP(ctxt) \
|
||||||
xmlXPathObjectPtr xsltVariableLookup (xsltStylesheetPtr style,
|
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 *name,
|
||||||
const xmlChar *ns_uri);
|
const xmlChar *ns_uri);
|
||||||
int xsltRegisterVariable (xsltStylesheetPtr style,
|
int xsltRegisterVariable (xsltTransformContextPtr ctxt,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
const xmlChar *ns_uri,
|
const xmlChar *ns_uri,
|
||||||
|
const xmlChar *select,
|
||||||
xmlXPathObjectPtr value);
|
xmlXPathObjectPtr value);
|
||||||
|
xmlXPathObjectPtr xsltXPathVariableLookup (void *ctxt,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *ns_uri);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
xsltFreeTemplateHashes(sheet);
|
xsltFreeTemplateHashes(sheet);
|
||||||
xsltFreeVariableHashes(sheet);
|
|
||||||
xsltFreeTemplateList(sheet->templates);
|
xsltFreeTemplateList(sheet->templates);
|
||||||
if (sheet->doc != NULL)
|
if (sheet->doc != NULL)
|
||||||
xmlFreeDoc(sheet->doc);
|
xmlFreeDoc(sheet->doc);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
#include <libxml/hash.h>
|
#include <libxml/hash.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
#include <libxslt/xslt.h>
|
#include <libxslt/xslt.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -64,12 +65,6 @@ struct _xsltStylesheet {
|
|||||||
xsltTemplatePtr templates; /* the ordered list of templates */
|
xsltTemplatePtr templates; /* the ordered list of templates */
|
||||||
void *templatesHash; /* hash table or wherever compiled templates
|
void *templatesHash; /* hash table or wherever compiled templates
|
||||||
informations are stored */
|
informations are stored */
|
||||||
/*
|
|
||||||
* Variable descriptions
|
|
||||||
*/
|
|
||||||
void *variablesHash; /* hash table or wherever variables
|
|
||||||
informations are stored */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output related stuff.
|
* Output related stuff.
|
||||||
*/
|
*/
|
||||||
@@ -86,6 +81,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
|
* Functions associated to the internal types
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix);
|
|||||||
void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
|
||||||
xmlAttrPtr xmlSetNsProp (xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
xmlAttrPtr xmlSetNsProp (xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
||||||
const xmlChar *value);
|
const xmlChar *value);
|
||||||
|
/*********
|
||||||
|
void xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
|
||||||
|
xmlXPathVariableLookupFunc f, void *data)
|
||||||
|
*********/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Useful macros
|
* Useful macros
|
||||||
|
|||||||
Reference in New Issue
Block a user