mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
Furious hacking session, making serious progresses, the hardest stuff
now seems in place !!! * xsltproc.c: removed bug * tests/REC2/html.xml: added newline after doctype * libxslt/variables.[ch] libxslt/xsltInternals.h: added param support, result tree fragment support (requires just commited extensions to libxml2 XPath !!!) * transform.c: added call-template, with-param support * libxslt/pattern.[ch]: xsltFindTemplate() needed for call-template * TODO: updated, added a DONE section and started migrating stuff :-) Daniel
This commit is contained in:
11
ChangeLog
11
ChangeLog
@@ -1,3 +1,14 @@
|
|||||||
|
Mon Jan 22 11:46:44 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* xsltproc.c: removed bug
|
||||||
|
* tests/REC2/html.xml: added newline after doctype
|
||||||
|
* libxslt/variables.[ch] libxslt/xsltInternals.h: added param
|
||||||
|
support, result tree fragment support (requires just commited
|
||||||
|
extensions to libxml2 XPath !!!)
|
||||||
|
* transform.c: added call-template, with-param support
|
||||||
|
* libxslt/pattern.[ch]: xsltFindTemplate() needed for call-template
|
||||||
|
* TODO: updated, added a DONE section and started migrating stuff :-)
|
||||||
|
|
||||||
Sun Jan 21 12:03:16 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Sun Jan 21 12:03:16 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* Makefile.am tests/Makefile.am tests/REC1/Makefile.am
|
* Makefile.am tests/Makefile.am tests/REC1/Makefile.am
|
||||||
|
|||||||
35
TODO
35
TODO
@@ -1,3 +1,8 @@
|
|||||||
|
********
|
||||||
|
* *
|
||||||
|
* TODO *
|
||||||
|
* *
|
||||||
|
********
|
||||||
Design:
|
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
|
||||||
@@ -18,15 +23,6 @@ Pattern scanner:
|
|||||||
-> handle unions
|
-> handle unions
|
||||||
-> compute priority
|
-> compute priority
|
||||||
|
|
||||||
Separate util module:
|
|
||||||
-> macros, config, verbosity ?
|
|
||||||
|
|
||||||
Support for disable-output-escaping="yes":
|
|
||||||
-> looks problematic, libxml has no support for anything like this,
|
|
||||||
and unless adding a new node type :-( or tweaking text node and
|
|
||||||
output routines this is gonna be messy ... must be handled at libxml
|
|
||||||
level.
|
|
||||||
|
|
||||||
Error handling:
|
Error handling:
|
||||||
-> check the version stuff, design a separate module for error interfacing
|
-> check the version stuff, design a separate module for error interfacing
|
||||||
and default handling, parsing vs. runtime, fatal / compat / warning,
|
and default handling, parsing vs. runtime, fatal / compat / warning,
|
||||||
@@ -35,6 +31,8 @@ Error handling:
|
|||||||
Support Attribute value templates:
|
Support Attribute value templates:
|
||||||
-> starts to be urgent. Design it in flexible ways but try to optimize
|
-> starts to be urgent. Design it in flexible ways but try to optimize
|
||||||
to handle most of it at the stylesheet parse time ...
|
to handle most of it at the stylesheet parse time ...
|
||||||
|
=> Done for the most part need to check all attributes in XSLT constructs
|
||||||
|
using them and use the dedicated readin function.
|
||||||
|
|
||||||
Sorting:
|
Sorting:
|
||||||
-> add support for imbricated sorts
|
-> add support for imbricated sorts
|
||||||
@@ -45,4 +43,23 @@ Validity:
|
|||||||
-> should we add validation by default ? Make this an option
|
-> should we add validation by default ? Make this an option
|
||||||
-> redirrect validity errors
|
-> redirrect validity errors
|
||||||
|
|
||||||
|
Contextual error reporting:
|
||||||
|
-> provide a couple of functions providing context analysis, not urgent
|
||||||
|
|
||||||
|
********
|
||||||
|
* *
|
||||||
|
* DONE *
|
||||||
|
* *
|
||||||
|
********
|
||||||
|
|
||||||
|
Separate util module:
|
||||||
|
-> macros, config, verbosity ?
|
||||||
|
=> xsltutils.[ch]
|
||||||
|
|
||||||
|
Support for disable-output-escaping="yes":
|
||||||
|
-> looks problematic, libxml has no support for anything like this,
|
||||||
|
and unless adding a new node type :-( or tweaking text node and
|
||||||
|
output routines this is gonna be messy ... must be handled at libxml
|
||||||
|
level.
|
||||||
|
=> Done with a trick, text node name is different, requires > 2.2.11
|
||||||
|
|
||||||
|
|||||||
@@ -974,12 +974,33 @@ int
|
|||||||
xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
|
xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
|
||||||
xsltCompMatchPtr pat, list;
|
xsltCompMatchPtr pat, list;
|
||||||
const xmlChar *name;
|
const xmlChar *name;
|
||||||
|
xmlChar *p, *pattern, tmp;
|
||||||
|
|
||||||
|
if ((style == NULL) || (cur == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
p = cur->match;
|
||||||
|
if (p == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
next_pattern:
|
||||||
|
if (*p == 0)
|
||||||
|
return(0);
|
||||||
/*
|
/*
|
||||||
* get a compiled form of the pattern
|
* get a compiled form of the pattern
|
||||||
*/
|
*/
|
||||||
/* TODO : handle | in patterns as multple pat !!! */
|
pattern = p;
|
||||||
pat = xsltCompilePattern(cur->match);
|
while ((*p != 0) && (*p != '|')) {
|
||||||
|
/* TODO: handle string escaping "a | b" in patterns ... */
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = *p;
|
||||||
|
*p = 0;
|
||||||
|
pat = xsltCompilePattern(pattern);
|
||||||
|
*p = tmp;
|
||||||
|
if (tmp != 0)
|
||||||
|
p++;
|
||||||
if (pat == NULL)
|
if (pat == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
pat->template = cur;
|
pat->template = cur;
|
||||||
@@ -1080,6 +1101,8 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (*p != 0)
|
||||||
|
goto next_pattern;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,3 +1197,36 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) {
|
|||||||
(xmlHashDeallocator) xsltFreeCompMatchList);
|
(xmlHashDeallocator) xsltFreeCompMatchList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltFindTemplate:
|
||||||
|
* @style: an XSLT stylesheet
|
||||||
|
* @name: the template name
|
||||||
|
* @nameURI: the template name URI
|
||||||
|
*
|
||||||
|
* Finds the named template.
|
||||||
|
*
|
||||||
|
* Returns the xsltTemplatePtr or NULL if not found
|
||||||
|
*/
|
||||||
|
xsltTemplatePtr
|
||||||
|
xsltFindTemplate(xsltStylesheetPtr style, const xmlChar *name,
|
||||||
|
const xmlChar *nameURI) {
|
||||||
|
xsltTemplatePtr cur;
|
||||||
|
|
||||||
|
if ((style == NULL) || (name == NULL))
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
/* TODO: apply stylesheet import order */
|
||||||
|
cur = style->templates;
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (xmlStrEqual(name, cur->name)) {
|
||||||
|
if (((nameURI == NULL) && (cur->nameURI == NULL)) ||
|
||||||
|
((nameURI != NULL) && (cur->nameURI != NULL) &&
|
||||||
|
(xmlStrEqual(nameURI, cur->nameURI)))) {
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ int xsltAddTemplate (xsltStylesheetPtr style,
|
|||||||
xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style,
|
xsltTemplatePtr xsltGetTemplate (xsltStylesheetPtr style,
|
||||||
xmlNodePtr node);
|
xmlNodePtr node);
|
||||||
void xsltFreeTemplateHashes (xsltStylesheetPtr style);
|
void xsltFreeTemplateHashes (xsltStylesheetPtr style);
|
||||||
|
xsltTemplatePtr xsltFindTemplate (xsltStylesheetPtr style,
|
||||||
|
const xmlChar *name,
|
||||||
|
const xmlChar *nameURI);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
if (ns) {
|
if (ns) {
|
||||||
#if LIBXML_VERSION > 20211
|
#if LIBXML_VERSION > 20211
|
||||||
attr = xmlSetNsProp(ctxt->insert, ncname, ns->href,
|
attr = xmlSetNsProp(ctxt->insert, ns, ncname,
|
||||||
(const xmlChar *)"");
|
(const xmlChar *)"");
|
||||||
#else
|
#else
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
@@ -585,6 +585,89 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltCallTemplate:
|
||||||
|
* @ctxt: a XSLT process context
|
||||||
|
* @node: the node in the source tree.
|
||||||
|
* @inst: the xslt call-template node
|
||||||
|
*
|
||||||
|
* Process the xslt call-template node on the source node
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
||||||
|
xmlNodePtr inst) {
|
||||||
|
xmlChar *prop = NULL;
|
||||||
|
xmlChar *ncname = NULL;
|
||||||
|
xmlChar *prefix = NULL;
|
||||||
|
xmlNsPtr ns = NULL;
|
||||||
|
xsltTemplatePtr template;
|
||||||
|
xmlNodePtr cur;
|
||||||
|
int has_param = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (ctxt->insert == NULL)
|
||||||
|
return;
|
||||||
|
prop = xmlGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
|
||||||
|
if (prop == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xslt:call-template : name is missing\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncname = xmlSplitQName2(prop, &prefix);
|
||||||
|
if (ncname == NULL) {
|
||||||
|
ncname = prop;
|
||||||
|
prop = NULL;
|
||||||
|
prefix = NULL;
|
||||||
|
}
|
||||||
|
if ((prefix != NULL) && (ns == NULL)) {
|
||||||
|
ns = xmlSearchNs(ctxt->insert->doc, ctxt->insert, prefix);
|
||||||
|
if (ns == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"no namespace bound to prefix %s\n", prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ns != NULL)
|
||||||
|
template = xsltFindTemplate(ctxt->style, ncname, ns->href);
|
||||||
|
else
|
||||||
|
template = xsltFindTemplate(ctxt->style, ncname, NULL);
|
||||||
|
if (template == NULL) {
|
||||||
|
xsltGenericError(xsltGenericDebugContext,
|
||||||
|
"xslt:call-template: template %s not found\n", cur->name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
cur = inst->children;
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (IS_XSLT_ELEM(cur)) {
|
||||||
|
if (IS_XSLT_NAME(cur, "with-param")) {
|
||||||
|
if (has_param == 0) {
|
||||||
|
xsltPushStack(ctxt);
|
||||||
|
has_param = 1;
|
||||||
|
}
|
||||||
|
xsltParseStylesheetParam(ctxt, cur);
|
||||||
|
} else {
|
||||||
|
xsltGenericError(xsltGenericDebugContext,
|
||||||
|
"xslt:call-template: misplaced xslt:%s\n", cur->name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xsltGenericError(xsltGenericDebugContext,
|
||||||
|
"xslt:call-template: misplaced %s element\n", cur->name);
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
xsltApplyOneTemplate(ctxt, node, template->content);
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (has_param == 1)
|
||||||
|
xsltPopStack(ctxt);
|
||||||
|
if (prop != NULL)
|
||||||
|
xmlFree(prop);
|
||||||
|
if (ncname != NULL)
|
||||||
|
xmlFree(ncname);
|
||||||
|
if (prefix != NULL)
|
||||||
|
xmlFree(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltApplyTemplates:
|
* xsltApplyTemplates:
|
||||||
* @ctxt: a XSLT process context
|
* @ctxt: a XSLT process context
|
||||||
@@ -803,8 +886,21 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
|
|||||||
} else if (IS_XSLT_NAME(cur, "variable")) {
|
} else if (IS_XSLT_NAME(cur, "variable")) {
|
||||||
if (has_variables == 0) {
|
if (has_variables == 0) {
|
||||||
xsltPushStack(ctxt);
|
xsltPushStack(ctxt);
|
||||||
|
has_variables = 1;
|
||||||
}
|
}
|
||||||
xsltParseStylesheetVariable(ctxt, cur);
|
xsltParseStylesheetVariable(ctxt, cur);
|
||||||
|
} else if (IS_XSLT_NAME(cur, "param")) {
|
||||||
|
if (has_variables == 0) {
|
||||||
|
xsltPushStack(ctxt);
|
||||||
|
has_variables = 1;
|
||||||
|
}
|
||||||
|
xsltParseStylesheetParam(ctxt, cur);
|
||||||
|
} else if (IS_XSLT_NAME(cur, "call-template")) {
|
||||||
|
if (has_variables == 0) {
|
||||||
|
xsltPushStack(ctxt);
|
||||||
|
has_variables = 1;
|
||||||
|
}
|
||||||
|
xsltCallTemplate(ctxt, node, cur);
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_PROCESS
|
#ifdef DEBUG_PROCESS
|
||||||
xsltGenericError(xsltGenericDebugContext,
|
xsltGenericError(xsltGenericDebugContext,
|
||||||
@@ -1120,6 +1216,7 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
ctxt->doc = doc;
|
ctxt->doc = doc;
|
||||||
ctxt->style = style;
|
ctxt->style = style;
|
||||||
|
xsltEvalGlobalVariables(ctxt);
|
||||||
if ((style->method != NULL) &&
|
if ((style->method != NULL) &&
|
||||||
(!xmlStrEqual(style->method, (const xmlChar *) "xml"))) {
|
(!xmlStrEqual(style->method, (const xmlChar *) "xml"))) {
|
||||||
if (xmlStrEqual(style->method, (const xmlChar *) "html")) {
|
if (xmlStrEqual(style->method, (const xmlChar *) "html")) {
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style,
|
xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style,
|
||||||
xmlDocPtr doc);
|
xmlDocPtr doc);
|
||||||
|
void xsltApplyOneTemplate (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
xmlNodePtr list);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,12 +18,14 @@
|
|||||||
#include <libxml/valid.h>
|
#include <libxml/valid.h>
|
||||||
#include <libxml/hash.h>
|
#include <libxml/hash.h>
|
||||||
#include <libxml/xmlerror.h>
|
#include <libxml/xmlerror.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
#include <libxml/xpathInternals.h>
|
#include <libxml/xpathInternals.h>
|
||||||
#include <libxml/parserInternals.h>
|
#include <libxml/parserInternals.h>
|
||||||
#include "xslt.h"
|
#include "xslt.h"
|
||||||
#include "xsltInternals.h"
|
#include "xsltInternals.h"
|
||||||
#include "xsltutils.h"
|
#include "xsltutils.h"
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
|
#include "transform.h"
|
||||||
|
|
||||||
#define DEBUG_VARIABLE
|
#define DEBUG_VARIABLE
|
||||||
|
|
||||||
@@ -31,24 +33,6 @@
|
|||||||
* Types are private:
|
* Types are private:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
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 struct _xsltStack xsltStack;
|
||||||
typedef xsltStack *xsltStackPtr;
|
typedef xsltStack *xsltStackPtr;
|
||||||
struct _xsltStack {
|
struct _xsltStack {
|
||||||
@@ -138,6 +122,7 @@ xsltFreeStackElemList(xsltStackElemPtr elem) {
|
|||||||
int
|
int
|
||||||
xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
|
xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
|
||||||
xsltStackPtr stack;
|
xsltStackPtr stack;
|
||||||
|
xsltStackElemPtr cur;
|
||||||
|
|
||||||
if ((ctxt == NULL) || (elem == NULL))
|
if ((ctxt == NULL) || (elem == NULL))
|
||||||
return(-1);
|
return(-1);
|
||||||
@@ -158,6 +143,20 @@ xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
|
|||||||
}
|
}
|
||||||
/* TODO: check that there is no conflict with existing values
|
/* TODO: check that there is no conflict with existing values
|
||||||
* at that level */
|
* at that level */
|
||||||
|
cur = stack->elems[stack->cur];
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (xmlStrEqual(elem->name, cur->name)) {
|
||||||
|
if (((elem->nameURI == NULL) && (cur->nameURI == NULL)) ||
|
||||||
|
((elem->nameURI != NULL) && (cur->nameURI != NULL) &&
|
||||||
|
(xmlStrEqual(elem->nameURI, cur->nameURI)))) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"redefinition of param or variable %s\n", elem->name);
|
||||||
|
xsltFreeStackElem(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
elem->next = stack->elems[stack->cur];
|
elem->next = stack->elems[stack->cur];
|
||||||
stack->elems[stack->cur] = elem;
|
stack->elems[stack->cur] = elem;
|
||||||
return(0);
|
return(0);
|
||||||
@@ -233,6 +232,7 @@ xsltPopStack(xsltTransformContextPtr ctxt) {
|
|||||||
xsltStackElemPtr
|
xsltStackElemPtr
|
||||||
xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
const xmlChar *nameURI) {
|
const xmlChar *nameURI) {
|
||||||
|
xsltStackElemPtr ret = NULL;
|
||||||
xsltStackPtr stack;
|
xsltStackPtr stack;
|
||||||
int i;
|
int i;
|
||||||
xsltStackElemPtr cur;
|
xsltStackElemPtr cur;
|
||||||
@@ -248,20 +248,29 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
cur = stack->elems[i];
|
cur = stack->elems[i];
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
if (xmlStrEqual(cur->name, name)) {
|
if (xmlStrEqual(cur->name, name)) {
|
||||||
|
/* TODO: double check param binding */
|
||||||
if (nameURI == NULL) {
|
if (nameURI == NULL) {
|
||||||
if (cur->nameURI == NULL)
|
if (cur->nameURI == NULL) {
|
||||||
return(cur);
|
if (cur->type == XSLT_ELEM_PARAM)
|
||||||
|
ret = cur;
|
||||||
|
else
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((cur->nameURI != NULL) &&
|
if ((cur->nameURI != NULL) &&
|
||||||
(xmlStrEqual(cur->nameURI, nameURI)))
|
(xmlStrEqual(cur->nameURI, nameURI))) {
|
||||||
return(cur);
|
if (cur->type == XSLT_ELEM_PARAM)
|
||||||
|
ret = cur;
|
||||||
|
else
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -270,13 +279,192 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltEvalVariable:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @elem: the variable or parameter.
|
||||||
|
*
|
||||||
|
* Evaluate a variable value.
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, -1 in case of error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltEvalVariables(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) {
|
||||||
|
xmlXPathParserContextPtr xpathParserCtxt;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (elem == NULL))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (ctxt->xpathCtxt == NULL) {
|
||||||
|
xmlXPathInit();
|
||||||
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
|
if (ctxt->xpathCtxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Evaluating variable %s\n", elem->name);
|
||||||
|
#endif
|
||||||
|
if (elem->select != NULL) {
|
||||||
|
xmlXPathObjectPtr result, tmp;
|
||||||
|
|
||||||
|
xpathParserCtxt = xmlXPathNewParserContext(elem->select,
|
||||||
|
ctxt->xpathCtxt);
|
||||||
|
if (xpathParserCtxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
|
||||||
|
xmlXPathEvalExpr(xpathParserCtxt);
|
||||||
|
result = valuePop(xpathParserCtxt);
|
||||||
|
do {
|
||||||
|
tmp = valuePop(xpathParserCtxt);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
xmlXPathFreeObject(tmp);
|
||||||
|
}
|
||||||
|
} while (tmp != NULL);
|
||||||
|
|
||||||
|
if (result == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"Evaluating global variable %s failed\n");
|
||||||
|
}
|
||||||
|
if (xpathParserCtxt != NULL)
|
||||||
|
xmlXPathFreeParserContext(xpathParserCtxt);
|
||||||
|
if (result != NULL) {
|
||||||
|
if (elem->value != NULL)
|
||||||
|
xmlXPathFreeObject(elem->value);
|
||||||
|
elem->value = result;
|
||||||
|
elem->computed = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (elem->tree == NULL) {
|
||||||
|
elem->value = xmlXPathNewCString("");
|
||||||
|
elem->computed = 1;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* This is a result tree fragment.
|
||||||
|
*/
|
||||||
|
xmlNodePtr container;
|
||||||
|
xmlNodePtr oldInsert, oldNode;
|
||||||
|
|
||||||
|
container = xmlNewDocNode(ctxt->output, NULL,
|
||||||
|
(const xmlChar *) "fake", NULL);
|
||||||
|
if (container == NULL)
|
||||||
|
return(-1);
|
||||||
|
oldInsert = ctxt->insert;
|
||||||
|
oldNode = ctxt->node;
|
||||||
|
ctxt->insert = container;
|
||||||
|
|
||||||
|
xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree);
|
||||||
|
|
||||||
|
ctxt->insert = oldInsert;
|
||||||
|
ctxt->node = oldNode;
|
||||||
|
elem->value = xmlXPathNewValueTree(container);
|
||||||
|
elem->computed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* xsltEvalGlobalVariables:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
*
|
||||||
|
* Evaluate the global variables of a stylesheet. This need to be
|
||||||
|
* done on parsed stylesheets before starting to apply transformations
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, -1 in case of error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
|
||||||
|
xsltStackElemPtr elem;
|
||||||
|
xsltStylesheetPtr style;
|
||||||
|
|
||||||
|
if (ctxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (ctxt->xpathCtxt == NULL) {
|
||||||
|
xmlXPathInit();
|
||||||
|
ctxt->xpathCtxt = xmlXPathNewContext(ctxt->doc);
|
||||||
|
if (ctxt->xpathCtxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
XSLT_REGISTER_VARIABLE_LOOKUP(ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Evaluating global variables\n");
|
||||||
|
#endif
|
||||||
|
ctxt->node = (xmlNodePtr) ctxt->doc;
|
||||||
|
style = ctxt->style;
|
||||||
|
/* TODO: handle the stylesheet cascade */
|
||||||
|
if (style != NULL) {
|
||||||
|
elem = style->variables;
|
||||||
|
|
||||||
|
while (elem != NULL) {
|
||||||
|
xsltEvalVariables(ctxt, elem);
|
||||||
|
elem = elem->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltRegisterGlobalVariable:
|
||||||
|
* @style: the XSLT transformation context
|
||||||
|
* @name: the variable name
|
||||||
|
* @ns_uri: the variable namespace URI
|
||||||
|
* @select: the expression which need to be evaluated to generate a value
|
||||||
|
* @tree: the subtree if select is NULL
|
||||||
|
* @param: this is a parameter actually
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
|
||||||
|
const xmlChar *ns_uri, const xmlChar *select,
|
||||||
|
xmlNodePtr tree, int param) {
|
||||||
|
xsltStackElemPtr elem;
|
||||||
|
if (style == NULL)
|
||||||
|
return(-1);
|
||||||
|
if (name == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
if (param)
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Defineing global param %s\n", name);
|
||||||
|
else
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Defineing global variable %s\n", name);
|
||||||
|
#endif
|
||||||
|
elem = xsltNewStackElem();
|
||||||
|
if (elem == NULL)
|
||||||
|
return(-1);
|
||||||
|
if (param)
|
||||||
|
elem->type = XSLT_ELEM_PARAM;
|
||||||
|
else
|
||||||
|
elem->type = XSLT_ELEM_VARIABLE;
|
||||||
|
elem->name = xmlStrdup(name);
|
||||||
|
elem->select = xmlStrdup(select);
|
||||||
|
if (ns_uri)
|
||||||
|
elem->nameURI = xmlStrdup(ns_uri);
|
||||||
|
elem->tree = tree;
|
||||||
|
elem->next = style->variables;
|
||||||
|
style->variables = elem;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltRegisterVariable:
|
* xsltRegisterVariable:
|
||||||
* @ctxt: the XSLT transformation context
|
* @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
|
||||||
* @select: the expression which need to be evaluated to generate a value
|
* @select: the expression which need to be evaluated to generate a value
|
||||||
* @value: the variable value if select is NULL
|
* @tree: the tree if select is NULL
|
||||||
|
* @param: this is a parameter actually
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -286,7 +474,7 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
int
|
int
|
||||||
xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
||||||
const xmlChar *ns_uri, const xmlChar *select,
|
const xmlChar *ns_uri, const xmlChar *select,
|
||||||
xmlXPathObjectPtr value) {
|
xmlNodePtr tree, int param) {
|
||||||
xsltStackElemPtr elem;
|
xsltStackElemPtr elem;
|
||||||
if (ctxt == NULL)
|
if (ctxt == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
@@ -300,46 +488,17 @@ xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
elem = xsltNewStackElem();
|
elem = xsltNewStackElem();
|
||||||
if (elem == NULL)
|
if (elem == NULL)
|
||||||
return(-1);
|
return(-1);
|
||||||
|
if (param)
|
||||||
|
elem->type = XSLT_ELEM_PARAM;
|
||||||
|
else
|
||||||
|
elem->type = XSLT_ELEM_VARIABLE;
|
||||||
elem->name = xmlStrdup(name);
|
elem->name = xmlStrdup(name);
|
||||||
elem->select = xmlStrdup(select);
|
elem->select = xmlStrdup(select);
|
||||||
if (ns_uri)
|
if (ns_uri)
|
||||||
elem->nameURI = xmlStrdup(ns_uri);
|
elem->nameURI = xmlStrdup(ns_uri);
|
||||||
elem->value = value;
|
elem->tree = tree;
|
||||||
xsltAddStackElem(ctxt, elem);
|
xsltAddStackElem(ctxt, elem);
|
||||||
if (elem->select != NULL) {
|
xsltEvalVariables(ctxt, elem);
|
||||||
xmlXPathObjectPtr result, tmp;
|
|
||||||
xmlXPathParserContextPtr xpathParserCtxt;
|
|
||||||
|
|
||||||
xpathParserCtxt = xmlXPathNewParserContext(elem->select,
|
|
||||||
ctxt->xpathCtxt);
|
|
||||||
if (xpathParserCtxt == NULL)
|
|
||||||
goto error;
|
|
||||||
ctxt->xpathCtxt->node = ctxt->node;
|
|
||||||
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +531,7 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
|
|||||||
xsltGenericDebug(xsltGenericDebugContext,
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
"uncomputed variable %s\n", name);
|
"uncomputed variable %s\n", name);
|
||||||
#endif
|
#endif
|
||||||
TODO /* Variable value computation needed */
|
xsltEvalVariables(ctxt, elem);
|
||||||
}
|
}
|
||||||
if (elem->value != NULL)
|
if (elem->value != NULL)
|
||||||
return(xmlXPathObjectCopy(elem->value));
|
return(xmlXPathObjectCopy(elem->value));
|
||||||
@@ -408,12 +567,212 @@ xsltFreeVariableHashes(xsltTransformContextPtr ctxt) {
|
|||||||
xmlFree(stack);
|
xmlFree(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseStylesheetParam:
|
||||||
|
* @ctxt: the XSLT transformation context
|
||||||
|
* @cur: the "param" element
|
||||||
|
*
|
||||||
|
* parse an XSLT transformation param declaration and record
|
||||||
|
* its value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
||||||
|
xmlChar *name, *ncname, *prefix;
|
||||||
|
xmlChar *select;
|
||||||
|
xmlNodePtr tree = NULL;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (ctxt == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
|
||||||
|
if (name == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsl:param : missing name attribute\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Parsing param %s\n", name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
|
if (select == NULL) {
|
||||||
|
tree = cur->children;
|
||||||
|
} else {
|
||||||
|
if (cur->children != NULL)
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsl:param : 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:param : no namespace bound to prefix %s\n", prefix);
|
||||||
|
} else {
|
||||||
|
xsltRegisterVariable(ctxt, ncname, ns->href, select, tree, 1);
|
||||||
|
}
|
||||||
|
xmlFree(prefix);
|
||||||
|
} else {
|
||||||
|
xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 1);
|
||||||
|
}
|
||||||
|
xmlFree(ncname);
|
||||||
|
} else {
|
||||||
|
xsltRegisterVariable(ctxt, name, NULL, select, tree, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFree(name);
|
||||||
|
if (select != NULL)
|
||||||
|
xmlFree(select);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseGlobalVariable:
|
||||||
|
* @style: the XSLT stylesheet
|
||||||
|
* @cur: the "variable" element
|
||||||
|
*
|
||||||
|
* parse an XSLT transformation variable declaration and record
|
||||||
|
* its value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) {
|
||||||
|
xmlChar *name, *ncname, *prefix;
|
||||||
|
xmlChar *select;
|
||||||
|
xmlNodePtr tree = NULL;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (style == 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
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Parsing global variable %s\n", name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
|
if (select == NULL) {
|
||||||
|
tree = 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 {
|
||||||
|
xsltRegisterGlobalVariable(style, ncname, ns->href, select, tree, 0);
|
||||||
|
}
|
||||||
|
xmlFree(prefix);
|
||||||
|
} else {
|
||||||
|
xsltRegisterGlobalVariable(style, ncname, NULL, select, tree, 0);
|
||||||
|
}
|
||||||
|
xmlFree(ncname);
|
||||||
|
} else {
|
||||||
|
xsltRegisterGlobalVariable(style, name, NULL, select, tree, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFree(name);
|
||||||
|
if (select != NULL)
|
||||||
|
xmlFree(select);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xsltParseGlobalParam:
|
||||||
|
* @style: the XSLT stylesheet
|
||||||
|
* @cur: the "param" element
|
||||||
|
*
|
||||||
|
* parse an XSLT transformation param declaration and record
|
||||||
|
* its value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
|
||||||
|
xmlChar *name, *ncname, *prefix;
|
||||||
|
xmlChar *select;
|
||||||
|
xmlNodePtr tree = NULL;
|
||||||
|
|
||||||
|
if ((cur == NULL) || (style == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE);
|
||||||
|
if (name == NULL) {
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsl:param : missing name attribute\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_VARIABLE
|
||||||
|
xsltGenericDebug(xsltGenericDebugContext,
|
||||||
|
"Parsing global param %s\n", name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
|
if (select == NULL) {
|
||||||
|
tree = cur->children;
|
||||||
|
} else {
|
||||||
|
if (cur->children != NULL)
|
||||||
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
|
"xsl:param : 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:param : no namespace bound to prefix %s\n", prefix);
|
||||||
|
} else {
|
||||||
|
xsltRegisterGlobalVariable(style, ncname, ns->href, select, tree, 1);
|
||||||
|
}
|
||||||
|
xmlFree(prefix);
|
||||||
|
} else {
|
||||||
|
xsltRegisterGlobalVariable(style, ncname, NULL, select, tree, 1);
|
||||||
|
}
|
||||||
|
xmlFree(ncname);
|
||||||
|
} else {
|
||||||
|
xsltRegisterGlobalVariable(style, name, NULL, select, tree, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFree(name);
|
||||||
|
if (select != NULL)
|
||||||
|
xmlFree(select);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xsltParseStylesheetVariable:
|
* xsltParseStylesheetVariable:
|
||||||
* @ctxt: the XSLT transformation context
|
* @ctxt: the XSLT transformation context
|
||||||
* @template: the "variable" name
|
* @cur: the "variable" element
|
||||||
*
|
*
|
||||||
* parse an XSLT transformation context variable name and record
|
* parse an XSLT transformation variable declaration and record
|
||||||
* its value.
|
* its value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -421,7 +780,7 @@ void
|
|||||||
xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
||||||
xmlChar *name, *ncname, *prefix;
|
xmlChar *name, *ncname, *prefix;
|
||||||
xmlChar *select;
|
xmlChar *select;
|
||||||
xmlXPathObjectPtr value = NULL;
|
xmlNodePtr tree = NULL;
|
||||||
|
|
||||||
if ((cur == NULL) || (ctxt == NULL))
|
if ((cur == NULL) || (ctxt == NULL))
|
||||||
return;
|
return;
|
||||||
@@ -440,10 +799,7 @@ xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
|||||||
|
|
||||||
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
|
select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE);
|
||||||
if (select == NULL) {
|
if (select == NULL) {
|
||||||
if (cur->children == NULL)
|
tree = cur->children;
|
||||||
value = xmlXPathNewCString("");
|
|
||||||
else
|
|
||||||
value = xmlXPathNewNodeSet(cur->children);
|
|
||||||
} else {
|
} else {
|
||||||
if (cur->children != NULL)
|
if (cur->children != NULL)
|
||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
@@ -461,15 +817,15 @@ xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) {
|
|||||||
xsltGenericError(xsltGenericErrorContext,
|
xsltGenericError(xsltGenericErrorContext,
|
||||||
"xsl:variable : no namespace bound to prefix %s\n", prefix);
|
"xsl:variable : no namespace bound to prefix %s\n", prefix);
|
||||||
} else {
|
} else {
|
||||||
xsltRegisterVariable(ctxt, ncname, ns->href, select, value);
|
xsltRegisterVariable(ctxt, ncname, ns->href, select, tree, 0);
|
||||||
}
|
}
|
||||||
xmlFree(prefix);
|
xmlFree(prefix);
|
||||||
} else {
|
} else {
|
||||||
xsltRegisterVariable(ctxt, ncname, NULL, select, value);
|
xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 0);
|
||||||
}
|
}
|
||||||
xmlFree(ncname);
|
xmlFree(ncname);
|
||||||
} else {
|
} else {
|
||||||
xsltRegisterVariable(ctxt, name, NULL, select, value);
|
xsltRegisterVariable(ctxt, name, NULL, select, tree, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlFree(name);
|
xmlFree(name);
|
||||||
|
|||||||
@@ -25,10 +25,17 @@ extern "C" {
|
|||||||
* Interfaces for the variable module.
|
* Interfaces for the variable module.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int xsltEvalGlobalVariables (xsltTransformContextPtr ctxt);
|
||||||
void xsltPushStack (xsltTransformContextPtr ctxt);
|
void xsltPushStack (xsltTransformContextPtr ctxt);
|
||||||
void xsltPopStack (xsltTransformContextPtr ctxt);
|
void xsltPopStack (xsltTransformContextPtr ctxt);
|
||||||
|
void xsltParseGlobalVariable (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
|
void xsltParseGlobalParam (xsltStylesheetPtr style,
|
||||||
|
xmlNodePtr cur);
|
||||||
void xsltParseStylesheetVariable (xsltTransformContextPtr ctxt,
|
void xsltParseStylesheetVariable (xsltTransformContextPtr ctxt,
|
||||||
xmlNodePtr cur);
|
xmlNodePtr cur);
|
||||||
|
void xsltParseStylesheetParam (xsltTransformContextPtr ctxt,
|
||||||
|
xmlNodePtr cur);
|
||||||
void xsltFreeVariableHashes (xsltTransformContextPtr ctxt);
|
void xsltFreeVariableHashes (xsltTransformContextPtr ctxt);
|
||||||
xmlXPathObjectPtr xsltVariableLookup (xsltTransformContextPtr ctxt,
|
xmlXPathObjectPtr xsltVariableLookup (xsltTransformContextPtr ctxt,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
@@ -37,7 +44,8 @@ int xsltRegisterVariable (xsltTransformContextPtr ctxt,
|
|||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
const xmlChar *ns_uri,
|
const xmlChar *ns_uri,
|
||||||
const xmlChar *select,
|
const xmlChar *select,
|
||||||
xmlXPathObjectPtr value);
|
xmlNodePtr tree,
|
||||||
|
int param);
|
||||||
xmlXPathObjectPtr xsltXPathVariableLookup (void *ctxt,
|
xmlXPathObjectPtr xsltXPathVariableLookup (void *ctxt,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
const xmlChar *ns_uri);
|
const xmlChar *ns_uri);
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet) {
|
|||||||
xsltFreeTemplateList(sheet->templates);
|
xsltFreeTemplateList(sheet->templates);
|
||||||
if (sheet->doc != NULL)
|
if (sheet->doc != NULL)
|
||||||
xmlFreeDoc(sheet->doc);
|
xmlFreeDoc(sheet->doc);
|
||||||
|
if (sheet->variables != NULL)
|
||||||
|
xsltFreeStackElemList(sheet->variables);
|
||||||
if (sheet->stripSpaces != NULL)
|
if (sheet->stripSpaces != NULL)
|
||||||
xmlHashFree(sheet->stripSpaces, NULL);
|
xmlHashFree(sheet->stripSpaces, NULL);
|
||||||
|
|
||||||
@@ -563,12 +565,11 @@ skip_children:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Find and handle the params
|
* Find and handle the params
|
||||||
*/
|
|
||||||
cur = template->children;
|
cur = template->children;
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
/*
|
/ *
|
||||||
* Remove Blank nodes found at this level.
|
* Remove Blank nodes found at this level.
|
||||||
*/
|
* /
|
||||||
if (IS_BLANK_NODE(cur)) {
|
if (IS_BLANK_NODE(cur)) {
|
||||||
xmlNodePtr blank = cur;
|
xmlNodePtr blank = cur;
|
||||||
|
|
||||||
@@ -578,11 +579,12 @@ skip_children:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
|
if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
|
||||||
TODO /* Handle param */
|
xsltParseGlobalParam(style, cur);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Browse the remaining of the template
|
* Browse the remaining of the template
|
||||||
|
|||||||
@@ -19,12 +19,33 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The in-memory structure corresponding to an XSLT Stylesheet
|
* The in-memory structure corresponding to an XSLT Variable
|
||||||
* NOTE: most of the content is simply linked from the doc tree
|
* or Param
|
||||||
* structure, no specific allocation is made.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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 type; /* 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 */
|
||||||
|
xmlChar *select; /* the eval string */
|
||||||
|
xmlNodePtr tree; /* the tree if no eval string */
|
||||||
|
xmlXPathObjectPtr value; /* The value if computed */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The in-memory structure corresponding to an XSLT Template
|
||||||
|
*/
|
||||||
#define XSLT_PAT_NO_PRIORITY -12345789
|
#define XSLT_PAT_NO_PRIORITY -12345789
|
||||||
|
|
||||||
typedef struct _xsltTemplate xsltTemplate;
|
typedef struct _xsltTemplate xsltTemplate;
|
||||||
@@ -42,6 +63,8 @@ struct _xsltTemplate {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The in-memory structure corresponding to an XSLT Stylesheet
|
* The in-memory structure corresponding to an XSLT Stylesheet
|
||||||
|
* NOTE: most of the content is simply linked from the doc tree
|
||||||
|
* structure, no specific allocation is made.
|
||||||
*/
|
*/
|
||||||
typedef struct _xsltStylesheet xsltStylesheet;
|
typedef struct _xsltStylesheet xsltStylesheet;
|
||||||
typedef xsltStylesheet *xsltStylesheetPtr;
|
typedef xsltStylesheet *xsltStylesheetPtr;
|
||||||
@@ -59,6 +82,11 @@ struct _xsltStylesheet {
|
|||||||
xmlHashTablePtr stripSpaces;/* the hash table of the strip-space
|
xmlHashTablePtr stripSpaces;/* the hash table of the strip-space
|
||||||
preserve space and cdata-section elements */
|
preserve space and cdata-section elements */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global variable or parameters
|
||||||
|
*/
|
||||||
|
xsltStackElemPtr variables; /* linked list of param and variables */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Template descriptions
|
* Template descriptions
|
||||||
*/
|
*/
|
||||||
@@ -114,6 +142,7 @@ struct _xsltTransformContext {
|
|||||||
xsltStylesheetPtr xsltParseStylesheetFile (const xmlChar* filename);
|
xsltStylesheetPtr xsltParseStylesheetFile (const xmlChar* filename);
|
||||||
void xsltFreeStylesheet (xsltStylesheetPtr sheet);
|
void xsltFreeStylesheet (xsltStylesheetPtr sheet);
|
||||||
int xsltIsBlank (xmlChar *str);
|
int xsltIsBlank (xmlChar *str);
|
||||||
|
void xsltFreeStackElemList (xsltStackElemPtr elem);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ static int repeat = 0;
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv) {
|
main(int argc, char **argv) {
|
||||||
int i;
|
int i;
|
||||||
xsltStylesheetPtr cur;
|
xsltStylesheetPtr cur = NULL;
|
||||||
xmlDocPtr doc, res;
|
xmlDocPtr doc, res;
|
||||||
|
|
||||||
/* --repeat : repeat 100 times, for timing or profiling */
|
/* --repeat : repeat 100 times, for timing or profiling */
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><html lang="en">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||||
|
<html lang="en">
|
||||||
<head><title>Sales Results By Division</title></head>
|
<head><title>Sales Results By Division</title></head>
|
||||||
<body><table border="1">
|
<body><table border="1">
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user