Home | History | Annotate | Download | only in libxslt
      1 /*
      2  * preproc.c: Preprocessing of style operations
      3  *
      4  * References:
      5  *   http://www.w3.org/TR/1999/REC-xslt-19991116
      6  *
      7  *   Michael Kay "XSLT Programmer's Reference" pp 637-643
      8  *   Writing Multiple Output Files
      9  *
     10  *   XSLT-1.1 Working Draft
     11  *   http://www.w3.org/TR/xslt11#multiple-output
     12  *
     13  * See Copyright for the status of this software.
     14  *
     15  * daniel (at) veillard.com
     16  */
     17 
     18 #define IN_LIBXSLT
     19 #include "libxslt.h"
     20 
     21 #include <string.h>
     22 
     23 #include <libxml/xmlmemory.h>
     24 #include <libxml/parser.h>
     25 #include <libxml/tree.h>
     26 #include <libxml/valid.h>
     27 #include <libxml/hash.h>
     28 #include <libxml/uri.h>
     29 #include <libxml/encoding.h>
     30 #include <libxml/xmlerror.h>
     31 #include "xslt.h"
     32 #include "xsltutils.h"
     33 #include "xsltInternals.h"
     34 #include "transform.h"
     35 #include "templates.h"
     36 #include "variables.h"
     37 #include "numbersInternals.h"
     38 #include "preproc.h"
     39 #include "extra.h"
     40 #include "imports.h"
     41 #include "extensions.h"
     42 
     43 #ifdef WITH_XSLT_DEBUG
     44 #define WITH_XSLT_DEBUG_PREPROC
     45 #endif
     46 
     47 const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
     48 
     49 /************************************************************************
     50  *									*
     51  *			Grammar checks					*
     52  *									*
     53  ************************************************************************/
     54 
     55 #ifdef XSLT_REFACTORED
     56     /*
     57     * Grammar checks are now performed in xslt.c.
     58     */
     59 #else
     60 /**
     61  * xsltCheckTopLevelElement:
     62  * @style: the XSLT stylesheet
     63  * @inst: the XSLT instruction
     64  * @err: raise an error or not
     65  *
     66  * Check that the instruction is instanciated as a top level element.
     67  *
     68  * Returns -1 in case of error, 0 if failed and 1 in case of success
     69  */
     70 static int
     71 xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) {
     72     xmlNodePtr parent;
     73     if ((style == NULL) || (inst == NULL) || (inst->ns == NULL))
     74         return(-1);
     75 
     76     parent = inst->parent;
     77     if (parent == NULL) {
     78         if (err) {
     79 	    xsltTransformError(NULL, style, inst,
     80 		    "internal problem: element has no parent\n");
     81 	    style->errors++;
     82 	}
     83 	return(0);
     84     }
     85     if ((parent->ns == NULL) || (parent->type != XML_ELEMENT_NODE) ||
     86         ((parent->ns != inst->ns) &&
     87 	 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
     88 	((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) &&
     89 	 (!xmlStrEqual(parent->name, BAD_CAST "transform")))) {
     90 	if (err) {
     91 	    xsltTransformError(NULL, style, inst,
     92 		    "element %s only allowed as child of stylesheet\n",
     93 			       inst->name);
     94 	    style->errors++;
     95 	}
     96 	return(0);
     97     }
     98     return(1);
     99 }
    100 
    101 /**
    102  * xsltCheckInstructionElement:
    103  * @style: the XSLT stylesheet
    104  * @inst: the XSLT instruction
    105  *
    106  * Check that the instruction is instanciated as an instruction element.
    107  */
    108 static void
    109 xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) {
    110     xmlNodePtr parent;
    111     int has_ext;
    112 
    113     if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
    114         (style->literal_result))
    115         return;
    116 
    117     has_ext = (style->extInfos != NULL);
    118 
    119     parent = inst->parent;
    120     if (parent == NULL) {
    121 	xsltTransformError(NULL, style, inst,
    122 		"internal problem: element has no parent\n");
    123 	style->errors++;
    124 	return;
    125     }
    126     while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
    127         if (((parent->ns == inst->ns) ||
    128 	     ((parent->ns != NULL) &&
    129 	      (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
    130 	    ((xmlStrEqual(parent->name, BAD_CAST "template")) ||
    131 	     (xmlStrEqual(parent->name, BAD_CAST "param")) ||
    132 	     (xmlStrEqual(parent->name, BAD_CAST "attribute")) ||
    133 	     (xmlStrEqual(parent->name, BAD_CAST "variable")))) {
    134 	    return;
    135 	}
    136 
    137 	/*
    138 	 * if we are within an extension element all bets are off
    139 	 * about the semantic there e.g. xsl:param within func:function
    140 	 */
    141 	if ((has_ext) && (parent->ns != NULL) &&
    142 	    (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
    143 	    return;
    144 
    145         parent = parent->parent;
    146     }
    147     xsltTransformError(NULL, style, inst,
    148 	    "element %s only allowed within a template, variable or param\n",
    149 		           inst->name);
    150     style->errors++;
    151 }
    152 
    153 /**
    154  * xsltCheckParentElement:
    155  * @style: the XSLT stylesheet
    156  * @inst: the XSLT instruction
    157  * @allow1: allowed parent1
    158  * @allow2: allowed parent2
    159  *
    160  * Check that the instruction is instanciated as the childre of one of the
    161  * possible parents.
    162  */
    163 static void
    164 xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,
    165                        const xmlChar *allow1, const xmlChar *allow2) {
    166     xmlNodePtr parent;
    167 
    168     if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
    169         (style->literal_result))
    170         return;
    171 
    172     parent = inst->parent;
    173     if (parent == NULL) {
    174 	xsltTransformError(NULL, style, inst,
    175 		"internal problem: element has no parent\n");
    176 	style->errors++;
    177 	return;
    178     }
    179     if (((parent->ns == inst->ns) ||
    180 	 ((parent->ns != NULL) &&
    181 	  (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
    182 	((xmlStrEqual(parent->name, allow1)) ||
    183 	 (xmlStrEqual(parent->name, allow2)))) {
    184 	return;
    185     }
    186 
    187     if (style->extInfos != NULL) {
    188 	while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
    189 	    /*
    190 	     * if we are within an extension element all bets are off
    191 	     * about the semantic there e.g. xsl:param within func:function
    192 	     */
    193 	    if ((parent->ns != NULL) &&
    194 		(xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
    195 		return;
    196 
    197 	    parent = parent->parent;
    198 	}
    199     }
    200     xsltTransformError(NULL, style, inst,
    201 		       "element %s is not allowed within that context\n",
    202 		       inst->name);
    203     style->errors++;
    204 }
    205 #endif
    206 
    207 /************************************************************************
    208  *									*
    209  *			handling of precomputed data			*
    210  *									*
    211  ************************************************************************/
    212 
    213 /**
    214  * xsltNewStylePreComp:
    215  * @style:  the XSLT stylesheet
    216  * @type:  the construct type
    217  *
    218  * Create a new XSLT Style precomputed block
    219  *
    220  * Returns the newly allocated specialized structure
    221  *         or NULL in case of error
    222  */
    223 static xsltStylePreCompPtr
    224 xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
    225     xsltStylePreCompPtr cur;
    226 #ifdef XSLT_REFACTORED
    227     size_t size;
    228 #endif
    229 
    230     if (style == NULL)
    231         return(NULL);
    232 
    233 #ifdef XSLT_REFACTORED
    234     /*
    235     * URGENT TODO: Use specialized factory functions in order
    236     *   to avoid this ugliness.
    237     */
    238     switch (type) {
    239         case XSLT_FUNC_COPY:
    240             size = sizeof(xsltStyleItemCopy); break;
    241         case XSLT_FUNC_SORT:
    242             size = sizeof(xsltStyleItemSort); break;
    243         case XSLT_FUNC_TEXT:
    244             size = sizeof(xsltStyleItemText); break;
    245         case XSLT_FUNC_ELEMENT:
    246             size = sizeof(xsltStyleItemElement); break;
    247         case XSLT_FUNC_ATTRIBUTE:
    248             size = sizeof(xsltStyleItemAttribute); break;
    249         case XSLT_FUNC_COMMENT:
    250             size = sizeof(xsltStyleItemComment); break;
    251         case XSLT_FUNC_PI:
    252             size = sizeof(xsltStyleItemPI); break;
    253         case XSLT_FUNC_COPYOF:
    254             size = sizeof(xsltStyleItemCopyOf); break;
    255         case XSLT_FUNC_VALUEOF:
    256             size = sizeof(xsltStyleItemValueOf); break;;
    257         case XSLT_FUNC_NUMBER:
    258             size = sizeof(xsltStyleItemNumber); break;
    259         case XSLT_FUNC_APPLYIMPORTS:
    260             size = sizeof(xsltStyleItemApplyImports); break;
    261         case XSLT_FUNC_CALLTEMPLATE:
    262             size = sizeof(xsltStyleItemCallTemplate); break;
    263         case XSLT_FUNC_APPLYTEMPLATES:
    264             size = sizeof(xsltStyleItemApplyTemplates); break;
    265         case XSLT_FUNC_CHOOSE:
    266             size = sizeof(xsltStyleItemChoose); break;
    267         case XSLT_FUNC_IF:
    268             size = sizeof(xsltStyleItemIf); break;
    269         case XSLT_FUNC_FOREACH:
    270             size = sizeof(xsltStyleItemForEach); break;
    271         case XSLT_FUNC_DOCUMENT:
    272             size = sizeof(xsltStyleItemDocument); break;
    273 	case XSLT_FUNC_WITHPARAM:
    274 	    size = sizeof(xsltStyleItemWithParam); break;
    275 	case XSLT_FUNC_PARAM:
    276 	    size = sizeof(xsltStyleItemParam); break;
    277 	case XSLT_FUNC_VARIABLE:
    278 	    size = sizeof(xsltStyleItemVariable); break;
    279 	case XSLT_FUNC_WHEN:
    280 	    size = sizeof(xsltStyleItemWhen); break;
    281 	case XSLT_FUNC_OTHERWISE:
    282 	    size = sizeof(xsltStyleItemOtherwise); break;
    283 	default:
    284 	    xsltTransformError(NULL, style, NULL,
    285 		    "xsltNewStylePreComp : invalid type %d\n", type);
    286 	    style->errors++;
    287 	    return(NULL);
    288     }
    289     /*
    290     * Create the structure.
    291     */
    292     cur = (xsltStylePreCompPtr) xmlMalloc(size);
    293     if (cur == NULL) {
    294 	xsltTransformError(NULL, style, NULL,
    295 		"xsltNewStylePreComp : malloc failed\n");
    296 	style->errors++;
    297 	return(NULL);
    298     }
    299     memset(cur, 0, size);
    300 
    301 #else /* XSLT_REFACTORED */
    302     /*
    303     * Old behaviour.
    304     */
    305     cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));
    306     if (cur == NULL) {
    307 	xsltTransformError(NULL, style, NULL,
    308 		"xsltNewStylePreComp : malloc failed\n");
    309 	style->errors++;
    310 	return(NULL);
    311     }
    312     memset(cur, 0, sizeof(xsltStylePreComp));
    313 #endif /* XSLT_REFACTORED */
    314 
    315     /*
    316     * URGENT TODO: Better to move this to spezialized factory functions.
    317     */
    318     cur->type = type;
    319     switch (cur->type) {
    320         case XSLT_FUNC_COPY:
    321             cur->func = (xsltTransformFunction) xsltCopy;break;
    322         case XSLT_FUNC_SORT:
    323             cur->func = (xsltTransformFunction) xsltSort;break;
    324         case XSLT_FUNC_TEXT:
    325             cur->func = (xsltTransformFunction) xsltText;break;
    326         case XSLT_FUNC_ELEMENT:
    327             cur->func = (xsltTransformFunction) xsltElement;break;
    328         case XSLT_FUNC_ATTRIBUTE:
    329             cur->func = (xsltTransformFunction) xsltAttribute;break;
    330         case XSLT_FUNC_COMMENT:
    331             cur->func = (xsltTransformFunction) xsltComment;break;
    332         case XSLT_FUNC_PI:
    333             cur->func = (xsltTransformFunction) xsltProcessingInstruction;
    334 	    break;
    335         case XSLT_FUNC_COPYOF:
    336             cur->func = (xsltTransformFunction) xsltCopyOf;break;
    337         case XSLT_FUNC_VALUEOF:
    338             cur->func = (xsltTransformFunction) xsltValueOf;break;
    339         case XSLT_FUNC_NUMBER:
    340             cur->func = (xsltTransformFunction) xsltNumber;break;
    341         case XSLT_FUNC_APPLYIMPORTS:
    342             cur->func = (xsltTransformFunction) xsltApplyImports;break;
    343         case XSLT_FUNC_CALLTEMPLATE:
    344             cur->func = (xsltTransformFunction) xsltCallTemplate;break;
    345         case XSLT_FUNC_APPLYTEMPLATES:
    346             cur->func = (xsltTransformFunction) xsltApplyTemplates;break;
    347         case XSLT_FUNC_CHOOSE:
    348             cur->func = (xsltTransformFunction) xsltChoose;break;
    349         case XSLT_FUNC_IF:
    350             cur->func = (xsltTransformFunction) xsltIf;break;
    351         case XSLT_FUNC_FOREACH:
    352             cur->func = (xsltTransformFunction) xsltForEach;break;
    353         case XSLT_FUNC_DOCUMENT:
    354             cur->func = (xsltTransformFunction) xsltDocumentElem;break;
    355 	case XSLT_FUNC_WITHPARAM:
    356 	case XSLT_FUNC_PARAM:
    357 	case XSLT_FUNC_VARIABLE:
    358 	case XSLT_FUNC_WHEN:
    359 	    break;
    360 	default:
    361 	if (cur->func == NULL) {
    362 	    xsltTransformError(NULL, style, NULL,
    363 		    "xsltNewStylePreComp : no function for type %d\n", type);
    364 	    style->errors++;
    365 	}
    366     }
    367     cur->next = style->preComps;
    368     style->preComps = (xsltElemPreCompPtr) cur;
    369 
    370     return(cur);
    371 }
    372 
    373 /**
    374  * xsltFreeStylePreComp:
    375  * @comp:  an XSLT Style precomputed block
    376  *
    377  * Free up the memory allocated by @comp
    378  */
    379 static void
    380 xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
    381     if (comp == NULL)
    382 	return;
    383 #ifdef XSLT_REFACTORED
    384     /*
    385     * URGENT TODO: Implement destructors.
    386     */
    387     switch (comp->type) {
    388 	case XSLT_FUNC_LITERAL_RESULT_ELEMENT:
    389 	    break;
    390 	case XSLT_FUNC_COPY:
    391             break;
    392         case XSLT_FUNC_SORT: {
    393 		xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
    394 		if (item->locale != (xsltLocale)0)
    395 		    xsltFreeLocale(item->locale);
    396 		if (item->comp != NULL)
    397 		    xmlXPathFreeCompExpr(item->comp);
    398 	    }
    399             break;
    400         case XSLT_FUNC_TEXT:
    401             break;
    402         case XSLT_FUNC_ELEMENT:
    403             break;
    404         case XSLT_FUNC_ATTRIBUTE:
    405             break;
    406         case XSLT_FUNC_COMMENT:
    407             break;
    408         case XSLT_FUNC_PI:
    409 	    break;
    410         case XSLT_FUNC_COPYOF: {
    411 		xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp;
    412 		if (item->comp != NULL)
    413 		    xmlXPathFreeCompExpr(item->comp);
    414 	    }
    415             break;
    416         case XSLT_FUNC_VALUEOF: {
    417 		xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp;
    418 		if (item->comp != NULL)
    419 		    xmlXPathFreeCompExpr(item->comp);
    420 	    }
    421             break;
    422         case XSLT_FUNC_NUMBER:
    423             break;
    424         case XSLT_FUNC_APPLYIMPORTS:
    425             break;
    426         case XSLT_FUNC_CALLTEMPLATE:
    427             break;
    428         case XSLT_FUNC_APPLYTEMPLATES: {
    429 		xsltStyleItemApplyTemplatesPtr item =
    430 		    (xsltStyleItemApplyTemplatesPtr) comp;
    431 		if (item->comp != NULL)
    432 		    xmlXPathFreeCompExpr(item->comp);
    433 	    }
    434             break;
    435         case XSLT_FUNC_CHOOSE:
    436             break;
    437         case XSLT_FUNC_IF: {
    438 		xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp;
    439 		if (item->comp != NULL)
    440 		    xmlXPathFreeCompExpr(item->comp);
    441 	    }
    442             break;
    443         case XSLT_FUNC_FOREACH: {
    444 		xsltStyleItemForEachPtr item =
    445 		    (xsltStyleItemForEachPtr) comp;
    446 		if (item->comp != NULL)
    447 		    xmlXPathFreeCompExpr(item->comp);
    448 	    }
    449             break;
    450         case XSLT_FUNC_DOCUMENT:
    451             break;
    452 	case XSLT_FUNC_WITHPARAM: {
    453 		xsltStyleItemWithParamPtr item =
    454 		    (xsltStyleItemWithParamPtr) comp;
    455 		if (item->comp != NULL)
    456 		    xmlXPathFreeCompExpr(item->comp);
    457 	    }
    458 	    break;
    459 	case XSLT_FUNC_PARAM: {
    460 		xsltStyleItemParamPtr item =
    461 		    (xsltStyleItemParamPtr) comp;
    462 		if (item->comp != NULL)
    463 		    xmlXPathFreeCompExpr(item->comp);
    464 	    }
    465 	    break;
    466 	case XSLT_FUNC_VARIABLE: {
    467 		xsltStyleItemVariablePtr item =
    468 		    (xsltStyleItemVariablePtr) comp;
    469 		if (item->comp != NULL)
    470 		    xmlXPathFreeCompExpr(item->comp);
    471 	    }
    472 	    break;
    473 	case XSLT_FUNC_WHEN: {
    474 		xsltStyleItemWhenPtr item =
    475 		    (xsltStyleItemWhenPtr) comp;
    476 		if (item->comp != NULL)
    477 		    xmlXPathFreeCompExpr(item->comp);
    478 	    }
    479 	    break;
    480 	case XSLT_FUNC_OTHERWISE:
    481 	case XSLT_FUNC_FALLBACK:
    482 	case XSLT_FUNC_MESSAGE:
    483 	case XSLT_FUNC_INCLUDE:
    484 	case XSLT_FUNC_ATTRSET:
    485 
    486 	    break;
    487 	default:
    488 	    /* TODO: Raise error. */
    489 	    break;
    490     }
    491 #else
    492     if (comp->locale != (xsltLocale)0)
    493 	xsltFreeLocale(comp->locale);
    494     if (comp->comp != NULL)
    495 	xmlXPathFreeCompExpr(comp->comp);
    496     if (comp->nsList != NULL)
    497 	xmlFree(comp->nsList);
    498 #endif
    499 
    500     xmlFree(comp);
    501 }
    502 
    503 
    504 /************************************************************************
    505  *									*
    506  *		    XSLT-1.1 extensions					*
    507  *									*
    508  ************************************************************************/
    509 
    510 /**
    511  * xsltDocumentComp:
    512  * @style:  the XSLT stylesheet
    513  * @inst:  the instruction in the stylesheet
    514  * @function:  unused
    515  *
    516  * Pre process an XSLT-1.1 document element
    517  *
    518  * Returns a precompiled data structure for the element
    519  */
    520 xsltElemPreCompPtr
    521 xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
    522 		 xsltTransformFunction function ATTRIBUTE_UNUSED) {
    523 #ifdef XSLT_REFACTORED
    524     xsltStyleItemDocumentPtr comp;
    525 #else
    526     xsltStylePreCompPtr comp;
    527 #endif
    528     const xmlChar *filename = NULL;
    529 
    530     /*
    531     * As of 2006-03-30, this function is currently defined in Libxslt
    532     * to be used for:
    533     * (in libxslt/extra.c)
    534     * "output" in XSLT_SAXON_NAMESPACE
    535     * "write" XSLT_XALAN_NAMESPACE
    536     * "document" XSLT_XT_NAMESPACE
    537     * "document" XSLT_NAMESPACE (from the abandoned old working
    538     *                            draft of XSLT 1.1)
    539     * (in libexslt/common.c)
    540     * "document" in EXSLT_COMMON_NAMESPACE
    541     */
    542 #ifdef XSLT_REFACTORED
    543     comp = (xsltStyleItemDocumentPtr)
    544 	xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
    545 #else
    546     comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
    547 #endif
    548 
    549     if (comp == NULL)
    550 	return (NULL);
    551     comp->inst = inst;
    552     comp->ver11 = 0;
    553 
    554     if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
    555 #ifdef WITH_XSLT_DEBUG_EXTRA
    556 	xsltGenericDebug(xsltGenericDebugContext,
    557 	    "Found saxon:output extension\n");
    558 #endif
    559 	/*
    560 	* The element "output" is in the namespace XSLT_SAXON_NAMESPACE
    561 	*   (http://icl.com/saxon)
    562 	* The @file is in no namespace; it is an AVT.
    563 	*   (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)
    564 	*
    565 	* TODO: Do we need not to check the namespace here?
    566 	*/
    567 	filename = xsltEvalStaticAttrValueTemplate(style, inst,
    568 			 (const xmlChar *)"file",
    569 			 NULL, &comp->has_filename);
    570     } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
    571 #ifdef WITH_XSLT_DEBUG_EXTRA
    572 	xsltGenericDebug(xsltGenericDebugContext,
    573 	    "Found xalan:write extension\n");
    574 #endif
    575 	/* the filename need to be interpreted */
    576 	/*
    577 	* TODO: Is "filename need to be interpreted" meant to be a todo?
    578 	*   Where will be the filename of xalan:write be processed?
    579 	*
    580 	* TODO: Do we need not to check the namespace here?
    581 	*   The extension ns is "http://xml.apache.org/xalan/redirect".
    582 	*   See http://xml.apache.org/xalan-j/extensionslib.html.
    583 	*/
    584     } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
    585 	if (inst->ns != NULL) {
    586 	    if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) {
    587 		/*
    588 		* Mark the instruction as being of
    589 		* XSLT version 1.1 (abandoned).
    590 		*/
    591 		comp->ver11 = 1;
    592 #ifdef WITH_XSLT_DEBUG_EXTRA
    593 		xsltGenericDebug(xsltGenericDebugContext,
    594 		    "Found xslt11:document construct\n");
    595 #endif
    596 	    } else {
    597 		if (xmlStrEqual(inst->ns->href,
    598 		    (const xmlChar *)"http://exslt.org/common")) {
    599 		    /* EXSLT. */
    600 #ifdef WITH_XSLT_DEBUG_EXTRA
    601 		    xsltGenericDebug(xsltGenericDebugContext,
    602 			"Found exslt:document extension\n");
    603 #endif
    604 		} else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) {
    605 		    /* James Clark's XT. */
    606 #ifdef WITH_XSLT_DEBUG_EXTRA
    607 		    xsltGenericDebug(xsltGenericDebugContext,
    608 			"Found xt:document extension\n");
    609 #endif
    610 		}
    611 	    }
    612 	}
    613 	/*
    614 	* The element "document" is used in conjunction with the
    615 	* following namespaces:
    616 	*
    617 	* 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)
    618 	*    <!ELEMENT xsl:document %template;>
    619 	*    <!ATTLIST xsl:document
    620 	*       href %avt; #REQUIRED
    621 	*    @href is an AVT
    622 	*    IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,
    623 	*    it was removed and isn't available in XSLT 1.1 anymore.
    624 	*    In XSLT 2.0 it was renamed to xsl:result-document.
    625 	*
    626 	*   All other attributes are identical to the attributes
    627 	*   on xsl:output
    628 	*
    629 	* 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)
    630 	*    <exsl:document
    631 	*       href = { uri-reference }
    632 	*    TODO: is @href is an AVT?
    633 	*
    634 	* 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)
    635 	*     Example: <xt:document method="xml" href="myFile.xml">
    636 	*    TODO: is @href is an AVT?
    637 	*
    638 	* In all cases @href is in no namespace.
    639 	*/
    640 	filename = xsltEvalStaticAttrValueTemplate(style, inst,
    641 	    (const xmlChar *)"href", NULL, &comp->has_filename);
    642     }
    643     if (!comp->has_filename) {
    644 	goto error;
    645     }
    646     comp->filename = filename;
    647 
    648 error:
    649     return ((xsltElemPreCompPtr) comp);
    650 }
    651 
    652 /************************************************************************
    653  *									*
    654  *		Most of the XSLT-1.0 transformations			*
    655  *									*
    656  ************************************************************************/
    657 
    658 /**
    659  * xsltSortComp:
    660  * @style:  the XSLT stylesheet
    661  * @inst:  the xslt sort node
    662  *
    663  * Process the xslt sort node on the source node
    664  */
    665 static void
    666 xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
    667 #ifdef XSLT_REFACTORED
    668     xsltStyleItemSortPtr comp;
    669 #else
    670     xsltStylePreCompPtr comp;
    671 #endif
    672     if ((style == NULL) || (inst == NULL))
    673 	return;
    674 
    675 #ifdef XSLT_REFACTORED
    676     comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT);
    677 #else
    678     comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
    679 #endif
    680 
    681     if (comp == NULL)
    682 	return;
    683     inst->psvi = comp;
    684     comp->inst = inst;
    685 
    686     comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
    687 			 (const xmlChar *)"data-type",
    688 			 NULL, &comp->has_stype);
    689     if (comp->stype != NULL) {
    690 	if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
    691 	    comp->number = 0;
    692 	else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
    693 	    comp->number = 1;
    694 	else {
    695 	    xsltTransformError(NULL, style, inst,
    696 		 "xsltSortComp: no support for data-type = %s\n", comp->stype);
    697 	    comp->number = 0; /* use default */
    698 	    if (style != NULL) style->warnings++;
    699 	}
    700     }
    701     comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
    702 			      (const xmlChar *)"order",
    703 			      NULL, &comp->has_order);
    704     if (comp->order != NULL) {
    705 	if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
    706 	    comp->descending = 0;
    707 	else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
    708 	    comp->descending = 1;
    709 	else {
    710 	    xsltTransformError(NULL, style, inst,
    711 		 "xsltSortComp: invalid value %s for order\n", comp->order);
    712 	    comp->descending = 0; /* use default */
    713 	    if (style != NULL) style->warnings++;
    714 	}
    715     }
    716     comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst,
    717 			      (const xmlChar *)"case-order",
    718 			      NULL, &comp->has_use);
    719     if (comp->case_order != NULL) {
    720 	if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first"))
    721 	    comp->lower_first = 0;
    722 	else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first"))
    723 	    comp->lower_first = 1;
    724 	else {
    725 	    xsltTransformError(NULL, style, inst,
    726 		 "xsltSortComp: invalid value %s for order\n", comp->order);
    727 	    comp->lower_first = 0; /* use default */
    728 	    if (style != NULL) style->warnings++;
    729 	}
    730     }
    731 
    732     comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
    733 				 (const xmlChar *)"lang",
    734 				 NULL, &comp->has_lang);
    735     if (comp->lang != NULL) {
    736 	comp->locale = xsltNewLocale(comp->lang);
    737     }
    738     else {
    739         comp->locale = (xsltLocale)0;
    740     }
    741 
    742     comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
    743     if (comp->select == NULL) {
    744 	/*
    745 	 * The default value of the select attribute is ., which will
    746 	 * cause the string-value of the current node to be used as
    747 	 * the sort key.
    748 	 */
    749 	comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);
    750     }
    751     comp->comp = xsltXPathCompile(style, comp->select);
    752     if (comp->comp == NULL) {
    753 	xsltTransformError(NULL, style, inst,
    754 	     "xsltSortComp: could not compile select expression '%s'\n",
    755 	                 comp->select);
    756 	if (style != NULL) style->errors++;
    757     }
    758     if (inst->children != NULL) {
    759 	xsltTransformError(NULL, style, inst,
    760 	"xsl:sort : is not empty\n");
    761 	if (style != NULL) style->errors++;
    762     }
    763 }
    764 
    765 /**
    766  * xsltCopyComp:
    767  * @style:  the XSLT stylesheet
    768  * @inst:  the xslt copy node
    769  *
    770  * Process the xslt copy node on the source node
    771  */
    772 static void
    773 xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
    774 #ifdef XSLT_REFACTORED
    775     xsltStyleItemCopyPtr comp;
    776 #else
    777     xsltStylePreCompPtr comp;
    778 #endif
    779 
    780     if ((style == NULL) || (inst == NULL))
    781 	return;
    782 #ifdef XSLT_REFACTORED
    783     comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY);
    784 #else
    785     comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
    786 #endif
    787 
    788     if (comp == NULL)
    789 	return;
    790     inst->psvi = comp;
    791     comp->inst = inst;
    792 
    793 
    794     comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",
    795 				    XSLT_NAMESPACE);
    796     if (comp->use == NULL)
    797 	comp->has_use = 0;
    798     else
    799 	comp->has_use = 1;
    800 }
    801 
    802 #ifdef XSLT_REFACTORED
    803     /* Enable if ever needed for xsl:text. */
    804 #else
    805 /**
    806  * xsltTextComp:
    807  * @style: an XSLT compiled stylesheet
    808  * @inst:  the xslt text node
    809  *
    810  * TODO: This function is obsolete, since xsl:text won't
    811  *  be compiled, but removed from the tree.
    812  *
    813  * Process the xslt text node on the source node
    814  */
    815 static void
    816 xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
    817 #ifdef XSLT_REFACTORED
    818     xsltStyleItemTextPtr comp;
    819 #else
    820     xsltStylePreCompPtr comp;
    821 #endif
    822     const xmlChar *prop;
    823 
    824     if ((style == NULL) || (inst == NULL))
    825 	return;
    826 
    827 #ifdef XSLT_REFACTORED
    828     comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
    829 #else
    830     comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
    831 #endif
    832     if (comp == NULL)
    833 	return;
    834     inst->psvi = comp;
    835     comp->inst = inst;
    836     comp->noescape = 0;
    837 
    838     prop = xsltGetCNsProp(style, inst,
    839 	    (const xmlChar *)"disable-output-escaping",
    840 			XSLT_NAMESPACE);
    841     if (prop != NULL) {
    842 	if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
    843 	    comp->noescape = 1;
    844 	} else if (!xmlStrEqual(prop,
    845 	    (const xmlChar *)"no")){
    846 	    xsltTransformError(NULL, style, inst,
    847 		"xsl:text: disable-output-escaping allows only yes or no\n");
    848 	    if (style != NULL) style->warnings++;
    849 	}
    850     }
    851 }
    852 #endif /* else of XSLT_REFACTORED */
    853 
    854 /**
    855  * xsltElementComp:
    856  * @style: an XSLT compiled stylesheet
    857  * @inst:  the xslt element node
    858  *
    859  * Process the xslt element node on the source node
    860  */
    861 static void
    862 xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
    863 #ifdef XSLT_REFACTORED
    864     xsltStyleItemElementPtr comp;
    865 #else
    866     xsltStylePreCompPtr comp;
    867 #endif
    868 
    869     /*
    870     * <xsl:element
    871     *   name = { qname }
    872     *   namespace = { uri-reference }
    873     *   use-attribute-sets = qnames>
    874     *   <!-- Content: template -->
    875     * </xsl:element>
    876     */
    877     if ((style == NULL) || (inst == NULL))
    878 	return;
    879 
    880 #ifdef XSLT_REFACTORED
    881     comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
    882 #else
    883     comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
    884 #endif
    885 
    886     if (comp == NULL)
    887 	return;
    888     inst->psvi = comp;
    889     comp->inst = inst;
    890 
    891     /*
    892     * Attribute "name".
    893     */
    894     /*
    895     * TODO: Precompile the AVT. See bug #344894.
    896     */
    897     comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
    898 	(const xmlChar *)"name", NULL, &comp->has_name);
    899     if (! comp->has_name) {
    900 	xsltTransformError(NULL, style, inst,
    901 	    "xsl:element: The attribute 'name' is missing.\n");
    902 	style->errors++;
    903 	goto error;
    904     }
    905     /*
    906     * Attribute "namespace".
    907     */
    908     /*
    909     * TODO: Precompile the AVT. See bug #344894.
    910     */
    911     comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
    912 	(const xmlChar *)"namespace", NULL, &comp->has_ns);
    913 
    914     if (comp->name != NULL) {
    915 	if (xmlValidateQName(comp->name, 0)) {
    916 	    xsltTransformError(NULL, style, inst,
    917 		"xsl:element: The value '%s' of the attribute 'name' is "
    918 		"not a valid QName.\n", comp->name);
    919 	    style->errors++;
    920 	} else {
    921 	    const xmlChar *prefix = NULL, *name;
    922 
    923 	    name = xsltSplitQName(style->dict, comp->name, &prefix);
    924 	    if (comp->has_ns == 0) {
    925 		xmlNsPtr ns;
    926 
    927 		/*
    928 		* SPEC XSLT 1.0:
    929 		*  "If the namespace attribute is not present, then the QName is
    930 		*  expanded into an expanded-name using the namespace declarations
    931 		*  in effect for the xsl:element element, including any default
    932 		*  namespace declaration.
    933 		*/
    934 		ns = xmlSearchNs(inst->doc, inst, prefix);
    935 		if (ns != NULL) {
    936 		    comp->ns = xmlDictLookup(style->dict, ns->href, -1);
    937 		    comp->has_ns = 1;
    938 #ifdef XSLT_REFACTORED
    939 		    comp->nsPrefix = prefix;
    940 		    comp->name = name;
    941 #endif
    942 		} else if (prefix != NULL) {
    943 		    xsltTransformError(NULL, style, inst,
    944 			"xsl:element: The prefixed QName '%s' "
    945 			"has no namespace binding in scope in the "
    946 			"stylesheet; this is an error, since the namespace was "
    947 			"not specified by the instruction itself.\n", comp->name);
    948 		    style->errors++;
    949 		}
    950 	    }
    951 	    if ((prefix != NULL) &&
    952 		(!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
    953 	    {
    954 		/*
    955 		* Mark is to be skipped.
    956 		*/
    957 		comp->has_name = 0;
    958 	    }
    959 	}
    960     }
    961     /*
    962     * Attribute "use-attribute-sets",
    963     */
    964     comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
    965 		       (const xmlChar *)"use-attribute-sets",
    966 		       NULL, &comp->has_use);
    967 
    968 error:
    969     return;
    970 }
    971 
    972 /**
    973  * xsltAttributeComp:
    974  * @style: an XSLT compiled stylesheet
    975  * @inst:  the xslt attribute node
    976  *
    977  * Process the xslt attribute node on the source node
    978  */
    979 static void
    980 xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
    981 #ifdef XSLT_REFACTORED
    982     xsltStyleItemAttributePtr comp;
    983 #else
    984     xsltStylePreCompPtr comp;
    985 #endif
    986 
    987     /*
    988     * <xsl:attribute
    989     *   name = { qname }
    990     *   namespace = { uri-reference }>
    991     *   <!-- Content: template -->
    992     * </xsl:attribute>
    993     */
    994     if ((style == NULL) || (inst == NULL))
    995 	return;
    996 
    997 #ifdef XSLT_REFACTORED
    998     comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,
    999 	XSLT_FUNC_ATTRIBUTE);
   1000 #else
   1001     comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
   1002 #endif
   1003 
   1004     if (comp == NULL)
   1005 	return;
   1006     inst->psvi = comp;
   1007     comp->inst = inst;
   1008 
   1009     /*
   1010     * Attribute "name".
   1011     */
   1012     /*
   1013     * TODO: Precompile the AVT. See bug #344894.
   1014     */
   1015     comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
   1016 				 (const xmlChar *)"name",
   1017 				 NULL, &comp->has_name);
   1018     if (! comp->has_name) {
   1019 	xsltTransformError(NULL, style, inst,
   1020 	    "XSLT-attribute: The attribute 'name' is missing.\n");
   1021 	style->errors++;
   1022 	return;
   1023     }
   1024     /*
   1025     * Attribute "namespace".
   1026     */
   1027     /*
   1028     * TODO: Precompile the AVT. See bug #344894.
   1029     */
   1030     comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
   1031 	(const xmlChar *)"namespace",
   1032 	NULL, &comp->has_ns);
   1033 
   1034     if (comp->name != NULL) {
   1035 	if (xmlValidateQName(comp->name, 0)) {
   1036 	    xsltTransformError(NULL, style, inst,
   1037 		"xsl:attribute: The value '%s' of the attribute 'name' is "
   1038 		"not a valid QName.\n", comp->name);
   1039 	    style->errors++;
   1040 	} else {
   1041 	    const xmlChar *prefix = NULL, *name;
   1042 
   1043 	    name = xsltSplitQName(style->dict, comp->name, &prefix);
   1044 	    if (prefix != NULL) {
   1045 		if (comp->has_ns == 0) {
   1046 		    xmlNsPtr ns;
   1047 
   1048 		    /*
   1049 		    * SPEC XSLT 1.0:
   1050 		    *  "If the namespace attribute is not present, then the
   1051 		    *  QName is expanded into an expanded-name using the
   1052 		    *  namespace declarations in effect for the xsl:element
   1053 		    *  element, including any default namespace declaration.
   1054 		    */
   1055 		    ns = xmlSearchNs(inst->doc, inst, prefix);
   1056 		    if (ns != NULL) {
   1057 			comp->ns = xmlDictLookup(style->dict, ns->href, -1);
   1058 			comp->has_ns = 1;
   1059 #ifdef XSLT_REFACTORED
   1060 			comp->nsPrefix = prefix;
   1061 			comp->name = name;
   1062 #endif
   1063 		    } else {
   1064 			xsltTransformError(NULL, style, inst,
   1065 			    "xsl:attribute: The prefixed QName '%s' "
   1066 			    "has no namespace binding in scope in the "
   1067 			    "stylesheet; this is an error, since the "
   1068 			    "namespace was not specified by the instruction "
   1069 			    "itself.\n", comp->name);
   1070 			style->errors++;
   1071 		    }
   1072 		}
   1073 		if (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)) {
   1074 		    /*
   1075 		    * SPEC XSLT 1.0:
   1076 		    *  "It is an error if the string that results from
   1077 		    *  instantiating the attribute value template is not a
   1078 		    *  QName or is the string xmlns. An XSLT processor may
   1079 		    *  signal the error; if it does not signal the error,
   1080 		    *  it must recover by not adding the attribute to the
   1081 		    *  result tree."
   1082 		    *
   1083 		    * Reject a prefix of "xmlns". Mark to be skipped.
   1084 		    */
   1085 		    comp->has_name = 0;
   1086 
   1087 #ifdef WITH_XSLT_DEBUG_PARSING
   1088 		    xsltGenericDebug(xsltGenericDebugContext,
   1089 			"xsltAttribute: xmlns prefix forbidden\n");
   1090 #endif
   1091 		    return;
   1092 		}
   1093 
   1094 	    }
   1095 	}
   1096     }
   1097 }
   1098 
   1099 /**
   1100  * xsltCommentComp:
   1101  * @style: an XSLT compiled stylesheet
   1102  * @inst:  the xslt comment node
   1103  *
   1104  * Process the xslt comment node on the source node
   1105  */
   1106 static void
   1107 xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1108 #ifdef XSLT_REFACTORED
   1109     xsltStyleItemCommentPtr comp;
   1110 #else
   1111     xsltStylePreCompPtr comp;
   1112 #endif
   1113 
   1114     if ((style == NULL) || (inst == NULL))
   1115 	return;
   1116 
   1117 #ifdef XSLT_REFACTORED
   1118     comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
   1119 #else
   1120     comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
   1121 #endif
   1122 
   1123     if (comp == NULL)
   1124 	return;
   1125     inst->psvi = comp;
   1126     comp->inst = inst;
   1127 }
   1128 
   1129 /**
   1130  * xsltProcessingInstructionComp:
   1131  * @style: an XSLT compiled stylesheet
   1132  * @inst:  the xslt processing-instruction node
   1133  *
   1134  * Process the xslt processing-instruction node on the source node
   1135  */
   1136 static void
   1137 xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1138 #ifdef XSLT_REFACTORED
   1139     xsltStyleItemPIPtr comp;
   1140 #else
   1141     xsltStylePreCompPtr comp;
   1142 #endif
   1143 
   1144     if ((style == NULL) || (inst == NULL))
   1145 	return;
   1146 
   1147 #ifdef XSLT_REFACTORED
   1148     comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);
   1149 #else
   1150     comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
   1151 #endif
   1152 
   1153     if (comp == NULL)
   1154 	return;
   1155     inst->psvi = comp;
   1156     comp->inst = inst;
   1157 
   1158     comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
   1159 				 (const xmlChar *)"name",
   1160 				 XSLT_NAMESPACE, &comp->has_name);
   1161 }
   1162 
   1163 /**
   1164  * xsltCopyOfComp:
   1165  * @style: an XSLT compiled stylesheet
   1166  * @inst:  the xslt copy-of node
   1167  *
   1168  * Process the xslt copy-of node on the source node
   1169  */
   1170 static void
   1171 xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1172 #ifdef XSLT_REFACTORED
   1173     xsltStyleItemCopyOfPtr comp;
   1174 #else
   1175     xsltStylePreCompPtr comp;
   1176 #endif
   1177 
   1178     if ((style == NULL) || (inst == NULL))
   1179 	return;
   1180 
   1181 #ifdef XSLT_REFACTORED
   1182     comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
   1183 #else
   1184     comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
   1185 #endif
   1186 
   1187     if (comp == NULL)
   1188 	return;
   1189     inst->psvi = comp;
   1190     comp->inst = inst;
   1191 
   1192     comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
   1193 	                        XSLT_NAMESPACE);
   1194     if (comp->select == NULL) {
   1195 	xsltTransformError(NULL, style, inst,
   1196 	     "xsl:copy-of : select is missing\n");
   1197 	if (style != NULL) style->errors++;
   1198 	return;
   1199     }
   1200     comp->comp = xsltXPathCompile(style, comp->select);
   1201     if (comp->comp == NULL) {
   1202 	xsltTransformError(NULL, style, inst,
   1203 	     "xsl:copy-of : could not compile select expression '%s'\n",
   1204 	                 comp->select);
   1205 	if (style != NULL) style->errors++;
   1206     }
   1207 }
   1208 
   1209 /**
   1210  * xsltValueOfComp:
   1211  * @style: an XSLT compiled stylesheet
   1212  * @inst:  the xslt value-of node
   1213  *
   1214  * Process the xslt value-of node on the source node
   1215  */
   1216 static void
   1217 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1218 #ifdef XSLT_REFACTORED
   1219     xsltStyleItemValueOfPtr comp;
   1220 #else
   1221     xsltStylePreCompPtr comp;
   1222 #endif
   1223     const xmlChar *prop;
   1224 
   1225     if ((style == NULL) || (inst == NULL))
   1226 	return;
   1227 
   1228 #ifdef XSLT_REFACTORED
   1229     comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
   1230 #else
   1231     comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
   1232 #endif
   1233 
   1234     if (comp == NULL)
   1235 	return;
   1236     inst->psvi = comp;
   1237     comp->inst = inst;
   1238 
   1239     prop = xsltGetCNsProp(style, inst,
   1240 	    (const xmlChar *)"disable-output-escaping",
   1241 			XSLT_NAMESPACE);
   1242     if (prop != NULL) {
   1243 	if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
   1244 	    comp->noescape = 1;
   1245 	} else if (!xmlStrEqual(prop,
   1246 				(const xmlChar *)"no")){
   1247 	    xsltTransformError(NULL, style, inst,
   1248 "xsl:value-of : disable-output-escaping allows only yes or no\n");
   1249 	    if (style != NULL) style->warnings++;
   1250 	}
   1251     }
   1252     comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
   1253 	                        XSLT_NAMESPACE);
   1254     if (comp->select == NULL) {
   1255 	xsltTransformError(NULL, style, inst,
   1256 	     "xsl:value-of : select is missing\n");
   1257 	if (style != NULL) style->errors++;
   1258 	return;
   1259     }
   1260     comp->comp = xsltXPathCompile(style, comp->select);
   1261     if (comp->comp == NULL) {
   1262 	xsltTransformError(NULL, style, inst,
   1263 	     "xsl:value-of : could not compile select expression '%s'\n",
   1264 	                 comp->select);
   1265 	if (style != NULL) style->errors++;
   1266     }
   1267 }
   1268 
   1269 static void
   1270 xsltGetQNameProperty(xsltStylesheetPtr style, xmlNodePtr inst,
   1271 		     const xmlChar *propName,
   1272 		     int mandatory,
   1273 		     int *hasProp, const xmlChar **nsName,
   1274 		     const xmlChar** localName)
   1275 {
   1276     const xmlChar *prop;
   1277 
   1278     if (nsName)
   1279 	*nsName = NULL;
   1280     if (localName)
   1281 	*localName = NULL;
   1282     if (hasProp)
   1283 	*hasProp = 0;
   1284 
   1285     prop = xsltGetCNsProp(style, inst, propName, XSLT_NAMESPACE);
   1286     if (prop == NULL) {
   1287 	if (mandatory) {
   1288 	    xsltTransformError(NULL, style, inst,
   1289 		"The attribute '%s' is missing.\n", propName);
   1290 	    style->errors++;
   1291 	    return;
   1292 	}
   1293     } else {
   1294         const xmlChar *URI;
   1295 
   1296 	if (xmlValidateQName(prop, 0)) {
   1297 	    xsltTransformError(NULL, style, inst,
   1298 		"The value '%s' of the attribute "
   1299 		"'%s' is not a valid QName.\n", prop, propName);
   1300 	    style->errors++;
   1301 	    return;
   1302 	} else {
   1303 	    /*
   1304 	    * @prop will be in the string dict afterwards, @URI not.
   1305 	    */
   1306 	    URI = xsltGetQNameURI2(style, inst, &prop);
   1307 	    if (prop == NULL) {
   1308 		style->errors++;
   1309 	    } else {
   1310 		*localName = prop;
   1311 		if (hasProp)
   1312 		    *hasProp = 1;
   1313 		if (URI != NULL) {
   1314 		    /*
   1315 		    * Fixes bug #308441: Put the ns-name in the dict
   1316 		    * in order to pointer compare names during XPath's
   1317 		    * variable lookup.
   1318 		    */
   1319 		    if (nsName)
   1320 			*nsName = xmlDictLookup(style->dict, URI, -1);
   1321 		    /* comp->has_ns = 1; */
   1322 		}
   1323 	    }
   1324 	}
   1325     }
   1326     return;
   1327 }
   1328 
   1329 /**
   1330  * xsltWithParamComp:
   1331  * @style: an XSLT compiled stylesheet
   1332  * @inst:  the xslt with-param node
   1333  *
   1334  * Process the xslt with-param node on the source node
   1335  * Allowed parents: xsl:call-template, xsl:apply-templates.
   1336  * <xsl:with-param
   1337  *  name = qname
   1338  *  select = expression>
   1339  *  <!-- Content: template -->
   1340  * </xsl:with-param>
   1341  */
   1342 static void
   1343 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1344 #ifdef XSLT_REFACTORED
   1345     xsltStyleItemWithParamPtr comp;
   1346 #else
   1347     xsltStylePreCompPtr comp;
   1348 #endif
   1349 
   1350     if ((style == NULL) || (inst == NULL))
   1351 	return;
   1352 
   1353 #ifdef XSLT_REFACTORED
   1354     comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
   1355 #else
   1356     comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
   1357 #endif
   1358 
   1359     if (comp == NULL)
   1360 	return;
   1361     inst->psvi = comp;
   1362     comp->inst = inst;
   1363 
   1364     /*
   1365     * Attribute "name".
   1366     */
   1367     xsltGetQNameProperty(style, inst, BAD_CAST "name",
   1368 	1, &(comp->has_name), &(comp->ns), &(comp->name));
   1369     if (comp->ns)
   1370 	comp->has_ns = 1;
   1371     /*
   1372     * Attribute "select".
   1373     */
   1374     comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
   1375 	                        XSLT_NAMESPACE);
   1376     if (comp->select != NULL) {
   1377 	comp->comp = xsltXPathCompile(style, comp->select);
   1378 	if (comp->comp == NULL) {
   1379 	    xsltTransformError(NULL, style, inst,
   1380 		 "XSLT-with-param: Failed to compile select "
   1381 		 "expression '%s'\n", comp->select);
   1382 	    style->errors++;
   1383 	}
   1384 	if (inst->children != NULL) {
   1385 	    xsltTransformError(NULL, style, inst,
   1386 		"XSLT-with-param: The content should be empty since "
   1387 		"the attribute select is present.\n");
   1388 	    style->warnings++;
   1389 	}
   1390     }
   1391 }
   1392 
   1393 /**
   1394  * xsltNumberComp:
   1395  * @style: an XSLT compiled stylesheet
   1396  * @cur:   the xslt number node
   1397  *
   1398  * Process the xslt number node on the source node
   1399  */
   1400 static void
   1401 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
   1402 #ifdef XSLT_REFACTORED
   1403     xsltStyleItemNumberPtr comp;
   1404 #else
   1405     xsltStylePreCompPtr comp;
   1406 #endif
   1407     const xmlChar *prop;
   1408 
   1409     if ((style == NULL) || (cur == NULL))
   1410 	return;
   1411 
   1412 #ifdef XSLT_REFACTORED
   1413     comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
   1414 #else
   1415     comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
   1416 #endif
   1417 
   1418     if (comp == NULL)
   1419 	return;
   1420     cur->psvi = comp;
   1421 
   1422     if ((style == NULL) || (cur == NULL))
   1423 	return;
   1424 
   1425     comp->numdata.doc = cur->doc;
   1426     comp->numdata.node = cur;
   1427     comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
   1428 	                                XSLT_NAMESPACE);
   1429 
   1430     prop = xsltEvalStaticAttrValueTemplate(style, cur,
   1431 			 (const xmlChar *)"format",
   1432 			 XSLT_NAMESPACE, &comp->numdata.has_format);
   1433     if (comp->numdata.has_format == 0) {
   1434 	comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
   1435     } else {
   1436 	comp->numdata.format = prop;
   1437     }
   1438 
   1439     comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
   1440 					XSLT_NAMESPACE);
   1441     comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
   1442 					XSLT_NAMESPACE);
   1443 
   1444     prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
   1445     if (prop != NULL) {
   1446 	if (xmlStrEqual(prop, BAD_CAST("single")) ||
   1447 	    xmlStrEqual(prop, BAD_CAST("multiple")) ||
   1448 	    xmlStrEqual(prop, BAD_CAST("any"))) {
   1449 	    comp->numdata.level = prop;
   1450 	} else {
   1451 	    xsltTransformError(NULL, style, cur,
   1452 			 "xsl:number : invalid value %s for level\n", prop);
   1453 	    if (style != NULL) style->warnings++;
   1454 	}
   1455     }
   1456 
   1457     prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
   1458     if (prop != NULL) {
   1459 	    xsltTransformError(NULL, style, cur,
   1460 		 "xsl:number : lang attribute not implemented\n");
   1461 	XSLT_TODO; /* xsl:number lang attribute */
   1462     }
   1463 
   1464     prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
   1465     if (prop != NULL) {
   1466 	if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
   1467 	    xsltTransformError(NULL, style, cur,
   1468 		 "xsl:number : letter-value 'alphabetic' not implemented\n");
   1469 	    if (style != NULL) style->warnings++;
   1470 	    XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
   1471 	} else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
   1472 	    xsltTransformError(NULL, style, cur,
   1473 		 "xsl:number : letter-value 'traditional' not implemented\n");
   1474 	    if (style != NULL) style->warnings++;
   1475 	    XSLT_TODO; /* xsl:number letter-value attribute traditional */
   1476 	} else {
   1477 	    xsltTransformError(NULL, style, cur,
   1478 		     "xsl:number : invalid value %s for letter-value\n", prop);
   1479 	    if (style != NULL) style->warnings++;
   1480 	}
   1481     }
   1482 
   1483     prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
   1484 	                XSLT_NAMESPACE);
   1485     if (prop != NULL) {
   1486         comp->numdata.groupingCharacterLen = xmlStrlen(prop);
   1487 	comp->numdata.groupingCharacter =
   1488 	    xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
   1489     }
   1490 
   1491     prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
   1492     if (prop != NULL) {
   1493 	sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
   1494     } else {
   1495 	comp->numdata.groupingCharacter = 0;
   1496     }
   1497 
   1498     /* Set default values */
   1499     if (comp->numdata.value == NULL) {
   1500 	if (comp->numdata.level == NULL) {
   1501 	    comp->numdata.level = xmlDictLookup(style->dict,
   1502 	                                        BAD_CAST"single", 6);
   1503 	}
   1504     }
   1505 
   1506 }
   1507 
   1508 /**
   1509  * xsltApplyImportsComp:
   1510  * @style: an XSLT compiled stylesheet
   1511  * @inst:  the xslt apply-imports node
   1512  *
   1513  * Process the xslt apply-imports node on the source node
   1514  */
   1515 static void
   1516 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1517 #ifdef XSLT_REFACTORED
   1518     xsltStyleItemApplyImportsPtr comp;
   1519 #else
   1520     xsltStylePreCompPtr comp;
   1521 #endif
   1522 
   1523     if ((style == NULL) || (inst == NULL))
   1524 	return;
   1525 
   1526 #ifdef XSLT_REFACTORED
   1527     comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
   1528 #else
   1529     comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
   1530 #endif
   1531 
   1532     if (comp == NULL)
   1533 	return;
   1534     inst->psvi = comp;
   1535     comp->inst = inst;
   1536 }
   1537 
   1538 /**
   1539  * xsltCallTemplateComp:
   1540  * @style: an XSLT compiled stylesheet
   1541  * @inst:  the xslt call-template node
   1542  *
   1543  * Process the xslt call-template node on the source node
   1544  */
   1545 static void
   1546 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1547 #ifdef XSLT_REFACTORED
   1548     xsltStyleItemCallTemplatePtr comp;
   1549 #else
   1550     xsltStylePreCompPtr comp;
   1551 #endif
   1552 
   1553     if ((style == NULL) || (inst == NULL))
   1554 	return;
   1555 
   1556 #ifdef XSLT_REFACTORED
   1557     comp = (xsltStyleItemCallTemplatePtr)
   1558 	xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
   1559 #else
   1560     comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
   1561 #endif
   1562 
   1563     if (comp == NULL)
   1564 	return;
   1565     inst->psvi = comp;
   1566     comp->inst = inst;
   1567 
   1568     /*
   1569      * Attribute "name".
   1570      */
   1571     xsltGetQNameProperty(style, inst, BAD_CAST "name",
   1572 	1, &(comp->has_name), &(comp->ns), &(comp->name));
   1573     if (comp->ns)
   1574 	comp->has_ns = 1;
   1575 }
   1576 
   1577 /**
   1578  * xsltApplyTemplatesComp:
   1579  * @style: an XSLT compiled stylesheet
   1580  * @inst:  the apply-templates node
   1581  *
   1582  * Process the apply-templates node on the source node
   1583  */
   1584 static void
   1585 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1586 #ifdef XSLT_REFACTORED
   1587     xsltStyleItemApplyTemplatesPtr comp;
   1588 #else
   1589     xsltStylePreCompPtr comp;
   1590 #endif
   1591 
   1592     if ((style == NULL) || (inst == NULL))
   1593 	return;
   1594 
   1595 #ifdef XSLT_REFACTORED
   1596     comp = (xsltStyleItemApplyTemplatesPtr)
   1597 	xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
   1598 #else
   1599     comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
   1600 #endif
   1601 
   1602     if (comp == NULL)
   1603 	return;
   1604     inst->psvi = comp;
   1605     comp->inst = inst;
   1606 
   1607     /*
   1608      * Attribute "mode".
   1609      */
   1610     xsltGetQNameProperty(style, inst, BAD_CAST "mode",
   1611 	0, NULL, &(comp->modeURI), &(comp->mode));
   1612     /*
   1613     * Attribute "select".
   1614     */
   1615     comp->select = xsltGetCNsProp(style, inst, BAD_CAST "select",
   1616 	XSLT_NAMESPACE);
   1617     if (comp->select != NULL) {
   1618 	comp->comp = xsltXPathCompile(style, comp->select);
   1619 	if (comp->comp == NULL) {
   1620 	    xsltTransformError(NULL, style, inst,
   1621 		"XSLT-apply-templates: could not compile select "
   1622 		"expression '%s'\n", comp->select);
   1623 	     style->errors++;
   1624 	}
   1625     }
   1626     /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
   1627 }
   1628 
   1629 /**
   1630  * xsltChooseComp:
   1631  * @style: an XSLT compiled stylesheet
   1632  * @inst:  the xslt choose node
   1633  *
   1634  * Process the xslt choose node on the source node
   1635  */
   1636 static void
   1637 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1638 #ifdef XSLT_REFACTORED
   1639     xsltStyleItemChoosePtr comp;
   1640 #else
   1641     xsltStylePreCompPtr comp;
   1642 #endif
   1643 
   1644     if ((style == NULL) || (inst == NULL))
   1645 	return;
   1646 
   1647 #ifdef XSLT_REFACTORED
   1648     comp = (xsltStyleItemChoosePtr)
   1649 	xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
   1650 #else
   1651     comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
   1652 #endif
   1653 
   1654     if (comp == NULL)
   1655 	return;
   1656     inst->psvi = comp;
   1657     comp->inst = inst;
   1658 }
   1659 
   1660 /**
   1661  * xsltIfComp:
   1662  * @style: an XSLT compiled stylesheet
   1663  * @inst:  the xslt if node
   1664  *
   1665  * Process the xslt if node on the source node
   1666  */
   1667 static void
   1668 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1669 #ifdef XSLT_REFACTORED
   1670     xsltStyleItemIfPtr comp;
   1671 #else
   1672     xsltStylePreCompPtr comp;
   1673 #endif
   1674 
   1675     if ((style == NULL) || (inst == NULL))
   1676 	return;
   1677 
   1678 #ifdef XSLT_REFACTORED
   1679     comp = (xsltStyleItemIfPtr)
   1680 	xsltNewStylePreComp(style, XSLT_FUNC_IF);
   1681 #else
   1682     comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
   1683 #endif
   1684 
   1685     if (comp == NULL)
   1686 	return;
   1687     inst->psvi = comp;
   1688     comp->inst = inst;
   1689 
   1690     comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
   1691     if (comp->test == NULL) {
   1692 	xsltTransformError(NULL, style, inst,
   1693 	     "xsl:if : test is not defined\n");
   1694 	if (style != NULL) style->errors++;
   1695 	return;
   1696     }
   1697     comp->comp = xsltXPathCompile(style, comp->test);
   1698     if (comp->comp == NULL) {
   1699 	xsltTransformError(NULL, style, inst,
   1700 	     "xsl:if : could not compile test expression '%s'\n",
   1701 	                 comp->test);
   1702 	if (style != NULL) style->errors++;
   1703     }
   1704 }
   1705 
   1706 /**
   1707  * xsltWhenComp:
   1708  * @style: an XSLT compiled stylesheet
   1709  * @inst:  the xslt if node
   1710  *
   1711  * Process the xslt if node on the source node
   1712  */
   1713 static void
   1714 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1715 #ifdef XSLT_REFACTORED
   1716     xsltStyleItemWhenPtr comp;
   1717 #else
   1718     xsltStylePreCompPtr comp;
   1719 #endif
   1720 
   1721     if ((style == NULL) || (inst == NULL))
   1722 	return;
   1723 
   1724 #ifdef XSLT_REFACTORED
   1725     comp = (xsltStyleItemWhenPtr)
   1726 	xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
   1727 #else
   1728     comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
   1729 #endif
   1730 
   1731     if (comp == NULL)
   1732 	return;
   1733     inst->psvi = comp;
   1734     comp->inst = inst;
   1735 
   1736     comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
   1737     if (comp->test == NULL) {
   1738 	xsltTransformError(NULL, style, inst,
   1739 	     "xsl:when : test is not defined\n");
   1740 	if (style != NULL) style->errors++;
   1741 	return;
   1742     }
   1743     comp->comp = xsltXPathCompile(style, comp->test);
   1744     if (comp->comp == NULL) {
   1745 	xsltTransformError(NULL, style, inst,
   1746 	     "xsl:when : could not compile test expression '%s'\n",
   1747 	                 comp->test);
   1748 	if (style != NULL) style->errors++;
   1749     }
   1750 }
   1751 
   1752 /**
   1753  * xsltForEachComp:
   1754  * @style: an XSLT compiled stylesheet
   1755  * @inst:  the xslt for-each node
   1756  *
   1757  * Process the xslt for-each node on the source node
   1758  */
   1759 static void
   1760 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1761 #ifdef XSLT_REFACTORED
   1762     xsltStyleItemForEachPtr comp;
   1763 #else
   1764     xsltStylePreCompPtr comp;
   1765 #endif
   1766 
   1767     if ((style == NULL) || (inst == NULL))
   1768 	return;
   1769 
   1770 #ifdef XSLT_REFACTORED
   1771     comp = (xsltStyleItemForEachPtr)
   1772 	xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
   1773 #else
   1774     comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
   1775 #endif
   1776 
   1777     if (comp == NULL)
   1778 	return;
   1779     inst->psvi = comp;
   1780     comp->inst = inst;
   1781 
   1782     comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
   1783 	                        XSLT_NAMESPACE);
   1784     if (comp->select == NULL) {
   1785 	xsltTransformError(NULL, style, inst,
   1786 		"xsl:for-each : select is missing\n");
   1787 	if (style != NULL) style->errors++;
   1788     } else {
   1789 	comp->comp = xsltXPathCompile(style, comp->select);
   1790 	if (comp->comp == NULL) {
   1791 	    xsltTransformError(NULL, style, inst,
   1792      "xsl:for-each : could not compile select expression '%s'\n",
   1793 			     comp->select);
   1794 	    if (style != NULL) style->errors++;
   1795 	}
   1796     }
   1797     /* TODO: handle and skip the xsl:sort */
   1798 }
   1799 
   1800 /**
   1801  * xsltVariableComp:
   1802  * @style: an XSLT compiled stylesheet
   1803  * @inst:  the xslt variable node
   1804  *
   1805  * Process the xslt variable node on the source node
   1806  */
   1807 static void
   1808 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1809 #ifdef XSLT_REFACTORED
   1810     xsltStyleItemVariablePtr comp;
   1811 #else
   1812     xsltStylePreCompPtr comp;
   1813 #endif
   1814 
   1815     if ((style == NULL) || (inst == NULL))
   1816 	return;
   1817 
   1818 #ifdef XSLT_REFACTORED
   1819     comp = (xsltStyleItemVariablePtr)
   1820 	xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
   1821 #else
   1822     comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
   1823 #endif
   1824 
   1825     if (comp == NULL)
   1826 	return;
   1827 
   1828     inst->psvi = comp;
   1829     comp->inst = inst;
   1830     /*
   1831      * The full template resolution can be done statically
   1832      */
   1833 
   1834     /*
   1835     * Attribute "name".
   1836     */
   1837     xsltGetQNameProperty(style, inst, BAD_CAST "name",
   1838 	1, &(comp->has_name), &(comp->ns), &(comp->name));
   1839     if (comp->ns)
   1840 	comp->has_ns = 1;
   1841     /*
   1842     * Attribute "select".
   1843     */
   1844     comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
   1845 	                        XSLT_NAMESPACE);
   1846     if (comp->select != NULL) {
   1847 	comp->comp = xsltXPathCompile(style, comp->select);
   1848 	if (comp->comp == NULL) {
   1849 	    xsltTransformError(NULL, style, inst,
   1850 		"XSLT-variable: Failed to compile the XPath expression '%s'.\n",
   1851 		comp->select);
   1852 	    style->errors++;
   1853 	}
   1854 	if (inst->children != NULL) {
   1855 	    xsltTransformError(NULL, style, inst,
   1856 		"XSLT-variable: The must be no child nodes, since the "
   1857 		"attribute 'select' was specified.\n");
   1858 	    style->errors++;
   1859 	}
   1860     }
   1861 }
   1862 
   1863 /**
   1864  * xsltParamComp:
   1865  * @style: an XSLT compiled stylesheet
   1866  * @inst:  the xslt param node
   1867  *
   1868  * Process the xslt param node on the source node
   1869  */
   1870 static void
   1871 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
   1872 #ifdef XSLT_REFACTORED
   1873     xsltStyleItemParamPtr comp;
   1874 #else
   1875     xsltStylePreCompPtr comp;
   1876 #endif
   1877 
   1878     if ((style == NULL) || (inst == NULL))
   1879 	return;
   1880 
   1881 #ifdef XSLT_REFACTORED
   1882     comp = (xsltStyleItemParamPtr)
   1883 	xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
   1884 #else
   1885     comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
   1886 #endif
   1887 
   1888     if (comp == NULL)
   1889 	return;
   1890     inst->psvi = comp;
   1891     comp->inst = inst;
   1892 
   1893     /*
   1894      * Attribute "name".
   1895      */
   1896     xsltGetQNameProperty(style, inst, BAD_CAST "name",
   1897 	1, &(comp->has_name), &(comp->ns), &(comp->name));
   1898     if (comp->ns)
   1899 	comp->has_ns = 1;
   1900     /*
   1901     * Attribute "select".
   1902     */
   1903     comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
   1904 	                        XSLT_NAMESPACE);
   1905     if (comp->select != NULL) {
   1906 	comp->comp = xsltXPathCompile(style, comp->select);
   1907 	if (comp->comp == NULL) {
   1908 	    xsltTransformError(NULL, style, inst,
   1909 		"XSLT-param: could not compile select expression '%s'.\n",
   1910 		comp->select);
   1911 	    style->errors++;
   1912 	}
   1913 	if (inst->children != NULL) {
   1914 	    xsltTransformError(NULL, style, inst,
   1915 		"XSLT-param: The content should be empty since the "
   1916 		"attribute 'select' is present.\n");
   1917 	    style->warnings++;
   1918 	}
   1919     }
   1920 }
   1921 
   1922 /************************************************************************
   1923  *									*
   1924  *		    Generic interface					*
   1925  *									*
   1926  ************************************************************************/
   1927 
   1928 /**
   1929  * xsltFreeStylePreComps:
   1930  * @style:  an XSLT transformation context
   1931  *
   1932  * Free up the memory allocated by all precomputed blocks
   1933  */
   1934 void
   1935 xsltFreeStylePreComps(xsltStylesheetPtr style) {
   1936     xsltElemPreCompPtr cur, next;
   1937 
   1938     if (style == NULL)
   1939 	return;
   1940 
   1941     cur = style->preComps;
   1942     while (cur != NULL) {
   1943 	next = cur->next;
   1944 	if (cur->type == XSLT_FUNC_EXTENSION)
   1945 	    cur->free(cur);
   1946 	else
   1947 	    xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
   1948 	cur = next;
   1949     }
   1950 }
   1951 
   1952 #ifdef XSLT_REFACTORED
   1953 
   1954 /**
   1955  * xsltStylePreCompute:
   1956  * @style:  the XSLT stylesheet
   1957  * @node:  the element in the XSLT namespace
   1958  *
   1959  * Precompute an XSLT element.
   1960  * This expects the type of the element to be already
   1961  * set in style->compCtxt->inode->type;
   1962  */
   1963 void
   1964 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
   1965     /*
   1966     * The xsltXSLTElemMarker marker was set beforehand by
   1967     *  the parsing mechanism for all elements in the XSLT namespace.
   1968     */
   1969     if (style == NULL) {
   1970 	if (node != NULL)
   1971 	    node->psvi = NULL;
   1972 	return;
   1973     }
   1974     if (node == NULL)
   1975 	return;
   1976     if (! IS_XSLT_ELEM_FAST(node))
   1977 	return;
   1978 
   1979     node->psvi = NULL;
   1980     if (XSLT_CCTXT(style)->inode->type != 0) {
   1981 	switch (XSLT_CCTXT(style)->inode->type) {
   1982 	    case XSLT_FUNC_APPLYTEMPLATES:
   1983 		xsltApplyTemplatesComp(style, node);
   1984 		break;
   1985 	    case XSLT_FUNC_WITHPARAM:
   1986 		xsltWithParamComp(style, node);
   1987 		break;
   1988 	    case XSLT_FUNC_VALUEOF:
   1989 		xsltValueOfComp(style, node);
   1990 		break;
   1991 	    case XSLT_FUNC_COPY:
   1992 		xsltCopyComp(style, node);
   1993 		break;
   1994 	    case XSLT_FUNC_COPYOF:
   1995 		xsltCopyOfComp(style, node);
   1996 		break;
   1997 	    case XSLT_FUNC_IF:
   1998 		xsltIfComp(style, node);
   1999 		break;
   2000 	    case XSLT_FUNC_CHOOSE:
   2001 		xsltChooseComp(style, node);
   2002 		break;
   2003 	    case XSLT_FUNC_WHEN:
   2004 		xsltWhenComp(style, node);
   2005 		break;
   2006 	    case XSLT_FUNC_OTHERWISE:
   2007 		/* NOP yet */
   2008 		return;
   2009 	    case XSLT_FUNC_FOREACH:
   2010 		xsltForEachComp(style, node);
   2011 		break;
   2012 	    case XSLT_FUNC_APPLYIMPORTS:
   2013 		xsltApplyImportsComp(style, node);
   2014 		break;
   2015 	    case XSLT_FUNC_ATTRIBUTE:
   2016 		xsltAttributeComp(style, node);
   2017 		break;
   2018 	    case XSLT_FUNC_ELEMENT:
   2019 		xsltElementComp(style, node);
   2020 		break;
   2021 	    case XSLT_FUNC_SORT:
   2022 		xsltSortComp(style, node);
   2023 		break;
   2024 	    case XSLT_FUNC_COMMENT:
   2025 		xsltCommentComp(style, node);
   2026 		break;
   2027 	    case XSLT_FUNC_NUMBER:
   2028 		xsltNumberComp(style, node);
   2029 		break;
   2030 	    case XSLT_FUNC_PI:
   2031 		xsltProcessingInstructionComp(style, node);
   2032 		break;
   2033 	    case XSLT_FUNC_CALLTEMPLATE:
   2034 		xsltCallTemplateComp(style, node);
   2035 		break;
   2036 	    case XSLT_FUNC_PARAM:
   2037 		xsltParamComp(style, node);
   2038 		break;
   2039 	    case XSLT_FUNC_VARIABLE:
   2040 		xsltVariableComp(style, node);
   2041 		break;
   2042 	    case XSLT_FUNC_FALLBACK:
   2043 		/* NOP yet */
   2044 		return;
   2045 	    case XSLT_FUNC_DOCUMENT:
   2046 		/* The extra one */
   2047 		node->psvi = (void *) xsltDocumentComp(style, node,
   2048 		    (xsltTransformFunction) xsltDocumentElem);
   2049 		break;
   2050 	    case XSLT_FUNC_MESSAGE:
   2051 		/* NOP yet */
   2052 		return;
   2053 	    default:
   2054 		/*
   2055 		* NOTE that xsl:text, xsl:template, xsl:stylesheet,
   2056 		*  xsl:transform, xsl:import, xsl:include are not expected
   2057 		*  to be handed over to this function.
   2058 		*/
   2059 		xsltTransformError(NULL, style, node,
   2060 		    "Internal error: (xsltStylePreCompute) cannot handle "
   2061 		    "the XSLT element '%s'.\n", node->name);
   2062 		style->errors++;
   2063 		return;
   2064 	}
   2065     } else {
   2066 	/*
   2067 	* Fallback to string comparison.
   2068 	*/
   2069 	if (IS_XSLT_NAME(node, "apply-templates")) {
   2070 	    xsltApplyTemplatesComp(style, node);
   2071 	} else if (IS_XSLT_NAME(node, "with-param")) {
   2072 	    xsltWithParamComp(style, node);
   2073 	} else if (IS_XSLT_NAME(node, "value-of")) {
   2074 	    xsltValueOfComp(style, node);
   2075 	} else if (IS_XSLT_NAME(node, "copy")) {
   2076 	    xsltCopyComp(style, node);
   2077 	} else if (IS_XSLT_NAME(node, "copy-of")) {
   2078 	    xsltCopyOfComp(style, node);
   2079 	} else if (IS_XSLT_NAME(node, "if")) {
   2080 	    xsltIfComp(style, node);
   2081 	} else if (IS_XSLT_NAME(node, "choose")) {
   2082 	    xsltChooseComp(style, node);
   2083 	} else if (IS_XSLT_NAME(node, "when")) {
   2084 	    xsltWhenComp(style, node);
   2085 	} else if (IS_XSLT_NAME(node, "otherwise")) {
   2086 	    /* NOP yet */
   2087 	    return;
   2088 	} else if (IS_XSLT_NAME(node, "for-each")) {
   2089 	    xsltForEachComp(style, node);
   2090 	} else if (IS_XSLT_NAME(node, "apply-imports")) {
   2091 	    xsltApplyImportsComp(style, node);
   2092 	} else if (IS_XSLT_NAME(node, "attribute")) {
   2093 	    xsltAttributeComp(style, node);
   2094 	} else if (IS_XSLT_NAME(node, "element")) {
   2095 	    xsltElementComp(style, node);
   2096 	} else if (IS_XSLT_NAME(node, "sort")) {
   2097 	    xsltSortComp(style, node);
   2098 	} else if (IS_XSLT_NAME(node, "comment")) {
   2099 	    xsltCommentComp(style, node);
   2100 	} else if (IS_XSLT_NAME(node, "number")) {
   2101 	    xsltNumberComp(style, node);
   2102 	} else if (IS_XSLT_NAME(node, "processing-instruction")) {
   2103 	    xsltProcessingInstructionComp(style, node);
   2104 	} else if (IS_XSLT_NAME(node, "call-template")) {
   2105 	    xsltCallTemplateComp(style, node);
   2106 	} else if (IS_XSLT_NAME(node, "param")) {
   2107 	    xsltParamComp(style, node);
   2108 	} else if (IS_XSLT_NAME(node, "variable")) {
   2109 	    xsltVariableComp(style, node);
   2110 	} else if (IS_XSLT_NAME(node, "fallback")) {
   2111 	    /* NOP yet */
   2112 	    return;
   2113 	} else if (IS_XSLT_NAME(node, "document")) {
   2114 	    /* The extra one */
   2115 	    node->psvi = (void *) xsltDocumentComp(style, node,
   2116 		(xsltTransformFunction) xsltDocumentElem);
   2117 	} else if (IS_XSLT_NAME(node, "output")) {
   2118 	    /* Top-level */
   2119 	    return;
   2120 	} else if (IS_XSLT_NAME(node, "preserve-space")) {
   2121 	    /* Top-level */
   2122 	    return;
   2123 	} else if (IS_XSLT_NAME(node, "strip-space")) {
   2124 	    /* Top-level */
   2125 	    return;
   2126 	} else if (IS_XSLT_NAME(node, "key")) {
   2127 	    /* Top-level */
   2128 	    return;
   2129 	} else if (IS_XSLT_NAME(node, "message")) {
   2130 	    return;
   2131 	} else if (IS_XSLT_NAME(node, "attribute-set")) {
   2132 	    /* Top-level */
   2133 	    return;
   2134 	} else if (IS_XSLT_NAME(node, "namespace-alias")) {
   2135 	    /* Top-level */
   2136 	    return;
   2137 	} else if (IS_XSLT_NAME(node, "decimal-format")) {
   2138 	    /* Top-level */
   2139 	    return;
   2140 	} else if (IS_XSLT_NAME(node, "include")) {
   2141 	    /* Top-level */
   2142 	} else {
   2143 	    /*
   2144 	    * NOTE that xsl:text, xsl:template, xsl:stylesheet,
   2145 	    *  xsl:transform, xsl:import, xsl:include are not expected
   2146 	    *  to be handed over to this function.
   2147 	    */
   2148 	    xsltTransformError(NULL, style, node,
   2149 		"Internal error: (xsltStylePreCompute) cannot handle "
   2150 		"the XSLT element '%s'.\n", node->name);
   2151 		style->errors++;
   2152 	    return;
   2153 	}
   2154     }
   2155     /*
   2156     * Assign the current list of in-scope namespaces to the
   2157     * item. This is needed for XPath expressions.
   2158     */
   2159     if (node->psvi != NULL) {
   2160 	((xsltStylePreCompPtr) node->psvi)->inScopeNs =
   2161 	    XSLT_CCTXT(style)->inode->inScopeNs;
   2162     }
   2163 }
   2164 
   2165 #else
   2166 
   2167 /**
   2168  * xsltStylePreCompute:
   2169  * @style:  the XSLT stylesheet
   2170  * @inst:  the instruction in the stylesheet
   2171  *
   2172  * Precompute an XSLT stylesheet element
   2173  */
   2174 void
   2175 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
   2176     /*
   2177     * URGENT TODO: Normally inst->psvi Should never be reserved here,
   2178     *   BUT: since if we include the same stylesheet from
   2179     *   multiple imports, then the stylesheet will be parsed
   2180     *   again. We simply must not try to compute the stylesheet again.
   2181     * TODO: Get to the point where we don't need to query the
   2182     *   namespace- and local-name of the node, but can evaluate this
   2183     *   using cctxt->style->inode->category;
   2184     */
   2185     if (inst->psvi != NULL)
   2186 	return;
   2187 
   2188     if (IS_XSLT_ELEM(inst)) {
   2189 	xsltStylePreCompPtr cur;
   2190 
   2191 	if (IS_XSLT_NAME(inst, "apply-templates")) {
   2192 	    xsltCheckInstructionElement(style, inst);
   2193 	    xsltApplyTemplatesComp(style, inst);
   2194 	} else if (IS_XSLT_NAME(inst, "with-param")) {
   2195 	    xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
   2196 	                           BAD_CAST "call-template");
   2197 	    xsltWithParamComp(style, inst);
   2198 	} else if (IS_XSLT_NAME(inst, "value-of")) {
   2199 	    xsltCheckInstructionElement(style, inst);
   2200 	    xsltValueOfComp(style, inst);
   2201 	} else if (IS_XSLT_NAME(inst, "copy")) {
   2202 	    xsltCheckInstructionElement(style, inst);
   2203 	    xsltCopyComp(style, inst);
   2204 	} else if (IS_XSLT_NAME(inst, "copy-of")) {
   2205 	    xsltCheckInstructionElement(style, inst);
   2206 	    xsltCopyOfComp(style, inst);
   2207 	} else if (IS_XSLT_NAME(inst, "if")) {
   2208 	    xsltCheckInstructionElement(style, inst);
   2209 	    xsltIfComp(style, inst);
   2210 	} else if (IS_XSLT_NAME(inst, "when")) {
   2211 	    xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
   2212 	    xsltWhenComp(style, inst);
   2213 	} else if (IS_XSLT_NAME(inst, "choose")) {
   2214 	    xsltCheckInstructionElement(style, inst);
   2215 	    xsltChooseComp(style, inst);
   2216 	} else if (IS_XSLT_NAME(inst, "for-each")) {
   2217 	    xsltCheckInstructionElement(style, inst);
   2218 	    xsltForEachComp(style, inst);
   2219 	} else if (IS_XSLT_NAME(inst, "apply-imports")) {
   2220 	    xsltCheckInstructionElement(style, inst);
   2221 	    xsltApplyImportsComp(style, inst);
   2222 	} else if (IS_XSLT_NAME(inst, "attribute")) {
   2223 	    xmlNodePtr parent = inst->parent;
   2224 
   2225 	    if ((parent == NULL) || (parent->ns == NULL) ||
   2226 		((parent->ns != inst->ns) &&
   2227 		 (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
   2228 		(!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
   2229 		xsltCheckInstructionElement(style, inst);
   2230 	    }
   2231 	    xsltAttributeComp(style, inst);
   2232 	} else if (IS_XSLT_NAME(inst, "element")) {
   2233 	    xsltCheckInstructionElement(style, inst);
   2234 	    xsltElementComp(style, inst);
   2235 	} else if (IS_XSLT_NAME(inst, "text")) {
   2236 	    xsltCheckInstructionElement(style, inst);
   2237 	    xsltTextComp(style, inst);
   2238 	} else if (IS_XSLT_NAME(inst, "sort")) {
   2239 	    xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
   2240 	                           BAD_CAST "for-each");
   2241 	    xsltSortComp(style, inst);
   2242 	} else if (IS_XSLT_NAME(inst, "comment")) {
   2243 	    xsltCheckInstructionElement(style, inst);
   2244 	    xsltCommentComp(style, inst);
   2245 	} else if (IS_XSLT_NAME(inst, "number")) {
   2246 	    xsltCheckInstructionElement(style, inst);
   2247 	    xsltNumberComp(style, inst);
   2248 	} else if (IS_XSLT_NAME(inst, "processing-instruction")) {
   2249 	    xsltCheckInstructionElement(style, inst);
   2250 	    xsltProcessingInstructionComp(style, inst);
   2251 	} else if (IS_XSLT_NAME(inst, "call-template")) {
   2252 	    xsltCheckInstructionElement(style, inst);
   2253 	    xsltCallTemplateComp(style, inst);
   2254 	} else if (IS_XSLT_NAME(inst, "param")) {
   2255 	    if (xsltCheckTopLevelElement(style, inst, 0) == 0)
   2256 	        xsltCheckInstructionElement(style, inst);
   2257 	    xsltParamComp(style, inst);
   2258 	} else if (IS_XSLT_NAME(inst, "variable")) {
   2259 	    if (xsltCheckTopLevelElement(style, inst, 0) == 0)
   2260 	        xsltCheckInstructionElement(style, inst);
   2261 	    xsltVariableComp(style, inst);
   2262 	} else if (IS_XSLT_NAME(inst, "otherwise")) {
   2263 	    xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
   2264 	    xsltCheckInstructionElement(style, inst);
   2265 	    return;
   2266 	} else if (IS_XSLT_NAME(inst, "template")) {
   2267 	    xsltCheckTopLevelElement(style, inst, 1);
   2268 	    return;
   2269 	} else if (IS_XSLT_NAME(inst, "output")) {
   2270 	    xsltCheckTopLevelElement(style, inst, 1);
   2271 	    return;
   2272 	} else if (IS_XSLT_NAME(inst, "preserve-space")) {
   2273 	    xsltCheckTopLevelElement(style, inst, 1);
   2274 	    return;
   2275 	} else if (IS_XSLT_NAME(inst, "strip-space")) {
   2276 	    xsltCheckTopLevelElement(style, inst, 1);
   2277 	    return;
   2278 	} else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
   2279 	           (IS_XSLT_NAME(inst, "transform"))) {
   2280 	    xmlNodePtr parent = inst->parent;
   2281 
   2282 	    if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
   2283 		xsltTransformError(NULL, style, inst,
   2284 		    "element %s only allowed only as root element\n",
   2285 				   inst->name);
   2286 		style->errors++;
   2287 	    }
   2288 	    return;
   2289 	} else if (IS_XSLT_NAME(inst, "key")) {
   2290 	    xsltCheckTopLevelElement(style, inst, 1);
   2291 	    return;
   2292 	} else if (IS_XSLT_NAME(inst, "message")) {
   2293 	    xsltCheckInstructionElement(style, inst);
   2294 	    return;
   2295 	} else if (IS_XSLT_NAME(inst, "attribute-set")) {
   2296 	    xsltCheckTopLevelElement(style, inst, 1);
   2297 	    return;
   2298 	} else if (IS_XSLT_NAME(inst, "namespace-alias")) {
   2299 	    xsltCheckTopLevelElement(style, inst, 1);
   2300 	    return;
   2301 	} else if (IS_XSLT_NAME(inst, "include")) {
   2302 	    xsltCheckTopLevelElement(style, inst, 1);
   2303 	    return;
   2304 	} else if (IS_XSLT_NAME(inst, "import")) {
   2305 	    xsltCheckTopLevelElement(style, inst, 1);
   2306 	    return;
   2307 	} else if (IS_XSLT_NAME(inst, "decimal-format")) {
   2308 	    xsltCheckTopLevelElement(style, inst, 1);
   2309 	    return;
   2310 	} else if (IS_XSLT_NAME(inst, "fallback")) {
   2311 	    xsltCheckInstructionElement(style, inst);
   2312 	    return;
   2313 	} else if (IS_XSLT_NAME(inst, "document")) {
   2314 	    xsltCheckInstructionElement(style, inst);
   2315 	    inst->psvi = (void *) xsltDocumentComp(style, inst,
   2316 				(xsltTransformFunction) xsltDocumentElem);
   2317 	} else {
   2318 	    xsltTransformError(NULL, style, inst,
   2319 		 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
   2320 	    if (style != NULL) style->warnings++;
   2321 	}
   2322 
   2323 	cur = (xsltStylePreCompPtr) inst->psvi;
   2324 	/*
   2325 	* A ns-list is build for every XSLT item in the
   2326 	* node-tree. This is needed for XPath expressions.
   2327 	*/
   2328 	if (cur != NULL) {
   2329 	    int i = 0;
   2330 
   2331 	    cur->nsList = xmlGetNsList(inst->doc, inst);
   2332             if (cur->nsList != NULL) {
   2333 		while (cur->nsList[i] != NULL)
   2334 		    i++;
   2335 	    }
   2336 	    cur->nsNr = i;
   2337 	}
   2338     } else {
   2339 	inst->psvi =
   2340 	    (void *) xsltPreComputeExtModuleElement(style, inst);
   2341 
   2342 	/*
   2343 	 * Unknown element, maybe registered at the context
   2344 	 * level. Mark it for later recognition.
   2345 	 */
   2346 	if (inst->psvi == NULL)
   2347 	    inst->psvi = (void *) xsltExtMarker;
   2348     }
   2349 }
   2350 #endif /* XSLT_REFACTORED */
   2351