diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | TODO | 17 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | libxslt/attributes.c | 5 | ||||
-rw-r--r-- | libxslt/extensions.c | 2 | ||||
-rw-r--r-- | libxslt/extensions.h | 1 | ||||
-rw-r--r-- | libxslt/preproc.c | 549 | ||||
-rw-r--r-- | libxslt/preproc.h | 4 | ||||
-rw-r--r-- | libxslt/templates.c | 6 | ||||
-rw-r--r-- | libxslt/templates.h | 2 | ||||
-rw-r--r-- | libxslt/transform.c | 77 | ||||
-rw-r--r-- | libxslt/variables.c | 379 | ||||
-rw-r--r-- | libxslt/variables.h | 6 | ||||
-rw-r--r-- | libxslt/xslt.c | 19 | ||||
-rw-r--r-- | libxslt/xsltInternals.h | 175 |
15 files changed, 707 insertions, 546 deletions
@@ -1,3 +1,12 @@ +Sun Apr 29 11:47:58 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr> + + * preproc.[ch] templates.[ch] variables.[ch] xslt.c xsltInternals.h + attributes.c extensions.[ch]: moved all stylesheet precomputation + at stylesheet loading time (stylesheet transform should be thread + safe now), improved params and variables evaluations (but optim + is not complete yet). + * TODO: updated + Sat Apr 28 16:28:45 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr> * libxslt/xsltproc.c : changed the way --repeat works when @@ -8,15 +8,9 @@ Doc: - manpage and doc for xsltproc Design: - - should transforms for a given stylesheet be thread clean, - or can a stylesheet be enriched with document specific - informations and cleaned up later ? - seems that saving back XSLT stylesheet from a compiled form might be a bit ugly ... -Embedding Stylesheets: - - example in 2.7 would force to validate, we do it by default now - Import: @@ -51,6 +45,17 @@ Sorting: * * ******** +Design: + - should transforms for a given stylesheet be thread clean, + -> the precompilation now occur only at stylesheet processing + time (except the binding for named templates and extension + functions which need to be computed once at run-time). + Multiple threads should be able to reuse the same stylesheet + now. + +Embedding Stylesheets: + - example in 2.7 would force to validate, we do it by default now + ID and Key support: -> Done diff --git a/configure.in b/configure.in index e2e114cc..6332e284 100644 --- a/configure.in +++ b/configure.in @@ -49,7 +49,7 @@ if test "${LOGNAME}" = "veillard" -a "`pwd`" = "/u/veillard/XSLT" ; then fi AC_ARG_WITH(debug, [ --with-debug Add the debugging code (on)]) -if test "$with_mem_debug" = "no" ; then +if test "$with_debug" = "no" ; then echo Disabling debug support WITH_XSLT_DEBUG=0 else diff --git a/libxslt/attributes.c b/libxslt/attributes.c index dde13ed7..06478b70 100644 --- a/libxslt/attributes.c +++ b/libxslt/attributes.c @@ -418,7 +418,10 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, while (style != NULL) { values = xmlHashLookup2(style->attributeSets, ncname, prefix); while (values != NULL) { - xsltAttribute(ctxt, node, values->attr, NULL); + if (values->attr != NULL) { + xsltAttribute(ctxt, node, values->attr, + values->attr->_private); + } values = values->next; } style = xsltNextImport(style); diff --git a/libxslt/extensions.c b/libxslt/extensions.c index d6d60efc..d56e6fb9 100644 --- a/libxslt/extensions.c +++ b/libxslt/extensions.c @@ -35,8 +35,6 @@ struct _xsltExtDef { xmlChar *URI; }; -const xmlChar *xsltExtMarker = (const xmlChar *)"extension"; - /************************************************************************ * * * Type functions * diff --git a/libxslt/extensions.h b/libxslt/extensions.h index d14a314c..65685848 100644 --- a/libxslt/extensions.h +++ b/libxslt/extensions.h @@ -32,7 +32,6 @@ int xsltRegisterExtElement (xsltTransformContextPtr ctxt, void xsltFreeCtxtExts (xsltTransformContextPtr ctxt); void xsltFreeExts (xsltStylesheetPtr style); -extern const xmlChar *xsltExtMarker; #ifdef __cplusplus } #endif diff --git a/libxslt/preproc.c b/libxslt/preproc.c index cdc2e5a5..aece8fc5 100644 --- a/libxslt/preproc.c +++ b/libxslt/preproc.c @@ -41,6 +41,7 @@ #define WITH_XSLT_DEBUG_PREPROC #endif +const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element"; /************************************************************************ * * @@ -50,7 +51,7 @@ /** * xsltNewStylePreComp: - * @ctxt: an XSLT processing context + * @style: the XSLT stylesheet * @type: the construct type * * Create a new XSLT Style precomputed block @@ -58,7 +59,7 @@ * Returns the newly allocated xsltStylePreCompPtr or NULL in case of error */ static xsltStylePreCompPtr -xsltNewStylePreComp(xsltTransformContextPtr ctxt, xsltStyleType type) { +xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) { xsltStylePreCompPtr cur; cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp)); @@ -105,13 +106,22 @@ xsltNewStylePreComp(xsltTransformContextPtr ctxt, xsltStyleType type) { cur->func = xsltForEach;break; case XSLT_FUNC_DOCUMENT: cur->func = xsltDocumentElem;break; + case XSLT_FUNC_WITHPARAM: + cur->func = NULL;break; + case XSLT_FUNC_PARAM: + cur->func = NULL;break; + case XSLT_FUNC_VARIABLE: + cur->func = NULL;break; + case XSLT_FUNC_WHEN: + cur->func = NULL;break; + default: + if (cur->func == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltNewStylePreComp : no function for type %d\n", type); + } } - if (cur->func == NULL) { - xsltGenericError(xsltGenericErrorContext, - "xsltNewStylePreComp : no function for type %d\n", type); - } - cur->next = ctxt->preComps; - ctxt->preComps = cur; + cur->next = style->preComps; + style->preComps = cur; return(cur); } @@ -165,8 +175,6 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) { if (comp->nsList != NULL) xmlFree(comp->nsList); - memset(comp, -1, sizeof(xsltStylePreComp)); - xmlFree(comp); } @@ -179,19 +187,19 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) { /** * xsltDocumentComp: - * @ctxt: an XSLT processing context + * @style: the XSLT stylesheet * @inst: the instruction in the stylesheet * * Pre process an XSLT-1.1 document element */ static void -xsltDocumentComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; xmlChar *filename = NULL; xmlChar *base = NULL; xmlChar *URL = NULL; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_DOCUMENT); + comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT); if (comp == NULL) return; inst->_private = comp; @@ -203,7 +211,7 @@ xsltDocumentComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { xsltGenericDebug(xsltGenericDebugContext, "Found saxon:output extension\n"); #endif - filename = xsltEvalStaticAttrValueTemplate(ctxt, inst, + filename = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"file", XSLT_SAXON_NAMESPACE, &comp->has_filename); } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) { @@ -211,11 +219,11 @@ xsltDocumentComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { xsltGenericDebug(xsltGenericDebugContext, "Found xalan:write extension\n"); #endif - filename = xsltEvalStaticAttrValueTemplate(ctxt, inst, + filename = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"select", XSLT_XALAN_NAMESPACE, &comp->has_filename); } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) { - filename = xsltEvalStaticAttrValueTemplate(ctxt, inst, + filename = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"href", XSLT_XT_NAMESPACE, &comp->has_filename); if (filename == NULL) { @@ -223,7 +231,7 @@ xsltDocumentComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { xsltGenericDebug(xsltGenericDebugContext, "Found xslt11:document construct\n"); #endif - filename = xsltEvalStaticAttrValueTemplate(ctxt, inst, + filename = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"href", XSLT_NAMESPACE, &comp->has_filename); comp->ver11 = 1; @@ -273,25 +281,25 @@ error: /** * xsltSortComp: - * @ctxt: a XSLT process context + * @style: the XSLT stylesheet * @inst: the xslt sort node * * Process the xslt sort node on the source node */ static void -xsltSortComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_SORT); + comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT); if (comp == NULL) return; inst->_private = comp; comp->inst = inst; - comp->stype = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->stype = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"data-type", XSLT_NAMESPACE, &comp->has_stype); if (comp->stype != NULL) { @@ -305,7 +313,7 @@ xsltSortComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { comp->number = -1; } } - comp->order = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->order = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"order", XSLT_NAMESPACE, &comp->has_order); if (comp->order != NULL) { @@ -335,19 +343,19 @@ xsltSortComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltCopyComp: - * @ctxt: a XSLT process context + * @style: the XSLT stylesheet * @inst: the xslt copy node * * Process the xslt copy node on the source node */ static void -xsltCopyComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_COPY); + comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY); if (comp == NULL) return; inst->_private = comp; @@ -364,19 +372,19 @@ xsltCopyComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltTextComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt text node * * Process the xslt text node on the source node */ static void -xsltTextComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; xmlChar *prop; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_TEXT); + comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT); if (comp == NULL) return; inst->_private = comp; @@ -400,18 +408,18 @@ xsltTextComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltElementComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt element node * * Process the xslt element node on the source node */ static void -xsltElementComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_ELEMENT); + comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT); if (comp == NULL) return; inst->_private = comp; @@ -420,32 +428,32 @@ xsltElementComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /* * TODO: more computation can be done there, especially namespace lookup */ - comp->name = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->name = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE, &comp->has_name); - comp->ns = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->ns = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"namespace", XSLT_NAMESPACE, &comp->has_ns); - comp->use = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->use = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"use-attribute-sets", XSLT_NAMESPACE, &comp->has_use); } /** * xsltAttributeComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt attribute node * * Process the xslt attribute node on the source node */ static void -xsltAttributeComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_ATTRIBUTE); + comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE); if (comp == NULL) return; inst->_private = comp; @@ -454,10 +462,10 @@ xsltAttributeComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /* * TODO: more computation can be done there, especially namespace lookup */ - comp->name = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->name = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE, &comp->has_name); - comp->ns = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->ns = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"namespace", XSLT_NAMESPACE, &comp->has_ns); @@ -465,18 +473,18 @@ xsltAttributeComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltCommentComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt comment node * * Process the xslt comment node on the source node */ static void -xsltCommentComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_COMMENT); + comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT); if (comp == NULL) return; inst->_private = comp; @@ -485,42 +493,42 @@ xsltCommentComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltProcessingInstructionComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt processing-instruction node * * Process the xslt processing-instruction node on the source node */ static void -xsltProcessingInstructionComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_PI); + comp = xsltNewStylePreComp(style, XSLT_FUNC_PI); if (comp == NULL) return; inst->_private = comp; comp->inst = inst; - comp->name = xsltEvalStaticAttrValueTemplate(ctxt, inst, + comp->name = xsltEvalStaticAttrValueTemplate(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE, &comp->has_name); } /** * xsltCopyOfComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt copy-of node * * Process the xslt copy-of node on the source node */ static void -xsltCopyOfComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_COPYOF); + comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF); if (comp == NULL) return; inst->_private = comp; @@ -536,19 +544,19 @@ xsltCopyOfComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltValueOfComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt value-of node * * Process the xslt value-of node on the source node */ static void -xsltValueOfComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; xmlChar *prop; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_VALUEOF); + comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF); if (comp == NULL) return; inst->_private = comp; @@ -576,25 +584,96 @@ xsltValueOfComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { } /** + * xsltWithParamComp: + * @style: a XSLT process context + * @inst: the xslt with-param node + * + * Process the xslt with-param node on the source node + */ +static void +xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) { + xsltStylePreCompPtr comp; + xmlChar *prop; + xmlChar *ncname = NULL; + xmlChar *prefix = NULL; + xmlNsPtr ns = NULL; + + if ((style == NULL) || (inst == NULL)) + return; + comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM); + if (comp == NULL) + return; + inst->_private = comp; + comp->inst = inst; + + /* + * The full namespace resolution can be done statically + */ + prop = xmlGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE); + if (prop == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xslt:with-param : name is missing\n"); + } else { + + ncname = xmlSplitQName2(prop, &prefix); + if (ncname == NULL) { + ncname = prop; + prop = NULL; + prefix = NULL; + } + if (prefix != NULL) { + ns = xmlSearchNs(inst->doc, inst, prefix); + if (ns == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xslt:with-param : no namespace bound to prefix %s\n", prefix); + } + } + comp->name = xmlStrdup(ncname); + comp->has_name = 1; + if (ns != NULL) { + comp->has_ns = 1; + comp->ns = xmlStrdup(ns->href); + } else + comp->has_ns = 0; + } + + comp->select = xmlGetNsProp(inst, (const xmlChar *)"select", + XSLT_NAMESPACE); + if (comp->select != NULL) { + if (inst->children != NULL) + xsltGenericError(xsltGenericErrorContext, + "xsl:param : content should be empty since select is present \n"); + } + comp->comp = NULL; + + if (prop != NULL) + xmlFree(prop); + if (ncname != NULL) + xmlFree(ncname); + if (prefix != NULL) + xmlFree(prefix); +} + +/** * xsltNumberComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @cur: the xslt number node * * Process the xslt number node on the source node */ static void -xsltNumberComp(xsltTransformContextPtr ctxt, xmlNodePtr cur) { +xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) { xsltStylePreCompPtr comp; xmlChar *prop; - if ((ctxt == NULL) || (cur == NULL)) + if ((style == NULL) || (cur == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_NUMBER); + comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER); if (comp == NULL) return; cur->_private = comp; - if ((ctxt == NULL) || (cur == NULL)) + if ((style == NULL) || (cur == NULL)) return; comp->numdata.doc = cur->doc; @@ -671,18 +750,18 @@ xsltNumberComp(xsltTransformContextPtr ctxt, xmlNodePtr cur) { /** * xsltApplyImportsComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt apply-imports node * * Process the xslt apply-imports node on the source node */ static void -xsltApplyImportsComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_APPLYIMPORTS); + comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS); if (comp == NULL) return; inst->_private = comp; @@ -691,22 +770,22 @@ xsltApplyImportsComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltCallTemplateComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt call-template node * * Process the xslt call-template node on the source node */ static void -xsltCallTemplateComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; xmlChar *prop; xmlChar *ncname = NULL; xmlChar *prefix = NULL; xmlNsPtr ns = NULL; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_CALLTEMPLATE); + comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE); if (comp == NULL) return; inst->_private = comp; @@ -728,25 +807,22 @@ xsltCallTemplateComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { prefix = NULL; } if (prefix != NULL) { - ns = xmlSearchNs(ctxt->insert->doc, ctxt->insert, prefix); + ns = xmlSearchNs(inst->doc, inst, prefix); if (ns == NULL) { xsltGenericError(xsltGenericErrorContext, - "no namespace bound to prefix %s\n", prefix); + "xslt:call-template : no namespace bound to prefix %s\n", prefix); } } - if (ns != NULL) - comp->templ = xsltFindTemplate(ctxt, ncname, ns->href); - else - comp->templ = xsltFindTemplate(ctxt, ncname, NULL); - - if (comp->templ == NULL) { - xsltGenericError(xsltGenericErrorContext, - "xslt:call-template : template %s not found\n", ncname); - } + comp->name = xmlStrdup(ncname); + comp->has_name = 1; + if (ns != NULL) { + comp->ns = xmlStrdup(ns->href); + comp->has_ns = 1; + } else + comp->has_ns = 0; + comp->templ = NULL; } - /* TODO: with-param could be optimized too */ - if (prop != NULL) xmlFree(prop); if (ncname != NULL) @@ -757,19 +833,19 @@ xsltCallTemplateComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltApplyTemplatesComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the apply-templates node * * Process the apply-templates node on the source node */ static void -xsltApplyTemplatesComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; xmlChar *prop; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_APPLYTEMPLATES); + comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES); if (comp == NULL) return; inst->_private = comp; @@ -817,18 +893,18 @@ xsltApplyTemplatesComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltChooseComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt choose node * * Process the xslt choose node on the source node */ static void -xsltChooseComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_CHOOSE); + comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE); if (comp == NULL) return; inst->_private = comp; @@ -837,18 +913,18 @@ xsltChooseComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltIfComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt if node * * Process the xslt if node on the source node */ static void -xsltIfComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_IF); + comp = xsltNewStylePreComp(style, XSLT_FUNC_IF); if (comp == NULL) return; inst->_private = comp; @@ -857,25 +933,52 @@ xsltIfComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { comp->test = xmlGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE); if (comp->test == NULL) { xsltGenericError(xsltGenericErrorContext, - "xsltIf: test is not defined\n"); + "xslt:if : test is not defined\n"); + return; + } +} + +/** + * xsltWhenComp: + * @style: a XSLT process context + * @inst: the xslt if node + * + * Process the xslt if node on the source node + */ +static void +xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) { + xsltStylePreCompPtr comp; + + if ((style == NULL) || (inst == NULL)) + return; + comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN); + if (comp == NULL) + return; + inst->_private = comp; + comp->inst = inst; + + comp->test = xmlGetNsProp(inst, (const xmlChar *)"test", XSLT_NAMESPACE); + if (comp->test == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:when : test is not defined\n"); return; } } /** * xsltForEachComp: - * @ctxt: a XSLT process context + * @style: a XSLT process context * @inst: the xslt for-each node * * Process the xslt for-each node on the source node */ static void -xsltForEachComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) { xsltStylePreCompPtr comp; - if ((ctxt == NULL) || (inst == NULL)) + if ((style == NULL) || (inst == NULL)) return; - comp = xsltNewStylePreComp(ctxt, XSLT_FUNC_FOREACH); + comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH); if (comp == NULL) return; inst->_private = comp; @@ -887,6 +990,144 @@ xsltForEachComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /* TODO: handle and skip the xsl:sort */ } +/** + * xsltVariableComp: + * @style: a XSLT process context + * @inst: the xslt variable node + * + * Process the xslt variable node on the source node + */ +static void +xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) { + xsltStylePreCompPtr comp; + xmlChar *prop; + xmlChar *ncname = NULL; + xmlChar *prefix = NULL; + xmlNsPtr ns = NULL; + + if ((style == NULL) || (inst == NULL)) + return; + comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE); + if (comp == NULL) + return; + inst->_private = comp; + comp->inst = inst; + + /* + * The full template resolution can be done statically + */ + prop = xmlGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE); + if (prop == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xslt:variable : name is missing\n"); + } else { + ncname = xmlSplitQName2(prop, &prefix); + if (ncname == NULL) { + ncname = prop; + prop = NULL; + prefix = NULL; + } + if (prefix != NULL) { + ns = xmlSearchNs(inst->doc, inst, prefix); + if (ns == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:variable no namespace bound to prefix %s\n", prefix); + } + } + comp->name = xmlStrdup(ncname); + comp->has_name = 1; + if (ns != NULL) { + comp->ns = xmlStrdup(ns->href); + comp->has_ns = 1; + } else + comp->has_ns = 0; + } + + comp->select = xmlGetNsProp(inst, (const xmlChar *)"select", + XSLT_NAMESPACE); + if (comp->select != NULL) { + if (inst->children != NULL) + xsltGenericError(xsltGenericErrorContext, + "xsl:variable : content should be empty since select is present \n"); + } + + if (prop != NULL) + xmlFree(prop); + if (ncname != NULL) + xmlFree(ncname); + if (prefix != NULL) + xmlFree(prefix); +} + +/** + * xsltParamComp: + * @style: a XSLT process context + * @inst: the xslt param node + * + * Process the xslt param node on the source node + */ +static void +xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) { + xsltStylePreCompPtr comp; + xmlChar *prop; + xmlChar *ncname = NULL; + xmlChar *prefix = NULL; + xmlNsPtr ns = NULL; + + if ((style == NULL) || (inst == NULL)) + return; + comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM); + if (comp == NULL) + return; + inst->_private = comp; + comp->inst = inst; + + /* + * The full template resolution can be done statically + */ + prop = xmlGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE); + if (prop == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xslt:param : name is missing\n"); + } else { + ncname = xmlSplitQName2(prop, &prefix); + if (ncname == NULL) { + ncname = prop; + prop = NULL; + prefix = NULL; + } + if (prefix != NULL) { + ns = xmlSearchNs(inst->doc, inst, prefix); + if (ns == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:param no namespace bound to prefix %s\n", prefix); + } + } + comp->name = xmlStrdup(ncname); + comp->has_name = 1; + if (ns != NULL) { + comp->ns = xmlStrdup(ns->href); + comp->has_ns = 1; + } else + comp->has_ns = 0; + } + + comp->select = xmlGetNsProp(inst, (const xmlChar *)"select", + XSLT_NAMESPACE); + if (comp->select != NULL) { + if (inst->children != NULL) + xsltGenericError(xsltGenericErrorContext, + "xsl:variable : content should be empty since select is present \n"); + } + + if (prop != NULL) + xmlFree(prop); + if (ncname != NULL) + xmlFree(ncname); + if (prefix != NULL) + xmlFree(prefix); +} + /************************************************************************ * * @@ -896,17 +1137,17 @@ xsltForEachComp(xsltTransformContextPtr ctxt, xmlNodePtr inst) { /** * xsltFreeStylePreComps: - * @ctxt: an XSLT transformation context + * @style: an XSLT transformation context * * Free up the memory allocated by all precomputed blocks */ void -xsltFreeStylePreComps(xsltTransformContextPtr ctxt) { +xsltFreeStylePreComps(xsltStylesheetPtr style) { xsltStylePreCompPtr cur, next; - if (ctxt == NULL) + if (style == NULL) return; - cur = ctxt->preComps; + cur = style->preComps; while (cur != NULL) { next = cur->next; xsltFreeStylePreComp(cur); @@ -916,61 +1157,99 @@ xsltFreeStylePreComps(xsltTransformContextPtr ctxt) { /** * xsltDocumentCompute: - * @ctxt: an XSLT processing context + * @style: the XSLT stylesheet * @inst: the instruction in the stylesheet * * Precompute an XSLT stylesheet element */ void -xsltStylePreCompute(xsltTransformContextPtr ctxt, xmlNodePtr inst) { +xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) { if (inst->_private != NULL) return; if (IS_XSLT_ELEM(inst)) { xsltStylePreCompPtr cur; if (IS_XSLT_NAME(inst, "apply-templates")) { - xsltApplyTemplatesComp(ctxt, inst); + xsltApplyTemplatesComp(style, inst); + } else if (IS_XSLT_NAME(inst, "with-param")) { + xsltWithParamComp(style, inst); } else if (IS_XSLT_NAME(inst, "value-of")) { - xsltValueOfComp(ctxt, inst); + xsltValueOfComp(style, inst); } else if (IS_XSLT_NAME(inst, "copy")) { - xsltCopyComp(ctxt, inst); + xsltCopyComp(style, inst); } else if (IS_XSLT_NAME(inst, "copy-of")) { - xsltCopyOfComp(ctxt, inst); + xsltCopyOfComp(style, inst); } else if (IS_XSLT_NAME(inst, "if")) { - xsltIfComp(ctxt, inst); + xsltIfComp(style, inst); + } else if (IS_XSLT_NAME(inst, "when")) { + xsltWhenComp(style, inst); } else if (IS_XSLT_NAME(inst, "choose")) { - xsltChooseComp(ctxt, inst); + xsltChooseComp(style, inst); } else if (IS_XSLT_NAME(inst, "for-each")) { - xsltForEachComp(ctxt, inst); + xsltForEachComp(style, inst); } else if (IS_XSLT_NAME(inst, "apply-imports")) { - xsltApplyImportsComp(ctxt, inst); + xsltApplyImportsComp(style, inst); } else if (IS_XSLT_NAME(inst, "attribute")) { - xsltAttributeComp(ctxt, inst); + xsltAttributeComp(style, inst); } else if (IS_XSLT_NAME(inst, "element")) { - xsltElementComp(ctxt, inst); + xsltElementComp(style, inst); } else if (IS_XSLT_NAME(inst, "text")) { - xsltTextComp(ctxt, inst); + xsltTextComp(style, inst); } else if (IS_XSLT_NAME(inst, "sort")) { - xsltSortComp(ctxt, inst); + xsltSortComp(style, inst); } else if (IS_XSLT_NAME(inst, "comment")) { - xsltCommentComp(ctxt, inst); + xsltCommentComp(style, inst); } else if (IS_XSLT_NAME(inst, "number")) { - xsltNumberComp(ctxt, inst); + xsltNumberComp(style, inst); } else if (IS_XSLT_NAME(inst, "processing-instruction")) { - xsltProcessingInstructionComp(ctxt, inst); + xsltProcessingInstructionComp(style, inst); } else if (IS_XSLT_NAME(inst, "call-template")) { - xsltCallTemplateComp(ctxt, inst); + xsltCallTemplateComp(style, inst); } else if (IS_XSLT_NAME(inst, "param")) { - /* TODO: is there any use optimizing param too ? */ - return; + xsltParamComp(style, inst); } else if (IS_XSLT_NAME(inst, "variable")) { - /* TODO: is there any use optimizing variable too ? */ + xsltVariableComp(style, inst); + } else if (IS_XSLT_NAME(inst, "otherwise")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "template")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "output")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "preserve-space")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "strip-space")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "stylesheet")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "key")) { + /* no computation needed */ return; } else if (IS_XSLT_NAME(inst, "message")) { - /* no optimization needed */ + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "attribute-set")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "namespace-alias")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "include")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "import")) { + /* no computation needed */ + return; + } else if (IS_XSLT_NAME(inst, "decimal-format")) { + /* no computation needed */ return; } else if (IS_XSLT_NAME(inst, "document")) { - xsltDocumentComp(ctxt, inst); + xsltDocumentComp(style, inst); } else { xsltGenericError(xsltGenericDebugContext, "xsltStylePreCompute: unknown xslt:%s\n", inst->name); @@ -992,7 +1271,13 @@ xsltStylePreCompute(xsltTransformContextPtr ctxt, xmlNodePtr inst) { } } else { if (IS_XSLT_NAME(inst, "document")) { - xsltDocumentComp(ctxt, inst); + xsltDocumentComp(style, inst); + } else { + /* + * Mark the element for later recognition. + */ + if (inst->_private == NULL) + inst->_private = (void *) xsltExtMarker; } } } diff --git a/libxslt/preproc.h b/libxslt/preproc.h index f07412ea..7700db6d 100644 --- a/libxslt/preproc.h +++ b/libxslt/preproc.h @@ -19,9 +19,9 @@ extern "C" { /* * Interfaces */ -void xsltStylePreCompute (xsltTransformContextPtr ctxt, +void xsltStylePreCompute (xsltStylesheetPtr style, xmlNodePtr inst); -void xsltFreeStylePreComps (xsltTransformContextPtr ctxt); +void xsltFreeStylePreComps (xsltStylesheetPtr style); #ifdef __cplusplus } #endif diff --git a/libxslt/templates.c b/libxslt/templates.c index db21a2a2..ea9aa2d5 100644 --- a/libxslt/templates.c +++ b/libxslt/templates.c @@ -262,7 +262,7 @@ xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, /** * xsltEvalStaticAttrValueTemplate: - * @ctxt: the XSLT transformation context + * @style: the XSLT stylesheet * @node: the stylesheet node * @name: the attribute Name * @name: the attribute namespace URI @@ -275,12 +275,12 @@ xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, * caller. */ xmlChar * -xsltEvalStaticAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, +xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr node, const xmlChar *name, const xmlChar *ns, int *found) { const xmlChar *ret; xmlChar *expr; - if ((ctxt == NULL) || (node == NULL) || (name == NULL)) + if ((style == NULL) || (node == NULL) || (name == NULL)) return(NULL); expr = xmlGetNsProp(node, name, ns); diff --git a/libxslt/templates.h b/libxslt/templates.h index 78edefcf..02637c5a 100644 --- a/libxslt/templates.h +++ b/libxslt/templates.h @@ -26,7 +26,7 @@ xmlChar * xsltEvalAttrValueTemplate (xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *name, const xmlChar *ns); -xmlChar * xsltEvalStaticAttrValueTemplate (xsltTransformContextPtr ctxt, +xmlChar * xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style, xmlNodePtr node, const xmlChar *name, const xmlChar *ns, diff --git a/libxslt/transform.c b/libxslt/transform.c index d4fe1d89..052adc38 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -214,7 +214,6 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) { xmlFree(ctxt->varsTab); xsltFreeDocuments(ctxt); xsltFreeCtxtExts(ctxt); - xsltFreeStylePreComps(ctxt); memset(ctxt, -1, sizeof(xsltTransformContext)); xmlFree(ctxt); } @@ -876,20 +875,18 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, } if (IS_XSLT_ELEM(cur)) { - if (cur->_private == NULL) - xsltStylePreCompute(ctxt, cur); + xsltStylePreCompPtr info = (xsltStylePreCompPtr) cur->_private; + if (info == NULL) { + xsltGenericError(xsltGenericDebugContext, + "xsltApplyOneTemplate: %s was not compiled\n", + cur->name); + goto skip_children; + } - if (cur->_private != NULL) { - xsltStylePreCompPtr info = (xsltStylePreCompPtr) cur->_private; - if (info->func != NULL) { - ctxt->insert = insert; - info->func(ctxt, node, cur, info); - ctxt->insert = oldInsert; - } else { - xsltGenericError(xsltGenericDebugContext, - "xsltApplyOneTemplate: %s has _private without function\n", - cur->name); - } + if (info->func != NULL) { + ctxt->insert = insert; + info->func(ctxt, node, cur, info); + ctxt->insert = oldInsert; goto skip_children; } @@ -953,10 +950,6 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, "xsltApplyOneTemplate: extension construct %s\n", cur->name); #endif - if (cur->_private == (void *) xsltExtMarker) { - cur->_private = NULL; - xsltStylePreCompute(ctxt, cur); - } ctxt->insert = insert; function(ctxt, node, cur, cur->_private); ctxt->insert = oldInsert; @@ -1195,8 +1188,9 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr oldNode; if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; + xsltGenericError(xsltGenericErrorContext, + "xslt:sort : compilation had failed\n"); + return; } if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) @@ -1560,8 +1554,9 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node, if (ctxt->insert == NULL) return; if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; + xsltGenericError(xsltGenericErrorContext, + "xslt:attribute : compilation had failed\n"); + return; } if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) @@ -1916,8 +1911,9 @@ xsltNumber(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; + xsltGenericError(xsltGenericErrorContext, + "xslt:number : compilation had failed\n"); + return; } if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) @@ -1974,18 +1970,24 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStackElemPtr params = NULL, param; - if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; - } if (ctxt->insert == NULL) return; + if (comp == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xslt:call-template : compilation had failed\n"); + return; + } /* * The template must have been precomputed */ - if (comp->templ == NULL) - return; + if (comp->templ == NULL) { + comp->templ = xsltFindTemplate(ctxt, comp->name, comp->ns); + if (comp->templ == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xslt:call-template : template %s not found\n", comp->name); + } + } /* * Create a new frame but block access to variables @@ -2039,8 +2041,9 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node, if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; + xsltGenericError(xsltGenericErrorContext, + "xslt:apply-templates : compilation had failed\n"); + return; } if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) return; @@ -2363,8 +2366,9 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node, int oldContextSize, oldProximityPosition; if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; + xsltGenericError(xsltGenericErrorContext, + "xslt:if : compilation had failed\n"); + return; } if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) return; @@ -2439,8 +2443,9 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr oldNode = ctxt->node; if (comp == NULL) { - xsltStylePreCompute(ctxt, inst); - comp = inst->_private; + xsltGenericError(xsltGenericErrorContext, + "xslt:for-each : compilation had failed\n"); + return; } if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) return; diff --git a/libxslt/variables.c b/libxslt/variables.c index 8730de53..3a5d7b28 100644 --- a/libxslt/variables.c +++ b/libxslt/variables.c @@ -28,6 +28,7 @@ #include "variables.h" #include "transform.h" #include "imports.h" +#include "preproc.h" #ifdef WITH_XSLT_DEBUG #define WITH_XSLT_DEBUG_VARIABLE @@ -245,8 +246,9 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name, * Returns 0 in case of success, -1 in case of error */ static int -xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) { -int oldProximityPosition, oldContextSize; +xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem, + xsltStylePreCompPtr precomp) { + int oldProximityPosition, oldContextSize; if ((ctxt == NULL) || (elem == NULL)) return(-1); @@ -255,10 +257,18 @@ int oldProximityPosition, oldContextSize; "Evaluating variable %s\n", elem->name); #endif if (elem->select != NULL) { - xmlXPathCompExprPtr comp; + xmlXPathCompExprPtr comp = NULL; xmlXPathObjectPtr result; - comp = xmlXPathCompile(elem->select); + if (precomp != NULL) { + comp = precomp->comp; + if (comp == NULL) { + comp = xmlXPathCompile(elem->select); + precomp->comp = comp; + } + } else { + comp = xmlXPathCompile(elem->select); + } if (comp == NULL) return(-1); oldProximityPosition = ctxt->xpathCtxt->proximityPosition; @@ -270,7 +280,8 @@ int oldProximityPosition, oldContextSize; result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt); ctxt->xpathCtxt->contextSize = oldContextSize; ctxt->xpathCtxt->proximityPosition = oldProximityPosition; - xmlXPathFreeCompExpr(comp); + if (precomp == NULL) + xmlXPathFreeCompExpr(comp); if (result == NULL) { xsltGenericError(xsltGenericErrorContext, "Evaluating variable %s failed\n", elem->name); @@ -358,7 +369,7 @@ xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) { while (elem != NULL) { if (elem->computed == 0) - xsltEvalVariable(ctxt, elem); + xsltEvalVariable(ctxt, elem, NULL); elem = elem->next; } @@ -498,21 +509,16 @@ xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) { * Returns the xsltStackElemPtr or NULL in case of error */ static xsltStackElemPtr -xsltBuildVariable(xsltTransformContextPtr ctxt, const xmlChar *name, - const xmlChar *ns_uri, const xmlChar *select, - xmlNodePtr tree, int param) { +xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp, + xmlNodePtr tree, int param) { xsltStackElemPtr elem; - if (ctxt == NULL) - return(NULL); - if (name == NULL) - return(NULL); #ifdef WITH_XSLT_DEBUG_VARIABLE xsltGenericDebug(xsltGenericDebugContext, - "Building variable %s", name); - if (select != NULL) + "Building variable %s", comp->name); + if (comp->select != NULL) xsltGenericDebug(xsltGenericDebugContext, - " select %s", select); + " select %s", comp->select); xsltGenericDebug(xsltGenericDebugContext, "\n"); #endif elem = xsltNewStackElem(); @@ -522,15 +528,15 @@ xsltBuildVariable(xsltTransformContextPtr ctxt, const xmlChar *name, elem->type = XSLT_ELEM_PARAM; else elem->type = XSLT_ELEM_VARIABLE; - elem->name = xmlStrdup(name); - if (select != NULL) - elem->select = xmlStrdup(select); + elem->name = xmlStrdup(comp->name); + if (comp->select != NULL) + elem->select = xmlStrdup(comp->select); else elem->select = NULL; - if (ns_uri) - elem->nameURI = xmlStrdup(ns_uri); + if (comp->ns) + elem->nameURI = xmlStrdup(comp->ns); elem->tree = tree; - xsltEvalVariable(ctxt, elem); + xsltEvalVariable(ctxt, elem, comp); return(elem); } @@ -547,29 +553,24 @@ xsltBuildVariable(xsltTransformContextPtr ctxt, const xmlChar *name, * * Returns 0 in case of success, -1 in case of error */ -int -xsltRegisterVariable(xsltTransformContextPtr ctxt, const xmlChar *name, - const xmlChar *ns_uri, const xmlChar *select, +static int +xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr comp, xmlNodePtr tree, int param) { xsltStackElemPtr elem; - if (ctxt == NULL) - return(-1); - if (name == NULL) - return(-1); - if (xsltCheckStackElem(ctxt, name, ns_uri) != 0) { + if (xsltCheckStackElem(ctxt, comp->name, comp->ns) != 0) { if (!param) { xsltGenericError(xsltGenericErrorContext, - "xsl:variable : redefining %s\n", name); + "xsl:variable : redefining %s\n", comp->name); } #ifdef WITH_XSLT_DEBUG_VARIABLE else xsltGenericDebug(xsltGenericDebugContext, - "param %s defined by caller", name); + "param %s defined by caller", comp->name); #endif return(0); } - elem = xsltBuildVariable(ctxt, name, ns_uri, select, tree, param); + elem = xsltBuildVariable(ctxt, comp, tree, param); xsltAddStackElem(ctxt, elem); return(0); } @@ -621,7 +622,7 @@ xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, xsltGenericDebug(xsltGenericDebugContext, "uncomputed global variable %s\n", name); #endif - xsltEvalVariable(ctxt, elem); + xsltEvalVariable(ctxt, elem, NULL); } if (elem->value != NULL) return(xmlXPathObjectCopy(elem->value)); @@ -660,7 +661,7 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, xsltGenericDebug(xsltGenericDebugContext, "uncomputed variable %s\n", name); #endif - xsltEvalVariable(ctxt, elem); + xsltEvalVariable(ctxt, elem, NULL); } if (elem->value != NULL) return(xmlXPathObjectCopy(elem->value)); @@ -684,137 +685,43 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, xsltStackElemPtr xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) { - xmlChar *name, *ncname, *prefix; - xmlChar *select; xmlNodePtr tree = NULL; xsltStackElemPtr elem = NULL; + xsltStylePreCompPtr comp; if ((cur == NULL) || (ctxt == NULL)) return(NULL); - - name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE); - if (name == NULL) { + comp = (xsltStylePreCompPtr) cur->_private; + if (comp == NULL) { xsltGenericError(xsltGenericErrorContext, - "xsl:param : missing name attribute\n"); + "xsl:param : compilation error\n"); return(NULL); } -#ifdef WITH_XSLT_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 { -#ifdef WITH_XSLT_DEBUG_VARIABLE - xsltGenericDebug(xsltGenericDebugContext, - " select %s\n", select); -#endif - 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 { - elem = xsltBuildVariable(ctxt, ncname, ns->href, select, - tree, 1); - } - xmlFree(prefix); - } else { - elem = xsltBuildVariable(ctxt, ncname, NULL, select, tree, 1); - } - xmlFree(ncname); - } else { - elem = xsltBuildVariable(ctxt, name, NULL, select, tree, 1); - } - - xmlFree(name); - if (select != NULL) - xmlFree(select); - return(elem); -} - -/** - * 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) { + if (comp->name == NULL) { xsltGenericError(xsltGenericErrorContext, "xsl:param : missing name attribute\n"); - return; + return(NULL); } - #ifdef WITH_XSLT_DEBUG_VARIABLE xsltGenericDebug(xsltGenericDebugContext, - "Parsing param %s\n", name); + "Handling param %s\n", comp->name); #endif - select = xmlGetNsProp(cur, (const xmlChar *)"select", XSLT_NAMESPACE); - if (select == NULL) { + + if (comp->select == NULL) { tree = cur->children; } else { #ifdef WITH_XSLT_DEBUG_VARIABLE xsltGenericDebug(xsltGenericDebugContext, - " select %s\n", select); + " select %s\n", comp->select); #endif - if (cur->children != NULL) - xsltGenericError(xsltGenericErrorContext, - "xsl:param : content shuld be empty since select is present \n"); + tree = cur; } - 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); + elem = xsltBuildVariable(ctxt, comp, tree, 1); + return(elem); } /** @@ -828,15 +735,20 @@ xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) { void xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) { - xmlChar *name, *ncname, *prefix; - xmlChar *select; - xmlNodePtr tree = NULL; + xsltStylePreCompPtr comp; if ((cur == NULL) || (style == NULL)) return; - name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE); - if (name == NULL) { + xsltStylePreCompute(style, cur); + comp = (xsltStylePreCompPtr) cur->_private; + if (comp == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:variable : compilation had failed\n"); + return; + } + + if (comp->name == NULL) { xsltGenericError(xsltGenericErrorContext, "xsl:variable : missing name attribute\n"); return; @@ -844,46 +756,11 @@ xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) { #ifdef WITH_XSLT_DEBUG_VARIABLE xsltGenericDebug(xsltGenericDebugContext, - "Parsing global variable %s\n", name); + "Registering global variable %s\n", comp->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, NULL); - } - xmlFree(prefix); - } else { - xsltRegisterGlobalVariable(style, ncname, NULL, select, tree, - 0, NULL); - } - xmlFree(ncname); - } else { - xsltRegisterGlobalVariable(style, name, NULL, select, tree, 0, NULL); - } - - xmlFree(name); - if (select != NULL) - xmlFree(select); - + xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select, + cur->children, 0, NULL); } /** @@ -897,15 +774,20 @@ xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur) { void xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) { - xmlChar *name, *ncname, *prefix; - xmlChar *select; - xmlNodePtr tree = NULL; + xsltStylePreCompPtr comp; if ((cur == NULL) || (style == NULL)) return; - name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE); - if (name == NULL) { + xsltStylePreCompute(style, cur); + comp = (xsltStylePreCompPtr) cur->_private; + if (comp == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:param : compilation had failed\n"); + return; + } + + if (comp->name == NULL) { xsltGenericError(xsltGenericErrorContext, "xsl:param : missing name attribute\n"); return; @@ -913,45 +795,11 @@ xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) { #ifdef WITH_XSLT_DEBUG_VARIABLE xsltGenericDebug(xsltGenericDebugContext, - "Parsing global param %s\n", name); + "Registering global param %s\n", comp->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, NULL); - } - xmlFree(prefix); - } else { - xsltRegisterGlobalVariable(style, ncname, NULL, select, tree, - 1, NULL); - } - xmlFree(ncname); - } else { - xsltRegisterGlobalVariable(style, name, NULL, select, tree, 1, NULL); - } - - xmlFree(name); - if (select != NULL) - xmlFree(select); + xsltRegisterGlobalVariable(style, comp->name, comp->ns, comp->select, + cur->children, 1, NULL); } /** @@ -965,15 +813,19 @@ xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) { void xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) { - xmlChar *name, *ncname, *prefix; - xmlChar *select; - xmlNodePtr tree = NULL; + xsltStylePreCompPtr comp; if ((cur == NULL) || (ctxt == NULL)) return; - name = xmlGetNsProp(cur, (const xmlChar *)"name", XSLT_NAMESPACE); - if (name == NULL) { + comp = (xsltStylePreCompPtr) cur->_private; + if (comp == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:variable : compilation had failed\n"); + return; + } + + if (comp->name == NULL) { xsltGenericError(xsltGenericErrorContext, "xsl:variable : missing name attribute\n"); return; @@ -981,44 +833,47 @@ xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur) { #ifdef WITH_XSLT_DEBUG_VARIABLE xsltGenericDebug(xsltGenericDebugContext, - "Parsing variable %s\n", name); + "Registering variable %s\n", comp->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 should be empty since select is present \n"); - } + xsltRegisterVariable(ctxt, comp, cur->children, 0); +} + +/** + * xsltParseStylesheetParam: + * @ctxt: the XSLT transformation context + * @cur: the "param" element + * + * parse an XSLT transformation param declaration and record + * its value. + */ - ncname = xmlSplitQName2(name, &prefix); +void +xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur) { + xsltStylePreCompPtr comp; - if (ncname != NULL) { - if (prefix != NULL) { - xmlNsPtr ns; + if ((cur == NULL) || (ctxt == NULL)) + return; - 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, tree, 0); - } - xmlFree(prefix); - } else { - xsltRegisterVariable(ctxt, ncname, NULL, select, tree, 0); - } - xmlFree(ncname); - } else { - xsltRegisterVariable(ctxt, name, NULL, select, tree, 0); + comp = (xsltStylePreCompPtr) cur->_private; + if (comp == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:param : compilation had failed\n"); + return; } - xmlFree(name); - if (select != NULL) - xmlFree(select); + if (comp->name == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsl:param : missing name attribute\n"); + return; + } + +#ifdef WITH_XSLT_DEBUG_VARIABLE + xsltGenericDebug(xsltGenericDebugContext, + "Registering param %s\n", comp->name); +#endif + xsltRegisterVariable(ctxt, comp, cur->children, 1); } /** diff --git a/libxslt/variables.h b/libxslt/variables.h index 17f6576a..f9eb792c 100644 --- a/libxslt/variables.h +++ b/libxslt/variables.h @@ -54,12 +54,6 @@ void xsltFreeVariableHashes (xsltTransformContextPtr ctxt); xmlXPathObjectPtr xsltVariableLookup (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri); -int xsltRegisterVariable (xsltTransformContextPtr ctxt, - const xmlChar *name, - const xmlChar *ns_uri, - const xmlChar *select, - xmlNodePtr tree, - int param); xmlXPathObjectPtr xsltXPathVariableLookup (void *ctxt, const xmlChar *name, const xmlChar *ns_uri); diff --git a/libxslt/xslt.c b/libxslt/xslt.c index 00114c0a..b8237ece 100644 --- a/libxslt/xslt.c +++ b/libxslt/xslt.c @@ -32,6 +32,7 @@ #include "keys.h" #include "documents.h" #include "extensions.h" +#include "preproc.h" #ifdef WITH_XSLT_DEBUG #define WITH_XSLT_DEBUG_PARSING @@ -293,6 +294,7 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet) { xsltFreeAttributeSetsHashes(sheet); xsltFreeNamespaceAliasHashes(sheet); xsltFreeStyleDocuments(sheet); + xsltFreeStylePreComps(sheet); if (sheet->doc != NULL) xmlFreeDoc(sheet->doc); if (sheet->variables != NULL) @@ -751,14 +753,16 @@ xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) { } /** - * xsltParseRemoveBlanks: + * xsltPrecomputeStylesheet: * @style: the XSLT stylesheet * * Clean-up the stylesheet content from unwanted ignorable blank nodes + * and run the preprocessing of all XSLT constructs. + * * and process xslt:text */ static void -xsltParseRemoveBlanks(xsltStylesheetPtr style) { +xsltPrecomputeStylesheet(xsltStylesheetPtr style) { xmlNodePtr cur, delete; /* @@ -775,13 +779,14 @@ xsltParseRemoveBlanks(xsltStylesheetPtr style) { if (delete != NULL) { #ifdef WITH_XSLT_DEBUG_BLANKS xsltGenericDebug(xsltGenericDebugContext, - "xsltParseRemoveBlanks: removing ignorable blank node\n"); + "xsltPrecomputeStylesheet: removing ignorable blank node\n"); #endif xmlUnlinkNode(delete); xmlFreeNode(delete); delete = NULL; } if ((cur->type == XML_ELEMENT_NODE) && (IS_XSLT_ELEM(cur))) { + xsltStylePreCompute(style, cur); if (IS_XSLT_NAME(cur, "text")) { goto skip_children; } @@ -830,7 +835,7 @@ skip_children: if (delete != NULL) { #ifdef WITH_XSLT_DEBUG_PARSING xsltGenericDebug(xsltGenericDebugContext, - "xsltParseRemoveBlanks: removing ignorable blank node\n"); + "xsltPrecomputeStylesheet: removing ignorable blank node\n"); #endif xmlUnlinkNode(delete); xmlFreeNode(delete); @@ -991,9 +996,9 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xsltTemplatePtr ret, } else if ((cur->ns != NULL) && (style->nsDefs != NULL)) { if (xsltCheckExtPrefix(style, cur->ns->prefix)) { /* - * Mark the element as being 'special' + * okay this is an extension element compile it too */ - cur->_private = (void *) xsltExtMarker; + xsltStylePreCompute(style, cur); } } @@ -1431,7 +1436,7 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) { return(NULL); } - xsltParseRemoveBlanks(ret); + xsltPrecomputeStylesheet(ret); if ((IS_XSLT_ELEM(cur)) && ((IS_XSLT_NAME(cur, "stylesheet")) || (IS_XSLT_NAME(cur, "transform")))) { diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 9b744ae4..b2839f6b 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -39,7 +39,7 @@ struct _xsltStackElem { 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 */ + xmlNodePtr tree; /* the tree if no eval string or the location */ xmlXPathObjectPtr value; /* The value if computed */ }; @@ -98,6 +98,92 @@ struct _xsltDocument { }; /* + * The in-memory structure corresponding to XSLT stylesheet constructs + * precomputed data. + */ + +typedef struct _xsltTransformContext xsltTransformContext; +typedef xsltTransformContext *xsltTransformContextPtr; + +typedef struct _xsltStylePreComp xsltStylePreComp; +typedef xsltStylePreComp *xsltStylePreCompPtr; + +typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt, + xmlNodePtr node, xmlNodePtr inst, + xsltStylePreCompPtr comp); + +typedef enum { + XSLT_FUNC_COPY=1, + XSLT_FUNC_SORT, + XSLT_FUNC_TEXT, + XSLT_FUNC_ELEMENT, + XSLT_FUNC_ATTRIBUTE, + XSLT_FUNC_COMMENT, + XSLT_FUNC_PI, + XSLT_FUNC_COPYOF, + XSLT_FUNC_VALUEOF, + XSLT_FUNC_NUMBER, + XSLT_FUNC_APPLYIMPORTS, + XSLT_FUNC_CALLTEMPLATE, + XSLT_FUNC_APPLYTEMPLATES, + XSLT_FUNC_CHOOSE, + XSLT_FUNC_IF, + XSLT_FUNC_FOREACH, + XSLT_FUNC_DOCUMENT, + XSLT_FUNC_WITHPARAM, + XSLT_FUNC_PARAM, + XSLT_FUNC_VARIABLE, + XSLT_FUNC_WHEN +} xsltStyleType; + +struct _xsltStylePreComp { + struct _xsltStylePreComp *next;/* chained list */ + xsltStyleType type; /* type of the element */ + xsltTransformFunction func; /* handling function */ + xmlNodePtr inst; /* the instruction */ + + /* + * Pre computed values + */ + + xmlChar *stype; /* sort */ + int has_stype; /* sort */ + int number; /* sort */ + xmlChar *order; /* sort */ + int has_order; /* sort */ + int descending; /* sort */ + + xmlChar *use; /* copy, element */ + int has_use; /* copy, element */ + + int noescape; /* text */ + + xmlChar *name; /* element, attribute, pi */ + int has_name; /* element, attribute, pi */ + xmlChar *ns; /* element */ + int has_ns; /* element */ + + xmlChar *mode; /* apply-templates */ + xmlChar *modeURI; /* apply-templates */ + + xmlChar *test; /* if */ + + xsltTemplatePtr templ; /* call-template */ + + xmlChar *select; /* sort, copy-of, value-of, apply-templates */ + + int ver11; /* document */ + xmlChar *filename; /* document URL */ + int has_filename; /* document */ + + xsltNumberData numdata; /* number */ + + xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ + xmlNsPtr *nsList; /* the namespaces in scope */ + int nsNr; /* the number of namespaces in scope */ +}; + +/* * 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. @@ -179,89 +265,11 @@ struct _xsltStylesheet { xmlChar *doctypeSystem; /* doctype-system string */ int indent; /* should output being indented */ xmlChar *mediaType; /* media-type string */ -}; - - -/* - * The in-memory structure corresponding to XSLT stylesheet constructs - * precomputed data. - */ - -typedef struct _xsltTransformContext xsltTransformContext; -typedef xsltTransformContext *xsltTransformContextPtr; - -typedef struct _xsltStylePreComp xsltStylePreComp; -typedef xsltStylePreComp *xsltStylePreCompPtr; - -typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt, - xmlNodePtr node, xmlNodePtr inst, - xsltStylePreCompPtr comp); - -typedef enum { - XSLT_FUNC_COPY=1, - XSLT_FUNC_SORT, - XSLT_FUNC_TEXT, - XSLT_FUNC_ELEMENT, - XSLT_FUNC_ATTRIBUTE, - XSLT_FUNC_COMMENT, - XSLT_FUNC_PI, - XSLT_FUNC_COPYOF, - XSLT_FUNC_VALUEOF, - XSLT_FUNC_NUMBER, - XSLT_FUNC_APPLYIMPORTS, - XSLT_FUNC_CALLTEMPLATE, - XSLT_FUNC_APPLYTEMPLATES, - XSLT_FUNC_CHOOSE, - XSLT_FUNC_IF, - XSLT_FUNC_FOREACH, - XSLT_FUNC_DOCUMENT -} xsltStyleType; - -struct _xsltStylePreComp { - struct _xsltStylePreComp *next;/* chained list */ - xsltStyleType type; /* type of the element */ - xsltTransformFunction func; /* handling function */ - xmlNodePtr inst; /* the instruction */ /* - * Pre computed values + * Precomputed blocks */ - - xmlChar *stype; /* sort */ - int has_stype; /* sort */ - int number; /* sort */ - xmlChar *order; /* sort */ - int has_order; /* sort */ - int descending; /* sort */ - - xmlChar *use; /* copy, element */ - int has_use; /* copy, element */ - - int noescape; /* text */ - - xmlChar *name; /* element, attribute, pi */ - int has_name; /* element, attribute, pi */ - xmlChar *ns; /* element */ - int has_ns; /* element */ - - xmlChar *mode; /* apply-templates */ - xmlChar *modeURI; /* apply-templates */ - - xmlChar *test; /* if */ - - xsltTemplatePtr templ; /* call-template */ - - xmlChar *select; /* sort, copy-of, value-of, apply-templates */ - - int ver11; /* document */ - xmlChar *filename; /* document URL */ - int has_filename; /* document */ - - xsltNumberData numdata; /* number */ - - xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ - xmlNsPtr *nsList; /* the namespaces in scope */ - int nsNr; /* the number of namespaces in scope */ + xsltStylePreCompPtr preComps; /* list of precomputed blocks */ }; /* @@ -294,11 +302,6 @@ struct _xsltTransformContext { xsltStackElemPtr *varsTab; /* the variable list stack */ /* - * Precomputed blocks - */ - xsltStylePreCompPtr preComps; /* list of precomputed blocks */ - - /* * Extensions */ xmlHashTablePtr extFunctions; /* the extension functions */ |