Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpreproc.c
Go to the documentation of this file.
00001 /* 00002 * preproc.c: Preprocessing of style operations 00003 * 00004 * References: 00005 * http://www.w3.org/TR/1999/REC-xslt-19991116 00006 * 00007 * Michael Kay "XSLT Programmer's Reference" pp 637-643 00008 * Writing Multiple Output Files 00009 * 00010 * XSLT-1.1 Working Draft 00011 * http://www.w3.org/TR/xslt11#multiple-output 00012 * 00013 * See Copyright for the status of this software. 00014 * 00015 * daniel@veillard.com 00016 */ 00017 00018 #define IN_LIBXSLT 00019 #include "libxslt.h" 00020 00021 #include <string.h> 00022 00023 #include <libxml/xmlmemory.h> 00024 #include <libxml/parser.h> 00025 #include <libxml/tree.h> 00026 #include <libxml/valid.h> 00027 #include <libxml/hash.h> 00028 #include <libxml/uri.h> 00029 #include <libxml/encoding.h> 00030 #include <libxml/xmlerror.h> 00031 #include "xslt.h" 00032 #include "xsltutils.h" 00033 #include "xsltInternals.h" 00034 #include "transform.h" 00035 #include "templates.h" 00036 #include "variables.h" 00037 #include "numbersInternals.h" 00038 #include "preproc.h" 00039 #include "extra.h" 00040 #include "imports.h" 00041 #include "extensions.h" 00042 00043 #ifdef WITH_XSLT_DEBUG 00044 #define WITH_XSLT_DEBUG_PREPROC 00045 #endif 00046 00047 const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element"; 00048 00049 /************************************************************************ 00050 * * 00051 * Grammar checks * 00052 * * 00053 ************************************************************************/ 00054 00055 #ifdef XSLT_REFACTORED 00056 /* 00057 * Grammar checks are now performed in xslt.c. 00058 */ 00059 #else 00060 00070 static int 00071 xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) { 00072 xmlNodePtr parent; 00073 if ((style == NULL) || (inst == NULL) || (inst->ns == NULL)) 00074 return(-1); 00075 00076 parent = inst->parent; 00077 if (parent == NULL) { 00078 if (err) { 00079 xsltTransformError(NULL, style, inst, 00080 "internal problem: element has no parent\n"); 00081 style->errors++; 00082 } 00083 return(0); 00084 } 00085 if ((parent->ns == NULL) || (parent->type != XML_ELEMENT_NODE) || 00086 ((parent->ns != inst->ns) && 00087 (!xmlStrEqual(parent->ns->href, inst->ns->href))) || 00088 ((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) && 00089 (!xmlStrEqual(parent->name, BAD_CAST "transform")))) { 00090 if (err) { 00091 xsltTransformError(NULL, style, inst, 00092 "element %s only allowed as child of stylesheet\n", 00093 inst->name); 00094 style->errors++; 00095 } 00096 return(0); 00097 } 00098 return(1); 00099 } 00100 00108 static void 00109 xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) { 00110 xmlNodePtr parent; 00111 int has_ext; 00112 00113 if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) || 00114 (style->literal_result)) 00115 return; 00116 00117 has_ext = (style->extInfos != NULL); 00118 00119 parent = inst->parent; 00120 if (parent == NULL) { 00121 xsltTransformError(NULL, style, inst, 00122 "internal problem: element has no parent\n"); 00123 style->errors++; 00124 return; 00125 } 00126 while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) { 00127 if (((parent->ns == inst->ns) || 00128 ((parent->ns != NULL) && 00129 (xmlStrEqual(parent->ns->href, inst->ns->href)))) && 00130 ((xmlStrEqual(parent->name, BAD_CAST "template")) || 00131 (xmlStrEqual(parent->name, BAD_CAST "param")) || 00132 (xmlStrEqual(parent->name, BAD_CAST "attribute")) || 00133 (xmlStrEqual(parent->name, BAD_CAST "variable")))) { 00134 return; 00135 } 00136 00137 /* 00138 * if we are within an extension element all bets are off 00139 * about the semantic there e.g. xsl:param within func:function 00140 */ 00141 if ((has_ext) && (parent->ns != NULL) && 00142 (xmlHashLookup(style->extInfos, parent->ns->href) != NULL)) 00143 return; 00144 00145 parent = parent->parent; 00146 } 00147 xsltTransformError(NULL, style, inst, 00148 "element %s only allowed within a template, variable or param\n", 00149 inst->name); 00150 style->errors++; 00151 } 00152 00163 static void 00164 xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst, 00165 const xmlChar *allow1, const xmlChar *allow2) { 00166 xmlNodePtr parent; 00167 00168 if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) || 00169 (style->literal_result)) 00170 return; 00171 00172 parent = inst->parent; 00173 if (parent == NULL) { 00174 xsltTransformError(NULL, style, inst, 00175 "internal problem: element has no parent\n"); 00176 style->errors++; 00177 return; 00178 } 00179 if (((parent->ns == inst->ns) || 00180 ((parent->ns != NULL) && 00181 (xmlStrEqual(parent->ns->href, inst->ns->href)))) && 00182 ((xmlStrEqual(parent->name, allow1)) || 00183 (xmlStrEqual(parent->name, allow2)))) { 00184 return; 00185 } 00186 00187 if (style->extInfos != NULL) { 00188 while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) { 00189 /* 00190 * if we are within an extension element all bets are off 00191 * about the semantic there e.g. xsl:param within func:function 00192 */ 00193 if ((parent->ns != NULL) && 00194 (xmlHashLookup(style->extInfos, parent->ns->href) != NULL)) 00195 return; 00196 00197 parent = parent->parent; 00198 } 00199 } 00200 xsltTransformError(NULL, style, inst, 00201 "element %s is not allowed within that context\n", 00202 inst->name); 00203 style->errors++; 00204 } 00205 #endif 00206 00207 /************************************************************************ 00208 * * 00209 * handling of precomputed data * 00210 * * 00211 ************************************************************************/ 00212 00223 static xsltStylePreCompPtr 00224 xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) { 00225 xsltStylePreCompPtr cur; 00226 #ifdef XSLT_REFACTORED 00227 size_t size; 00228 #endif 00229 00230 if (style == NULL) 00231 return(NULL); 00232 00233 #ifdef XSLT_REFACTORED 00234 /* 00235 * URGENT TODO: Use specialized factory functions in order 00236 * to avoid this ugliness. 00237 */ 00238 switch (type) { 00239 case XSLT_FUNC_COPY: 00240 size = sizeof(xsltStyleItemCopy); break; 00241 case XSLT_FUNC_SORT: 00242 size = sizeof(xsltStyleItemSort); break; 00243 case XSLT_FUNC_TEXT: 00244 size = sizeof(xsltStyleItemText); break; 00245 case XSLT_FUNC_ELEMENT: 00246 size = sizeof(xsltStyleItemElement); break; 00247 case XSLT_FUNC_ATTRIBUTE: 00248 size = sizeof(xsltStyleItemAttribute); break; 00249 case XSLT_FUNC_COMMENT: 00250 size = sizeof(xsltStyleItemComment); break; 00251 case XSLT_FUNC_PI: 00252 size = sizeof(xsltStyleItemPI); break; 00253 case XSLT_FUNC_COPYOF: 00254 size = sizeof(xsltStyleItemCopyOf); break; 00255 case XSLT_FUNC_VALUEOF: 00256 size = sizeof(xsltStyleItemValueOf); break;; 00257 case XSLT_FUNC_NUMBER: 00258 size = sizeof(xsltStyleItemNumber); break; 00259 case XSLT_FUNC_APPLYIMPORTS: 00260 size = sizeof(xsltStyleItemApplyImports); break; 00261 case XSLT_FUNC_CALLTEMPLATE: 00262 size = sizeof(xsltStyleItemCallTemplate); break; 00263 case XSLT_FUNC_APPLYTEMPLATES: 00264 size = sizeof(xsltStyleItemApplyTemplates); break; 00265 case XSLT_FUNC_CHOOSE: 00266 size = sizeof(xsltStyleItemChoose); break; 00267 case XSLT_FUNC_IF: 00268 size = sizeof(xsltStyleItemIf); break; 00269 case XSLT_FUNC_FOREACH: 00270 size = sizeof(xsltStyleItemForEach); break; 00271 case XSLT_FUNC_DOCUMENT: 00272 size = sizeof(xsltStyleItemDocument); break; 00273 case XSLT_FUNC_WITHPARAM: 00274 size = sizeof(xsltStyleItemWithParam); break; 00275 case XSLT_FUNC_PARAM: 00276 size = sizeof(xsltStyleItemParam); break; 00277 case XSLT_FUNC_VARIABLE: 00278 size = sizeof(xsltStyleItemVariable); break; 00279 case XSLT_FUNC_WHEN: 00280 size = sizeof(xsltStyleItemWhen); break; 00281 case XSLT_FUNC_OTHERWISE: 00282 size = sizeof(xsltStyleItemOtherwise); break; 00283 default: 00284 xsltTransformError(NULL, style, NULL, 00285 "xsltNewStylePreComp : invalid type %d\n", type); 00286 style->errors++; 00287 return(NULL); 00288 } 00289 /* 00290 * Create the structure. 00291 */ 00292 cur = (xsltStylePreCompPtr) xmlMalloc(size); 00293 if (cur == NULL) { 00294 xsltTransformError(NULL, style, NULL, 00295 "xsltNewStylePreComp : malloc failed\n"); 00296 style->errors++; 00297 return(NULL); 00298 } 00299 memset(cur, 0, size); 00300 00301 #else /* XSLT_REFACTORED */ 00302 /* 00303 * Old behaviour. 00304 */ 00305 cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp)); 00306 if (cur == NULL) { 00307 xsltTransformError(NULL, style, NULL, 00308 "xsltNewStylePreComp : malloc failed\n"); 00309 style->errors++; 00310 return(NULL); 00311 } 00312 memset(cur, 0, sizeof(xsltStylePreComp)); 00313 #endif /* XSLT_REFACTORED */ 00314 00315 /* 00316 * URGENT TODO: Better to move this to spezialized factory functions. 00317 */ 00318 cur->type = type; 00319 switch (cur->type) { 00320 case XSLT_FUNC_COPY: 00321 cur->func = (xsltTransformFunction) xsltCopy;break; 00322 case XSLT_FUNC_SORT: 00323 cur->func = (xsltTransformFunction) xsltSort;break; 00324 case XSLT_FUNC_TEXT: 00325 cur->func = (xsltTransformFunction) xsltText;break; 00326 case XSLT_FUNC_ELEMENT: 00327 cur->func = (xsltTransformFunction) xsltElement;break; 00328 case XSLT_FUNC_ATTRIBUTE: 00329 cur->func = (xsltTransformFunction) xsltAttribute;break; 00330 case XSLT_FUNC_COMMENT: 00331 cur->func = (xsltTransformFunction) xsltComment;break; 00332 case XSLT_FUNC_PI: 00333 cur->func = (xsltTransformFunction) xsltProcessingInstruction; 00334 break; 00335 case XSLT_FUNC_COPYOF: 00336 cur->func = (xsltTransformFunction) xsltCopyOf;break; 00337 case XSLT_FUNC_VALUEOF: 00338 cur->func = (xsltTransformFunction) xsltValueOf;break; 00339 case XSLT_FUNC_NUMBER: 00340 cur->func = (xsltTransformFunction) xsltNumber;break; 00341 case XSLT_FUNC_APPLYIMPORTS: 00342 cur->func = (xsltTransformFunction) xsltApplyImports;break; 00343 case XSLT_FUNC_CALLTEMPLATE: 00344 cur->func = (xsltTransformFunction) xsltCallTemplate;break; 00345 case XSLT_FUNC_APPLYTEMPLATES: 00346 cur->func = (xsltTransformFunction) xsltApplyTemplates;break; 00347 case XSLT_FUNC_CHOOSE: 00348 cur->func = (xsltTransformFunction) xsltChoose;break; 00349 case XSLT_FUNC_IF: 00350 cur->func = (xsltTransformFunction) xsltIf;break; 00351 case XSLT_FUNC_FOREACH: 00352 cur->func = (xsltTransformFunction) xsltForEach;break; 00353 case XSLT_FUNC_DOCUMENT: 00354 cur->func = (xsltTransformFunction) xsltDocumentElem;break; 00355 case XSLT_FUNC_WITHPARAM: 00356 case XSLT_FUNC_PARAM: 00357 case XSLT_FUNC_VARIABLE: 00358 case XSLT_FUNC_WHEN: 00359 break; 00360 default: 00361 if (cur->func == NULL) { 00362 xsltTransformError(NULL, style, NULL, 00363 "xsltNewStylePreComp : no function for type %d\n", type); 00364 style->errors++; 00365 } 00366 } 00367 cur->next = style->preComps; 00368 style->preComps = (xsltElemPreCompPtr) cur; 00369 00370 return(cur); 00371 } 00372 00379 static void 00380 xsltFreeStylePreComp(xsltStylePreCompPtr comp) { 00381 if (comp == NULL) 00382 return; 00383 #ifdef XSLT_REFACTORED 00384 /* 00385 * URGENT TODO: Implement destructors. 00386 */ 00387 switch (comp->type) { 00388 case XSLT_FUNC_LITERAL_RESULT_ELEMENT: 00389 break; 00390 case XSLT_FUNC_COPY: 00391 break; 00392 case XSLT_FUNC_SORT: { 00393 xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp; 00394 if (item->locale != (xsltLocale)0) 00395 xsltFreeLocale(item->locale); 00396 if (item->comp != NULL) 00397 xmlXPathFreeCompExpr(item->comp); 00398 } 00399 break; 00400 case XSLT_FUNC_TEXT: 00401 break; 00402 case XSLT_FUNC_ELEMENT: 00403 break; 00404 case XSLT_FUNC_ATTRIBUTE: 00405 break; 00406 case XSLT_FUNC_COMMENT: 00407 break; 00408 case XSLT_FUNC_PI: 00409 break; 00410 case XSLT_FUNC_COPYOF: { 00411 xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp; 00412 if (item->comp != NULL) 00413 xmlXPathFreeCompExpr(item->comp); 00414 } 00415 break; 00416 case XSLT_FUNC_VALUEOF: { 00417 xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp; 00418 if (item->comp != NULL) 00419 xmlXPathFreeCompExpr(item->comp); 00420 } 00421 break; 00422 case XSLT_FUNC_NUMBER: 00423 break; 00424 case XSLT_FUNC_APPLYIMPORTS: 00425 break; 00426 case XSLT_FUNC_CALLTEMPLATE: 00427 break; 00428 case XSLT_FUNC_APPLYTEMPLATES: { 00429 xsltStyleItemApplyTemplatesPtr item = 00430 (xsltStyleItemApplyTemplatesPtr) comp; 00431 if (item->comp != NULL) 00432 xmlXPathFreeCompExpr(item->comp); 00433 } 00434 break; 00435 case XSLT_FUNC_CHOOSE: 00436 break; 00437 case XSLT_FUNC_IF: { 00438 xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp; 00439 if (item->comp != NULL) 00440 xmlXPathFreeCompExpr(item->comp); 00441 } 00442 break; 00443 case XSLT_FUNC_FOREACH: { 00444 xsltStyleItemForEachPtr item = 00445 (xsltStyleItemForEachPtr) comp; 00446 if (item->comp != NULL) 00447 xmlXPathFreeCompExpr(item->comp); 00448 } 00449 break; 00450 case XSLT_FUNC_DOCUMENT: 00451 break; 00452 case XSLT_FUNC_WITHPARAM: { 00453 xsltStyleItemWithParamPtr item = 00454 (xsltStyleItemWithParamPtr) comp; 00455 if (item->comp != NULL) 00456 xmlXPathFreeCompExpr(item->comp); 00457 } 00458 break; 00459 case XSLT_FUNC_PARAM: { 00460 xsltStyleItemParamPtr item = 00461 (xsltStyleItemParamPtr) comp; 00462 if (item->comp != NULL) 00463 xmlXPathFreeCompExpr(item->comp); 00464 } 00465 break; 00466 case XSLT_FUNC_VARIABLE: { 00467 xsltStyleItemVariablePtr item = 00468 (xsltStyleItemVariablePtr) comp; 00469 if (item->comp != NULL) 00470 xmlXPathFreeCompExpr(item->comp); 00471 } 00472 break; 00473 case XSLT_FUNC_WHEN: { 00474 xsltStyleItemWhenPtr item = 00475 (xsltStyleItemWhenPtr) comp; 00476 if (item->comp != NULL) 00477 xmlXPathFreeCompExpr(item->comp); 00478 } 00479 break; 00480 case XSLT_FUNC_OTHERWISE: 00481 case XSLT_FUNC_FALLBACK: 00482 case XSLT_FUNC_MESSAGE: 00483 case XSLT_FUNC_INCLUDE: 00484 case XSLT_FUNC_ATTRSET: 00485 00486 break; 00487 default: 00488 /* TODO: Raise error. */ 00489 break; 00490 } 00491 #else 00492 if (comp->locale != (xsltLocale)0) 00493 xsltFreeLocale(comp->locale); 00494 if (comp->comp != NULL) 00495 xmlXPathFreeCompExpr(comp->comp); 00496 if (comp->nsList != NULL) 00497 xmlFree(comp->nsList); 00498 #endif 00499 00500 xmlFree(comp); 00501 } 00502 00503 00504 /************************************************************************ 00505 * * 00506 * XSLT-1.1 extensions * 00507 * * 00508 ************************************************************************/ 00509 00520 xsltElemPreCompPtr 00521 xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst, 00522 xsltTransformFunction function ATTRIBUTE_UNUSED) { 00523 #ifdef XSLT_REFACTORED 00524 xsltStyleItemDocumentPtr comp; 00525 #else 00526 xsltStylePreCompPtr comp; 00527 #endif 00528 const xmlChar *filename = NULL; 00529 00530 /* 00531 * As of 2006-03-30, this function is currently defined in Libxslt 00532 * to be used for: 00533 * (in libxslt/extra.c) 00534 * "output" in XSLT_SAXON_NAMESPACE 00535 * "write" XSLT_XALAN_NAMESPACE 00536 * "document" XSLT_XT_NAMESPACE 00537 * "document" XSLT_NAMESPACE (from the abandoned old working 00538 * draft of XSLT 1.1) 00539 * (in libexslt/common.c) 00540 * "document" in EXSLT_COMMON_NAMESPACE 00541 */ 00542 #ifdef XSLT_REFACTORED 00543 comp = (xsltStyleItemDocumentPtr) 00544 xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT); 00545 #else 00546 comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT); 00547 #endif 00548 00549 if (comp == NULL) 00550 return (NULL); 00551 comp->inst = inst; 00552 comp->ver11 = 0; 00553 00554 if (xmlStrEqual(inst->name, (const xmlChar *) "output")) { 00555 #ifdef WITH_XSLT_DEBUG_EXTRA 00556 xsltGenericDebug(xsltGenericDebugContext, 00557 "Found saxon:output extension\n"); 00558 #endif 00559 /* 00560 * The element "output" is in the namespace XSLT_SAXON_NAMESPACE 00561 * (http://icl.com/saxon) 00562 * The @file is in no namespace; it is an AVT. 00563 * (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output) 00564 * 00565 * TODO: Do we need not to check the namespace here? 00566 */ 00567 filename = xsltEvalStaticAttrValueTemplate(style, inst, 00568 (const xmlChar *)"file", 00569 NULL, &comp->has_filename); 00570 } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) { 00571 #ifdef WITH_XSLT_DEBUG_EXTRA 00572 xsltGenericDebug(xsltGenericDebugContext, 00573 "Found xalan:write extension\n"); 00574 #endif 00575 /* the filename need to be interpreted */ 00576 /* 00577 * TODO: Is "filename need to be interpreted" meant to be a todo? 00578 * Where will be the filename of xalan:write be processed? 00579 * 00580 * TODO: Do we need not to check the namespace here? 00581 * The extension ns is "http://xml.apache.org/xalan/redirect". 00582 * See http://xml.apache.org/xalan-j/extensionslib.html. 00583 */ 00584 } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) { 00585 if (inst->ns != NULL) { 00586 if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) { 00587 /* 00588 * Mark the instruction as being of 00589 * XSLT version 1.1 (abandoned). 00590 */ 00591 comp->ver11 = 1; 00592 #ifdef WITH_XSLT_DEBUG_EXTRA 00593 xsltGenericDebug(xsltGenericDebugContext, 00594 "Found xslt11:document construct\n"); 00595 #endif 00596 } else { 00597 if (xmlStrEqual(inst->ns->href, 00598 (const xmlChar *)"http://exslt.org/common")) { 00599 /* EXSLT. */ 00600 #ifdef WITH_XSLT_DEBUG_EXTRA 00601 xsltGenericDebug(xsltGenericDebugContext, 00602 "Found exslt:document extension\n"); 00603 #endif 00604 } else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) { 00605 /* James Clark's XT. */ 00606 #ifdef WITH_XSLT_DEBUG_EXTRA 00607 xsltGenericDebug(xsltGenericDebugContext, 00608 "Found xt:document extension\n"); 00609 #endif 00610 } 00611 } 00612 } 00613 /* 00614 * The element "document" is used in conjunction with the 00615 * following namespaces: 00616 * 00617 * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1) 00618 * <!ELEMENT xsl:document %template;> 00619 * <!ATTLIST xsl:document 00620 * href %avt; #REQUIRED 00621 * @href is an AVT 00622 * IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft, 00623 * it was removed and isn't available in XSLT 1.1 anymore. 00624 * In XSLT 2.0 it was renamed to xsl:result-document. 00625 * 00626 * All other attributes are identical to the attributes 00627 * on xsl:output 00628 * 00629 * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common) 00630 * <exsl:document 00631 * href = { uri-reference } 00632 * TODO: is @href is an AVT? 00633 * 00634 * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt) 00635 * Example: <xt:document method="xml" href="myFile.xml"> 00636 * TODO: is @href is an AVT? 00637 * 00638 * In all cases @href is in no namespace. 00639 */ 00640 filename = xsltEvalStaticAttrValueTemplate(style, inst, 00641 (const xmlChar *)"href", NULL, &comp->has_filename); 00642 } 00643 if (!comp->has_filename) { 00644 goto error; 00645 } 00646 comp->filename = filename; 00647 00648 error: 00649 return ((xsltElemPreCompPtr) comp); 00650 } 00651 00652 /************************************************************************ 00653 * * 00654 * Most of the XSLT-1.0 transformations * 00655 * * 00656 ************************************************************************/ 00657 00665 static void 00666 xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) { 00667 #ifdef XSLT_REFACTORED 00668 xsltStyleItemSortPtr comp; 00669 #else 00670 xsltStylePreCompPtr comp; 00671 #endif 00672 if ((style == NULL) || (inst == NULL)) 00673 return; 00674 00675 #ifdef XSLT_REFACTORED 00676 comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT); 00677 #else 00678 comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT); 00679 #endif 00680 00681 if (comp == NULL) 00682 return; 00683 inst->psvi = comp; 00684 comp->inst = inst; 00685 00686 comp->stype = xsltEvalStaticAttrValueTemplate(style, inst, 00687 (const xmlChar *)"data-type", 00688 NULL, &comp->has_stype); 00689 if (comp->stype != NULL) { 00690 if (xmlStrEqual(comp->stype, (const xmlChar *) "text")) 00691 comp->number = 0; 00692 else if (xmlStrEqual(comp->stype, (const xmlChar *) "number")) 00693 comp->number = 1; 00694 else { 00695 xsltTransformError(NULL, style, inst, 00696 "xsltSortComp: no support for data-type = %s\n", comp->stype); 00697 comp->number = 0; /* use default */ 00698 if (style != NULL) style->warnings++; 00699 } 00700 } 00701 comp->order = xsltEvalStaticAttrValueTemplate(style, inst, 00702 (const xmlChar *)"order", 00703 NULL, &comp->has_order); 00704 if (comp->order != NULL) { 00705 if (xmlStrEqual(comp->order, (const xmlChar *) "ascending")) 00706 comp->descending = 0; 00707 else if (xmlStrEqual(comp->order, (const xmlChar *) "descending")) 00708 comp->descending = 1; 00709 else { 00710 xsltTransformError(NULL, style, inst, 00711 "xsltSortComp: invalid value %s for order\n", comp->order); 00712 comp->descending = 0; /* use default */ 00713 if (style != NULL) style->warnings++; 00714 } 00715 } 00716 comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst, 00717 (const xmlChar *)"case-order", 00718 NULL, &comp->has_use); 00719 if (comp->case_order != NULL) { 00720 if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first")) 00721 comp->lower_first = 0; 00722 else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first")) 00723 comp->lower_first = 1; 00724 else { 00725 xsltTransformError(NULL, style, inst, 00726 "xsltSortComp: invalid value %s for order\n", comp->order); 00727 comp->lower_first = 0; /* use default */ 00728 if (style != NULL) style->warnings++; 00729 } 00730 } 00731 00732 comp->lang = xsltEvalStaticAttrValueTemplate(style, inst, 00733 (const xmlChar *)"lang", 00734 NULL, &comp->has_lang); 00735 if (comp->lang != NULL) { 00736 comp->locale = xsltNewLocale(comp->lang); 00737 } 00738 else { 00739 comp->locale = (xsltLocale)0; 00740 } 00741 00742 comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE); 00743 if (comp->select == NULL) { 00744 /* 00745 * The default value of the select attribute is ., which will 00746 * cause the string-value of the current node to be used as 00747 * the sort key. 00748 */ 00749 comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1); 00750 } 00751 comp->comp = xsltXPathCompile(style, comp->select); 00752 if (comp->comp == NULL) { 00753 xsltTransformError(NULL, style, inst, 00754 "xsltSortComp: could not compile select expression '%s'\n", 00755 comp->select); 00756 if (style != NULL) style->errors++; 00757 } 00758 if (inst->children != NULL) { 00759 xsltTransformError(NULL, style, inst, 00760 "xsl:sort : is not empty\n"); 00761 if (style != NULL) style->errors++; 00762 } 00763 } 00764 00772 static void 00773 xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) { 00774 #ifdef XSLT_REFACTORED 00775 xsltStyleItemCopyPtr comp; 00776 #else 00777 xsltStylePreCompPtr comp; 00778 #endif 00779 00780 if ((style == NULL) || (inst == NULL)) 00781 return; 00782 #ifdef XSLT_REFACTORED 00783 comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY); 00784 #else 00785 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY); 00786 #endif 00787 00788 if (comp == NULL) 00789 return; 00790 inst->psvi = comp; 00791 comp->inst = inst; 00792 00793 00794 comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets", 00795 XSLT_NAMESPACE); 00796 if (comp->use == NULL) 00797 comp->has_use = 0; 00798 else 00799 comp->has_use = 1; 00800 } 00801 00802 #ifdef XSLT_REFACTORED 00803 /* Enable if ever needed for xsl:text. */ 00804 #else 00805 00815 static void 00816 xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) { 00817 #ifdef XSLT_REFACTORED 00818 xsltStyleItemTextPtr comp; 00819 #else 00820 xsltStylePreCompPtr comp; 00821 #endif 00822 const xmlChar *prop; 00823 00824 if ((style == NULL) || (inst == NULL)) 00825 return; 00826 00827 #ifdef XSLT_REFACTORED 00828 comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT); 00829 #else 00830 comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT); 00831 #endif 00832 if (comp == NULL) 00833 return; 00834 inst->psvi = comp; 00835 comp->inst = inst; 00836 comp->noescape = 0; 00837 00838 prop = xsltGetCNsProp(style, inst, 00839 (const xmlChar *)"disable-output-escaping", 00840 XSLT_NAMESPACE); 00841 if (prop != NULL) { 00842 if (xmlStrEqual(prop, (const xmlChar *)"yes")) { 00843 comp->noescape = 1; 00844 } else if (!xmlStrEqual(prop, 00845 (const xmlChar *)"no")){ 00846 xsltTransformError(NULL, style, inst, 00847 "xsl:text: disable-output-escaping allows only yes or no\n"); 00848 if (style != NULL) style->warnings++; 00849 } 00850 } 00851 } 00852 #endif /* else of XSLT_REFACTORED */ 00853 00861 static void 00862 xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) { 00863 #ifdef XSLT_REFACTORED 00864 xsltStyleItemElementPtr comp; 00865 #else 00866 xsltStylePreCompPtr comp; 00867 #endif 00868 00869 /* 00870 * <xsl:element 00871 * name = { qname } 00872 * namespace = { uri-reference } 00873 * use-attribute-sets = qnames> 00874 * <!-- Content: template --> 00875 * </xsl:element> 00876 */ 00877 if ((style == NULL) || (inst == NULL)) 00878 return; 00879 00880 #ifdef XSLT_REFACTORED 00881 comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT); 00882 #else 00883 comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT); 00884 #endif 00885 00886 if (comp == NULL) 00887 return; 00888 inst->psvi = comp; 00889 comp->inst = inst; 00890 00891 /* 00892 * Attribute "name". 00893 */ 00894 /* 00895 * TODO: Precompile the AVT. See bug #344894. 00896 */ 00897 comp->name = xsltEvalStaticAttrValueTemplate(style, inst, 00898 (const xmlChar *)"name", NULL, &comp->has_name); 00899 if (! comp->has_name) { 00900 xsltTransformError(NULL, style, inst, 00901 "xsl:element: The attribute 'name' is missing.\n"); 00902 style->errors++; 00903 goto error; 00904 } 00905 /* 00906 * Attribute "namespace". 00907 */ 00908 /* 00909 * TODO: Precompile the AVT. See bug #344894. 00910 */ 00911 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst, 00912 (const xmlChar *)"namespace", NULL, &comp->has_ns); 00913 00914 if (comp->name != NULL) { 00915 if (xmlValidateQName(comp->name, 0)) { 00916 xsltTransformError(NULL, style, inst, 00917 "xsl:element: The value '%s' of the attribute 'name' is " 00918 "not a valid QName.\n", comp->name); 00919 style->errors++; 00920 } else { 00921 const xmlChar *prefix = NULL, *name; 00922 00923 name = xsltSplitQName(style->dict, comp->name, &prefix); 00924 if (comp->has_ns == 0) { 00925 xmlNsPtr ns; 00926 00927 /* 00928 * SPEC XSLT 1.0: 00929 * "If the namespace attribute is not present, then the QName is 00930 * expanded into an expanded-name using the namespace declarations 00931 * in effect for the xsl:element element, including any default 00932 * namespace declaration. 00933 */ 00934 ns = xmlSearchNs(inst->doc, inst, prefix); 00935 if (ns != NULL) { 00936 comp->ns = xmlDictLookup(style->dict, ns->href, -1); 00937 comp->has_ns = 1; 00938 #ifdef XSLT_REFACTORED 00939 comp->nsPrefix = prefix; 00940 comp->name = name; 00941 #endif 00942 } else if (prefix != NULL) { 00943 xsltTransformError(NULL, style, inst, 00944 "xsl:element: The prefixed QName '%s' " 00945 "has no namespace binding in scope in the " 00946 "stylesheet; this is an error, since the namespace was " 00947 "not specified by the instruction itself.\n", comp->name); 00948 style->errors++; 00949 } 00950 } 00951 if ((prefix != NULL) && 00952 (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3))) 00953 { 00954 /* 00955 * Mark is to be skipped. 00956 */ 00957 comp->has_name = 0; 00958 } 00959 } 00960 } 00961 /* 00962 * Attribute "use-attribute-sets", 00963 */ 00964 comp->use = xsltEvalStaticAttrValueTemplate(style, inst, 00965 (const xmlChar *)"use-attribute-sets", 00966 NULL, &comp->has_use); 00967 00968 error: 00969 return; 00970 } 00971 00979 static void 00980 xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) { 00981 #ifdef XSLT_REFACTORED 00982 xsltStyleItemAttributePtr comp; 00983 #else 00984 xsltStylePreCompPtr comp; 00985 #endif 00986 00987 /* 00988 * <xsl:attribute 00989 * name = { qname } 00990 * namespace = { uri-reference }> 00991 * <!-- Content: template --> 00992 * </xsl:attribute> 00993 */ 00994 if ((style == NULL) || (inst == NULL)) 00995 return; 00996 00997 #ifdef XSLT_REFACTORED 00998 comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style, 00999 XSLT_FUNC_ATTRIBUTE); 01000 #else 01001 comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE); 01002 #endif 01003 01004 if (comp == NULL) 01005 return; 01006 inst->psvi = comp; 01007 comp->inst = inst; 01008 01009 /* 01010 * Attribute "name". 01011 */ 01012 /* 01013 * TODO: Precompile the AVT. See bug #344894. 01014 */ 01015 comp->name = xsltEvalStaticAttrValueTemplate(style, inst, 01016 (const xmlChar *)"name", 01017 NULL, &comp->has_name); 01018 if (! comp->has_name) { 01019 xsltTransformError(NULL, style, inst, 01020 "XSLT-attribute: The attribute 'name' is missing.\n"); 01021 style->errors++; 01022 return; 01023 } 01024 /* 01025 * Attribute "namespace". 01026 */ 01027 /* 01028 * TODO: Precompile the AVT. See bug #344894. 01029 */ 01030 comp->ns = xsltEvalStaticAttrValueTemplate(style, inst, 01031 (const xmlChar *)"namespace", 01032 NULL, &comp->has_ns); 01033 01034 if (comp->name != NULL) { 01035 if (xmlValidateQName(comp->name, 0)) { 01036 xsltTransformError(NULL, style, inst, 01037 "xsl:attribute: The value '%s' of the attribute 'name' is " 01038 "not a valid QName.\n", comp->name); 01039 style->errors++; 01040 } else { 01041 const xmlChar *prefix = NULL, *name; 01042 01043 name = xsltSplitQName(style->dict, comp->name, &prefix); 01044 if (prefix != NULL) { 01045 if (comp->has_ns == 0) { 01046 xmlNsPtr ns; 01047 01048 /* 01049 * SPEC XSLT 1.0: 01050 * "If the namespace attribute is not present, then the 01051 * QName is expanded into an expanded-name using the 01052 * namespace declarations in effect for the xsl:element 01053 * element, including any default namespace declaration. 01054 */ 01055 ns = xmlSearchNs(inst->doc, inst, prefix); 01056 if (ns != NULL) { 01057 comp->ns = xmlDictLookup(style->dict, ns->href, -1); 01058 comp->has_ns = 1; 01059 #ifdef XSLT_REFACTORED 01060 comp->nsPrefix = prefix; 01061 comp->name = name; 01062 #endif 01063 } else { 01064 xsltTransformError(NULL, style, inst, 01065 "xsl:attribute: The prefixed QName '%s' " 01066 "has no namespace binding in scope in the " 01067 "stylesheet; this is an error, since the " 01068 "namespace was not specified by the instruction " 01069 "itself.\n", comp->name); 01070 style->errors++; 01071 } 01072 } 01073 if (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)) { 01074 /* 01075 * SPEC XSLT 1.0: 01076 * "It is an error if the string that results from 01077 * instantiating the attribute value template is not a 01078 * QName or is the string xmlns. An XSLT processor may 01079 * signal the error; if it does not signal the error, 01080 * it must recover by not adding the attribute to the 01081 * result tree." 01082 * 01083 * Reject a prefix of "xmlns". Mark to be skipped. 01084 */ 01085 comp->has_name = 0; 01086 01087 #ifdef WITH_XSLT_DEBUG_PARSING 01088 xsltGenericDebug(xsltGenericDebugContext, 01089 "xsltAttribute: xmlns prefix forbidden\n"); 01090 #endif 01091 return; 01092 } 01093 01094 } 01095 } 01096 } 01097 } 01098 01106 static void 01107 xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01108 #ifdef XSLT_REFACTORED 01109 xsltStyleItemCommentPtr comp; 01110 #else 01111 xsltStylePreCompPtr comp; 01112 #endif 01113 01114 if ((style == NULL) || (inst == NULL)) 01115 return; 01116 01117 #ifdef XSLT_REFACTORED 01118 comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT); 01119 #else 01120 comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT); 01121 #endif 01122 01123 if (comp == NULL) 01124 return; 01125 inst->psvi = comp; 01126 comp->inst = inst; 01127 } 01128 01136 static void 01137 xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01138 #ifdef XSLT_REFACTORED 01139 xsltStyleItemPIPtr comp; 01140 #else 01141 xsltStylePreCompPtr comp; 01142 #endif 01143 01144 if ((style == NULL) || (inst == NULL)) 01145 return; 01146 01147 #ifdef XSLT_REFACTORED 01148 comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI); 01149 #else 01150 comp = xsltNewStylePreComp(style, XSLT_FUNC_PI); 01151 #endif 01152 01153 if (comp == NULL) 01154 return; 01155 inst->psvi = comp; 01156 comp->inst = inst; 01157 01158 comp->name = xsltEvalStaticAttrValueTemplate(style, inst, 01159 (const xmlChar *)"name", 01160 XSLT_NAMESPACE, &comp->has_name); 01161 } 01162 01170 static void 01171 xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01172 #ifdef XSLT_REFACTORED 01173 xsltStyleItemCopyOfPtr comp; 01174 #else 01175 xsltStylePreCompPtr comp; 01176 #endif 01177 01178 if ((style == NULL) || (inst == NULL)) 01179 return; 01180 01181 #ifdef XSLT_REFACTORED 01182 comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF); 01183 #else 01184 comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF); 01185 #endif 01186 01187 if (comp == NULL) 01188 return; 01189 inst->psvi = comp; 01190 comp->inst = inst; 01191 01192 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select", 01193 XSLT_NAMESPACE); 01194 if (comp->select == NULL) { 01195 xsltTransformError(NULL, style, inst, 01196 "xsl:copy-of : select is missing\n"); 01197 if (style != NULL) style->errors++; 01198 return; 01199 } 01200 comp->comp = xsltXPathCompile(style, comp->select); 01201 if (comp->comp == NULL) { 01202 xsltTransformError(NULL, style, inst, 01203 "xsl:copy-of : could not compile select expression '%s'\n", 01204 comp->select); 01205 if (style != NULL) style->errors++; 01206 } 01207 } 01208 01216 static void 01217 xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01218 #ifdef XSLT_REFACTORED 01219 xsltStyleItemValueOfPtr comp; 01220 #else 01221 xsltStylePreCompPtr comp; 01222 #endif 01223 const xmlChar *prop; 01224 01225 if ((style == NULL) || (inst == NULL)) 01226 return; 01227 01228 #ifdef XSLT_REFACTORED 01229 comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF); 01230 #else 01231 comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF); 01232 #endif 01233 01234 if (comp == NULL) 01235 return; 01236 inst->psvi = comp; 01237 comp->inst = inst; 01238 01239 prop = xsltGetCNsProp(style, inst, 01240 (const xmlChar *)"disable-output-escaping", 01241 XSLT_NAMESPACE); 01242 if (prop != NULL) { 01243 if (xmlStrEqual(prop, (const xmlChar *)"yes")) { 01244 comp->noescape = 1; 01245 } else if (!xmlStrEqual(prop, 01246 (const xmlChar *)"no")){ 01247 xsltTransformError(NULL, style, inst, 01248 "xsl:value-of : disable-output-escaping allows only yes or no\n"); 01249 if (style != NULL) style->warnings++; 01250 } 01251 } 01252 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select", 01253 XSLT_NAMESPACE); 01254 if (comp->select == NULL) { 01255 xsltTransformError(NULL, style, inst, 01256 "xsl:value-of : select is missing\n"); 01257 if (style != NULL) style->errors++; 01258 return; 01259 } 01260 comp->comp = xsltXPathCompile(style, comp->select); 01261 if (comp->comp == NULL) { 01262 xsltTransformError(NULL, style, inst, 01263 "xsl:value-of : could not compile select expression '%s'\n", 01264 comp->select); 01265 if (style != NULL) style->errors++; 01266 } 01267 } 01268 01269 static void 01270 xsltGetQNameProperty(xsltStylesheetPtr style, xmlNodePtr inst, 01271 const xmlChar *propName, 01272 int mandatory, 01273 int *hasProp, const xmlChar **nsName, 01274 const xmlChar** localName) 01275 { 01276 const xmlChar *prop; 01277 01278 if (nsName) 01279 *nsName = NULL; 01280 if (localName) 01281 *localName = NULL; 01282 if (hasProp) 01283 *hasProp = 0; 01284 01285 prop = xsltGetCNsProp(style, inst, propName, XSLT_NAMESPACE); 01286 if (prop == NULL) { 01287 if (mandatory) { 01288 xsltTransformError(NULL, style, inst, 01289 "The attribute '%s' is missing.\n", propName); 01290 style->errors++; 01291 return; 01292 } 01293 } else { 01294 const xmlChar *URI; 01295 01296 if (xmlValidateQName(prop, 0)) { 01297 xsltTransformError(NULL, style, inst, 01298 "The value '%s' of the attribute " 01299 "'%s' is not a valid QName.\n", prop, propName); 01300 style->errors++; 01301 return; 01302 } else { 01303 /* 01304 * @prop will be in the string dict afterwards, @URI not. 01305 */ 01306 URI = xsltGetQNameURI2(style, inst, &prop); 01307 if (prop == NULL) { 01308 style->errors++; 01309 } else { 01310 *localName = prop; 01311 if (hasProp) 01312 *hasProp = 1; 01313 if (URI != NULL) { 01314 /* 01315 * Fixes bug #308441: Put the ns-name in the dict 01316 * in order to pointer compare names during XPath's 01317 * variable lookup. 01318 */ 01319 if (nsName) 01320 *nsName = xmlDictLookup(style->dict, URI, -1); 01321 /* comp->has_ns = 1; */ 01322 } 01323 } 01324 } 01325 } 01326 return; 01327 } 01328 01342 static void 01343 xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01344 #ifdef XSLT_REFACTORED 01345 xsltStyleItemWithParamPtr comp; 01346 #else 01347 xsltStylePreCompPtr comp; 01348 #endif 01349 01350 if ((style == NULL) || (inst == NULL)) 01351 return; 01352 01353 #ifdef XSLT_REFACTORED 01354 comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM); 01355 #else 01356 comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM); 01357 #endif 01358 01359 if (comp == NULL) 01360 return; 01361 inst->psvi = comp; 01362 comp->inst = inst; 01363 01364 /* 01365 * Attribute "name". 01366 */ 01367 xsltGetQNameProperty(style, inst, BAD_CAST "name", 01368 1, &(comp->has_name), &(comp->ns), &(comp->name)); 01369 if (comp->ns) 01370 comp->has_ns = 1; 01371 /* 01372 * Attribute "select". 01373 */ 01374 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select", 01375 XSLT_NAMESPACE); 01376 if (comp->select != NULL) { 01377 comp->comp = xsltXPathCompile(style, comp->select); 01378 if (comp->comp == NULL) { 01379 xsltTransformError(NULL, style, inst, 01380 "XSLT-with-param: Failed to compile select " 01381 "expression '%s'\n", comp->select); 01382 style->errors++; 01383 } 01384 if (inst->children != NULL) { 01385 xsltTransformError(NULL, style, inst, 01386 "XSLT-with-param: The content should be empty since " 01387 "the attribute select is present.\n"); 01388 style->warnings++; 01389 } 01390 } 01391 } 01392 01400 static void 01401 xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) { 01402 #ifdef XSLT_REFACTORED 01403 xsltStyleItemNumberPtr comp; 01404 #else 01405 xsltStylePreCompPtr comp; 01406 #endif 01407 const xmlChar *prop; 01408 01409 if ((style == NULL) || (cur == NULL)) 01410 return; 01411 01412 #ifdef XSLT_REFACTORED 01413 comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER); 01414 #else 01415 comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER); 01416 #endif 01417 01418 if (comp == NULL) 01419 return; 01420 cur->psvi = comp; 01421 01422 if ((style == NULL) || (cur == NULL)) 01423 return; 01424 01425 comp->numdata.doc = cur->doc; 01426 comp->numdata.node = cur; 01427 comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value", 01428 XSLT_NAMESPACE); 01429 01430 prop = xsltEvalStaticAttrValueTemplate(style, cur, 01431 (const xmlChar *)"format", 01432 XSLT_NAMESPACE, &comp->numdata.has_format); 01433 if (comp->numdata.has_format == 0) { 01434 comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0); 01435 } else { 01436 comp->numdata.format = prop; 01437 } 01438 01439 comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count", 01440 XSLT_NAMESPACE); 01441 comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from", 01442 XSLT_NAMESPACE); 01443 01444 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE); 01445 if (prop != NULL) { 01446 if (xmlStrEqual(prop, BAD_CAST("single")) || 01447 xmlStrEqual(prop, BAD_CAST("multiple")) || 01448 xmlStrEqual(prop, BAD_CAST("any"))) { 01449 comp->numdata.level = prop; 01450 } else { 01451 xsltTransformError(NULL, style, cur, 01452 "xsl:number : invalid value %s for level\n", prop); 01453 if (style != NULL) style->warnings++; 01454 } 01455 } 01456 01457 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE); 01458 if (prop != NULL) { 01459 xsltTransformError(NULL, style, cur, 01460 "xsl:number : lang attribute not implemented\n"); 01461 XSLT_TODO; /* xsl:number lang attribute */ 01462 } 01463 01464 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE); 01465 if (prop != NULL) { 01466 if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) { 01467 xsltTransformError(NULL, style, cur, 01468 "xsl:number : letter-value 'alphabetic' not implemented\n"); 01469 if (style != NULL) style->warnings++; 01470 XSLT_TODO; /* xsl:number letter-value attribute alphabetic */ 01471 } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) { 01472 xsltTransformError(NULL, style, cur, 01473 "xsl:number : letter-value 'traditional' not implemented\n"); 01474 if (style != NULL) style->warnings++; 01475 XSLT_TODO; /* xsl:number letter-value attribute traditional */ 01476 } else { 01477 xsltTransformError(NULL, style, cur, 01478 "xsl:number : invalid value %s for letter-value\n", prop); 01479 if (style != NULL) style->warnings++; 01480 } 01481 } 01482 01483 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator", 01484 XSLT_NAMESPACE); 01485 if (prop != NULL) { 01486 comp->numdata.groupingCharacterLen = xmlStrlen(prop); 01487 comp->numdata.groupingCharacter = 01488 xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen)); 01489 } 01490 01491 prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE); 01492 if (prop != NULL) { 01493 sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup); 01494 } else { 01495 comp->numdata.groupingCharacter = 0; 01496 } 01497 01498 /* Set default values */ 01499 if (comp->numdata.value == NULL) { 01500 if (comp->numdata.level == NULL) { 01501 comp->numdata.level = xmlDictLookup(style->dict, 01502 BAD_CAST"single", 6); 01503 } 01504 } 01505 01506 } 01507 01515 static void 01516 xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01517 #ifdef XSLT_REFACTORED 01518 xsltStyleItemApplyImportsPtr comp; 01519 #else 01520 xsltStylePreCompPtr comp; 01521 #endif 01522 01523 if ((style == NULL) || (inst == NULL)) 01524 return; 01525 01526 #ifdef XSLT_REFACTORED 01527 comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS); 01528 #else 01529 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS); 01530 #endif 01531 01532 if (comp == NULL) 01533 return; 01534 inst->psvi = comp; 01535 comp->inst = inst; 01536 } 01537 01545 static void 01546 xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01547 #ifdef XSLT_REFACTORED 01548 xsltStyleItemCallTemplatePtr comp; 01549 #else 01550 xsltStylePreCompPtr comp; 01551 #endif 01552 01553 if ((style == NULL) || (inst == NULL)) 01554 return; 01555 01556 #ifdef XSLT_REFACTORED 01557 comp = (xsltStyleItemCallTemplatePtr) 01558 xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE); 01559 #else 01560 comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE); 01561 #endif 01562 01563 if (comp == NULL) 01564 return; 01565 inst->psvi = comp; 01566 comp->inst = inst; 01567 01568 /* 01569 * Attribute "name". 01570 */ 01571 xsltGetQNameProperty(style, inst, BAD_CAST "name", 01572 1, &(comp->has_name), &(comp->ns), &(comp->name)); 01573 if (comp->ns) 01574 comp->has_ns = 1; 01575 } 01576 01584 static void 01585 xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01586 #ifdef XSLT_REFACTORED 01587 xsltStyleItemApplyTemplatesPtr comp; 01588 #else 01589 xsltStylePreCompPtr comp; 01590 #endif 01591 01592 if ((style == NULL) || (inst == NULL)) 01593 return; 01594 01595 #ifdef XSLT_REFACTORED 01596 comp = (xsltStyleItemApplyTemplatesPtr) 01597 xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES); 01598 #else 01599 comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES); 01600 #endif 01601 01602 if (comp == NULL) 01603 return; 01604 inst->psvi = comp; 01605 comp->inst = inst; 01606 01607 /* 01608 * Attribute "mode". 01609 */ 01610 xsltGetQNameProperty(style, inst, BAD_CAST "mode", 01611 0, NULL, &(comp->modeURI), &(comp->mode)); 01612 /* 01613 * Attribute "select". 01614 */ 01615 comp->select = xsltGetCNsProp(style, inst, BAD_CAST "select", 01616 XSLT_NAMESPACE); 01617 if (comp->select != NULL) { 01618 comp->comp = xsltXPathCompile(style, comp->select); 01619 if (comp->comp == NULL) { 01620 xsltTransformError(NULL, style, inst, 01621 "XSLT-apply-templates: could not compile select " 01622 "expression '%s'\n", comp->select); 01623 style->errors++; 01624 } 01625 } 01626 /* TODO: handle (or skip) the xsl:sort and xsl:with-param */ 01627 } 01628 01636 static void 01637 xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01638 #ifdef XSLT_REFACTORED 01639 xsltStyleItemChoosePtr comp; 01640 #else 01641 xsltStylePreCompPtr comp; 01642 #endif 01643 01644 if ((style == NULL) || (inst == NULL)) 01645 return; 01646 01647 #ifdef XSLT_REFACTORED 01648 comp = (xsltStyleItemChoosePtr) 01649 xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE); 01650 #else 01651 comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE); 01652 #endif 01653 01654 if (comp == NULL) 01655 return; 01656 inst->psvi = comp; 01657 comp->inst = inst; 01658 } 01659 01667 static void 01668 xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01669 #ifdef XSLT_REFACTORED 01670 xsltStyleItemIfPtr comp; 01671 #else 01672 xsltStylePreCompPtr comp; 01673 #endif 01674 01675 if ((style == NULL) || (inst == NULL)) 01676 return; 01677 01678 #ifdef XSLT_REFACTORED 01679 comp = (xsltStyleItemIfPtr) 01680 xsltNewStylePreComp(style, XSLT_FUNC_IF); 01681 #else 01682 comp = xsltNewStylePreComp(style, XSLT_FUNC_IF); 01683 #endif 01684 01685 if (comp == NULL) 01686 return; 01687 inst->psvi = comp; 01688 comp->inst = inst; 01689 01690 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE); 01691 if (comp->test == NULL) { 01692 xsltTransformError(NULL, style, inst, 01693 "xsl:if : test is not defined\n"); 01694 if (style != NULL) style->errors++; 01695 return; 01696 } 01697 comp->comp = xsltXPathCompile(style, comp->test); 01698 if (comp->comp == NULL) { 01699 xsltTransformError(NULL, style, inst, 01700 "xsl:if : could not compile test expression '%s'\n", 01701 comp->test); 01702 if (style != NULL) style->errors++; 01703 } 01704 } 01705 01713 static void 01714 xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01715 #ifdef XSLT_REFACTORED 01716 xsltStyleItemWhenPtr comp; 01717 #else 01718 xsltStylePreCompPtr comp; 01719 #endif 01720 01721 if ((style == NULL) || (inst == NULL)) 01722 return; 01723 01724 #ifdef XSLT_REFACTORED 01725 comp = (xsltStyleItemWhenPtr) 01726 xsltNewStylePreComp(style, XSLT_FUNC_WHEN); 01727 #else 01728 comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN); 01729 #endif 01730 01731 if (comp == NULL) 01732 return; 01733 inst->psvi = comp; 01734 comp->inst = inst; 01735 01736 comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE); 01737 if (comp->test == NULL) { 01738 xsltTransformError(NULL, style, inst, 01739 "xsl:when : test is not defined\n"); 01740 if (style != NULL) style->errors++; 01741 return; 01742 } 01743 comp->comp = xsltXPathCompile(style, comp->test); 01744 if (comp->comp == NULL) { 01745 xsltTransformError(NULL, style, inst, 01746 "xsl:when : could not compile test expression '%s'\n", 01747 comp->test); 01748 if (style != NULL) style->errors++; 01749 } 01750 } 01751 01759 static void 01760 xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01761 #ifdef XSLT_REFACTORED 01762 xsltStyleItemForEachPtr comp; 01763 #else 01764 xsltStylePreCompPtr comp; 01765 #endif 01766 01767 if ((style == NULL) || (inst == NULL)) 01768 return; 01769 01770 #ifdef XSLT_REFACTORED 01771 comp = (xsltStyleItemForEachPtr) 01772 xsltNewStylePreComp(style, XSLT_FUNC_FOREACH); 01773 #else 01774 comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH); 01775 #endif 01776 01777 if (comp == NULL) 01778 return; 01779 inst->psvi = comp; 01780 comp->inst = inst; 01781 01782 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select", 01783 XSLT_NAMESPACE); 01784 if (comp->select == NULL) { 01785 xsltTransformError(NULL, style, inst, 01786 "xsl:for-each : select is missing\n"); 01787 if (style != NULL) style->errors++; 01788 } else { 01789 comp->comp = xsltXPathCompile(style, comp->select); 01790 if (comp->comp == NULL) { 01791 xsltTransformError(NULL, style, inst, 01792 "xsl:for-each : could not compile select expression '%s'\n", 01793 comp->select); 01794 if (style != NULL) style->errors++; 01795 } 01796 } 01797 /* TODO: handle and skip the xsl:sort */ 01798 } 01799 01807 static void 01808 xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01809 #ifdef XSLT_REFACTORED 01810 xsltStyleItemVariablePtr comp; 01811 #else 01812 xsltStylePreCompPtr comp; 01813 #endif 01814 01815 if ((style == NULL) || (inst == NULL)) 01816 return; 01817 01818 #ifdef XSLT_REFACTORED 01819 comp = (xsltStyleItemVariablePtr) 01820 xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE); 01821 #else 01822 comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE); 01823 #endif 01824 01825 if (comp == NULL) 01826 return; 01827 01828 inst->psvi = comp; 01829 comp->inst = inst; 01830 /* 01831 * The full template resolution can be done statically 01832 */ 01833 01834 /* 01835 * Attribute "name". 01836 */ 01837 xsltGetQNameProperty(style, inst, BAD_CAST "name", 01838 1, &(comp->has_name), &(comp->ns), &(comp->name)); 01839 if (comp->ns) 01840 comp->has_ns = 1; 01841 /* 01842 * Attribute "select". 01843 */ 01844 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select", 01845 XSLT_NAMESPACE); 01846 if (comp->select != NULL) { 01847 comp->comp = xsltXPathCompile(style, comp->select); 01848 if (comp->comp == NULL) { 01849 xsltTransformError(NULL, style, inst, 01850 "XSLT-variable: Failed to compile the XPath expression '%s'.\n", 01851 comp->select); 01852 style->errors++; 01853 } 01854 if (inst->children != NULL) { 01855 xsltTransformError(NULL, style, inst, 01856 "XSLT-variable: The must be no child nodes, since the " 01857 "attribute 'select' was specified.\n"); 01858 style->errors++; 01859 } 01860 } 01861 } 01862 01870 static void 01871 xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) { 01872 #ifdef XSLT_REFACTORED 01873 xsltStyleItemParamPtr comp; 01874 #else 01875 xsltStylePreCompPtr comp; 01876 #endif 01877 01878 if ((style == NULL) || (inst == NULL)) 01879 return; 01880 01881 #ifdef XSLT_REFACTORED 01882 comp = (xsltStyleItemParamPtr) 01883 xsltNewStylePreComp(style, XSLT_FUNC_PARAM); 01884 #else 01885 comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM); 01886 #endif 01887 01888 if (comp == NULL) 01889 return; 01890 inst->psvi = comp; 01891 comp->inst = inst; 01892 01893 /* 01894 * Attribute "name". 01895 */ 01896 xsltGetQNameProperty(style, inst, BAD_CAST "name", 01897 1, &(comp->has_name), &(comp->ns), &(comp->name)); 01898 if (comp->ns) 01899 comp->has_ns = 1; 01900 /* 01901 * Attribute "select". 01902 */ 01903 comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select", 01904 XSLT_NAMESPACE); 01905 if (comp->select != NULL) { 01906 comp->comp = xsltXPathCompile(style, comp->select); 01907 if (comp->comp == NULL) { 01908 xsltTransformError(NULL, style, inst, 01909 "XSLT-param: could not compile select expression '%s'.\n", 01910 comp->select); 01911 style->errors++; 01912 } 01913 if (inst->children != NULL) { 01914 xsltTransformError(NULL, style, inst, 01915 "XSLT-param: The content should be empty since the " 01916 "attribute 'select' is present.\n"); 01917 style->warnings++; 01918 } 01919 } 01920 } 01921 01922 /************************************************************************ 01923 * * 01924 * Generic interface * 01925 * * 01926 ************************************************************************/ 01927 01934 void 01935 xsltFreeStylePreComps(xsltStylesheetPtr style) { 01936 xsltElemPreCompPtr cur, next; 01937 01938 if (style == NULL) 01939 return; 01940 01941 cur = style->preComps; 01942 while (cur != NULL) { 01943 next = cur->next; 01944 if (cur->type == XSLT_FUNC_EXTENSION) 01945 cur->free(cur); 01946 else 01947 xsltFreeStylePreComp((xsltStylePreCompPtr) cur); 01948 cur = next; 01949 } 01950 } 01951 01952 #ifdef XSLT_REFACTORED 01953 01963 void 01964 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) { 01965 /* 01966 * The xsltXSLTElemMarker marker was set beforehand by 01967 * the parsing mechanism for all elements in the XSLT namespace. 01968 */ 01969 if (style == NULL) { 01970 if (node != NULL) 01971 node->psvi = NULL; 01972 return; 01973 } 01974 if (node == NULL) 01975 return; 01976 if (! IS_XSLT_ELEM_FAST(node)) 01977 return; 01978 01979 node->psvi = NULL; 01980 if (XSLT_CCTXT(style)->inode->type != 0) { 01981 switch (XSLT_CCTXT(style)->inode->type) { 01982 case XSLT_FUNC_APPLYTEMPLATES: 01983 xsltApplyTemplatesComp(style, node); 01984 break; 01985 case XSLT_FUNC_WITHPARAM: 01986 xsltWithParamComp(style, node); 01987 break; 01988 case XSLT_FUNC_VALUEOF: 01989 xsltValueOfComp(style, node); 01990 break; 01991 case XSLT_FUNC_COPY: 01992 xsltCopyComp(style, node); 01993 break; 01994 case XSLT_FUNC_COPYOF: 01995 xsltCopyOfComp(style, node); 01996 break; 01997 case XSLT_FUNC_IF: 01998 xsltIfComp(style, node); 01999 break; 02000 case XSLT_FUNC_CHOOSE: 02001 xsltChooseComp(style, node); 02002 break; 02003 case XSLT_FUNC_WHEN: 02004 xsltWhenComp(style, node); 02005 break; 02006 case XSLT_FUNC_OTHERWISE: 02007 /* NOP yet */ 02008 return; 02009 case XSLT_FUNC_FOREACH: 02010 xsltForEachComp(style, node); 02011 break; 02012 case XSLT_FUNC_APPLYIMPORTS: 02013 xsltApplyImportsComp(style, node); 02014 break; 02015 case XSLT_FUNC_ATTRIBUTE: 02016 xsltAttributeComp(style, node); 02017 break; 02018 case XSLT_FUNC_ELEMENT: 02019 xsltElementComp(style, node); 02020 break; 02021 case XSLT_FUNC_SORT: 02022 xsltSortComp(style, node); 02023 break; 02024 case XSLT_FUNC_COMMENT: 02025 xsltCommentComp(style, node); 02026 break; 02027 case XSLT_FUNC_NUMBER: 02028 xsltNumberComp(style, node); 02029 break; 02030 case XSLT_FUNC_PI: 02031 xsltProcessingInstructionComp(style, node); 02032 break; 02033 case XSLT_FUNC_CALLTEMPLATE: 02034 xsltCallTemplateComp(style, node); 02035 break; 02036 case XSLT_FUNC_PARAM: 02037 xsltParamComp(style, node); 02038 break; 02039 case XSLT_FUNC_VARIABLE: 02040 xsltVariableComp(style, node); 02041 break; 02042 case XSLT_FUNC_FALLBACK: 02043 /* NOP yet */ 02044 return; 02045 case XSLT_FUNC_DOCUMENT: 02046 /* The extra one */ 02047 node->psvi = (void *) xsltDocumentComp(style, node, 02048 (xsltTransformFunction) xsltDocumentElem); 02049 break; 02050 case XSLT_FUNC_MESSAGE: 02051 /* NOP yet */ 02052 return; 02053 default: 02054 /* 02055 * NOTE that xsl:text, xsl:template, xsl:stylesheet, 02056 * xsl:transform, xsl:import, xsl:include are not expected 02057 * to be handed over to this function. 02058 */ 02059 xsltTransformError(NULL, style, node, 02060 "Internal error: (xsltStylePreCompute) cannot handle " 02061 "the XSLT element '%s'.\n", node->name); 02062 style->errors++; 02063 return; 02064 } 02065 } else { 02066 /* 02067 * Fallback to string comparison. 02068 */ 02069 if (IS_XSLT_NAME(node, "apply-templates")) { 02070 xsltApplyTemplatesComp(style, node); 02071 } else if (IS_XSLT_NAME(node, "with-param")) { 02072 xsltWithParamComp(style, node); 02073 } else if (IS_XSLT_NAME(node, "value-of")) { 02074 xsltValueOfComp(style, node); 02075 } else if (IS_XSLT_NAME(node, "copy")) { 02076 xsltCopyComp(style, node); 02077 } else if (IS_XSLT_NAME(node, "copy-of")) { 02078 xsltCopyOfComp(style, node); 02079 } else if (IS_XSLT_NAME(node, "if")) { 02080 xsltIfComp(style, node); 02081 } else if (IS_XSLT_NAME(node, "choose")) { 02082 xsltChooseComp(style, node); 02083 } else if (IS_XSLT_NAME(node, "when")) { 02084 xsltWhenComp(style, node); 02085 } else if (IS_XSLT_NAME(node, "otherwise")) { 02086 /* NOP yet */ 02087 return; 02088 } else if (IS_XSLT_NAME(node, "for-each")) { 02089 xsltForEachComp(style, node); 02090 } else if (IS_XSLT_NAME(node, "apply-imports")) { 02091 xsltApplyImportsComp(style, node); 02092 } else if (IS_XSLT_NAME(node, "attribute")) { 02093 xsltAttributeComp(style, node); 02094 } else if (IS_XSLT_NAME(node, "element")) { 02095 xsltElementComp(style, node); 02096 } else if (IS_XSLT_NAME(node, "sort")) { 02097 xsltSortComp(style, node); 02098 } else if (IS_XSLT_NAME(node, "comment")) { 02099 xsltCommentComp(style, node); 02100 } else if (IS_XSLT_NAME(node, "number")) { 02101 xsltNumberComp(style, node); 02102 } else if (IS_XSLT_NAME(node, "processing-instruction")) { 02103 xsltProcessingInstructionComp(style, node); 02104 } else if (IS_XSLT_NAME(node, "call-template")) { 02105 xsltCallTemplateComp(style, node); 02106 } else if (IS_XSLT_NAME(node, "param")) { 02107 xsltParamComp(style, node); 02108 } else if (IS_XSLT_NAME(node, "variable")) { 02109 xsltVariableComp(style, node); 02110 } else if (IS_XSLT_NAME(node, "fallback")) { 02111 /* NOP yet */ 02112 return; 02113 } else if (IS_XSLT_NAME(node, "document")) { 02114 /* The extra one */ 02115 node->psvi = (void *) xsltDocumentComp(style, node, 02116 (xsltTransformFunction) xsltDocumentElem); 02117 } else if (IS_XSLT_NAME(node, "output")) { 02118 /* Top-level */ 02119 return; 02120 } else if (IS_XSLT_NAME(node, "preserve-space")) { 02121 /* Top-level */ 02122 return; 02123 } else if (IS_XSLT_NAME(node, "strip-space")) { 02124 /* Top-level */ 02125 return; 02126 } else if (IS_XSLT_NAME(node, "key")) { 02127 /* Top-level */ 02128 return; 02129 } else if (IS_XSLT_NAME(node, "message")) { 02130 return; 02131 } else if (IS_XSLT_NAME(node, "attribute-set")) { 02132 /* Top-level */ 02133 return; 02134 } else if (IS_XSLT_NAME(node, "namespace-alias")) { 02135 /* Top-level */ 02136 return; 02137 } else if (IS_XSLT_NAME(node, "decimal-format")) { 02138 /* Top-level */ 02139 return; 02140 } else if (IS_XSLT_NAME(node, "include")) { 02141 /* Top-level */ 02142 } else { 02143 /* 02144 * NOTE that xsl:text, xsl:template, xsl:stylesheet, 02145 * xsl:transform, xsl:import, xsl:include are not expected 02146 * to be handed over to this function. 02147 */ 02148 xsltTransformError(NULL, style, node, 02149 "Internal error: (xsltStylePreCompute) cannot handle " 02150 "the XSLT element '%s'.\n", node->name); 02151 style->errors++; 02152 return; 02153 } 02154 } 02155 /* 02156 * Assign the current list of in-scope namespaces to the 02157 * item. This is needed for XPath expressions. 02158 */ 02159 if (node->psvi != NULL) { 02160 ((xsltStylePreCompPtr) node->psvi)->inScopeNs = 02161 XSLT_CCTXT(style)->inode->inScopeNs; 02162 } 02163 } 02164 02165 #else 02166 02174 void 02175 xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) { 02176 /* 02177 * URGENT TODO: Normally inst->psvi Should never be reserved here, 02178 * BUT: since if we include the same stylesheet from 02179 * multiple imports, then the stylesheet will be parsed 02180 * again. We simply must not try to compute the stylesheet again. 02181 * TODO: Get to the point where we don't need to query the 02182 * namespace- and local-name of the node, but can evaluate this 02183 * using cctxt->style->inode->category; 02184 */ 02185 if (inst->psvi != NULL) 02186 return; 02187 02188 if (IS_XSLT_ELEM(inst)) { 02189 xsltStylePreCompPtr cur; 02190 02191 if (IS_XSLT_NAME(inst, "apply-templates")) { 02192 xsltCheckInstructionElement(style, inst); 02193 xsltApplyTemplatesComp(style, inst); 02194 } else if (IS_XSLT_NAME(inst, "with-param")) { 02195 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates", 02196 BAD_CAST "call-template"); 02197 xsltWithParamComp(style, inst); 02198 } else if (IS_XSLT_NAME(inst, "value-of")) { 02199 xsltCheckInstructionElement(style, inst); 02200 xsltValueOfComp(style, inst); 02201 } else if (IS_XSLT_NAME(inst, "copy")) { 02202 xsltCheckInstructionElement(style, inst); 02203 xsltCopyComp(style, inst); 02204 } else if (IS_XSLT_NAME(inst, "copy-of")) { 02205 xsltCheckInstructionElement(style, inst); 02206 xsltCopyOfComp(style, inst); 02207 } else if (IS_XSLT_NAME(inst, "if")) { 02208 xsltCheckInstructionElement(style, inst); 02209 xsltIfComp(style, inst); 02210 } else if (IS_XSLT_NAME(inst, "when")) { 02211 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL); 02212 xsltWhenComp(style, inst); 02213 } else if (IS_XSLT_NAME(inst, "choose")) { 02214 xsltCheckInstructionElement(style, inst); 02215 xsltChooseComp(style, inst); 02216 } else if (IS_XSLT_NAME(inst, "for-each")) { 02217 xsltCheckInstructionElement(style, inst); 02218 xsltForEachComp(style, inst); 02219 } else if (IS_XSLT_NAME(inst, "apply-imports")) { 02220 xsltCheckInstructionElement(style, inst); 02221 xsltApplyImportsComp(style, inst); 02222 } else if (IS_XSLT_NAME(inst, "attribute")) { 02223 xmlNodePtr parent = inst->parent; 02224 02225 if ((parent == NULL) || (parent->ns == NULL) || 02226 ((parent->ns != inst->ns) && 02227 (!xmlStrEqual(parent->ns->href, inst->ns->href))) || 02228 (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) { 02229 xsltCheckInstructionElement(style, inst); 02230 } 02231 xsltAttributeComp(style, inst); 02232 } else if (IS_XSLT_NAME(inst, "element")) { 02233 xsltCheckInstructionElement(style, inst); 02234 xsltElementComp(style, inst); 02235 } else if (IS_XSLT_NAME(inst, "text")) { 02236 xsltCheckInstructionElement(style, inst); 02237 xsltTextComp(style, inst); 02238 } else if (IS_XSLT_NAME(inst, "sort")) { 02239 xsltCheckParentElement(style, inst, BAD_CAST "apply-templates", 02240 BAD_CAST "for-each"); 02241 xsltSortComp(style, inst); 02242 } else if (IS_XSLT_NAME(inst, "comment")) { 02243 xsltCheckInstructionElement(style, inst); 02244 xsltCommentComp(style, inst); 02245 } else if (IS_XSLT_NAME(inst, "number")) { 02246 xsltCheckInstructionElement(style, inst); 02247 xsltNumberComp(style, inst); 02248 } else if (IS_XSLT_NAME(inst, "processing-instruction")) { 02249 xsltCheckInstructionElement(style, inst); 02250 xsltProcessingInstructionComp(style, inst); 02251 } else if (IS_XSLT_NAME(inst, "call-template")) { 02252 xsltCheckInstructionElement(style, inst); 02253 xsltCallTemplateComp(style, inst); 02254 } else if (IS_XSLT_NAME(inst, "param")) { 02255 if (xsltCheckTopLevelElement(style, inst, 0) == 0) 02256 xsltCheckInstructionElement(style, inst); 02257 xsltParamComp(style, inst); 02258 } else if (IS_XSLT_NAME(inst, "variable")) { 02259 if (xsltCheckTopLevelElement(style, inst, 0) == 0) 02260 xsltCheckInstructionElement(style, inst); 02261 xsltVariableComp(style, inst); 02262 } else if (IS_XSLT_NAME(inst, "otherwise")) { 02263 xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL); 02264 xsltCheckInstructionElement(style, inst); 02265 return; 02266 } else if (IS_XSLT_NAME(inst, "template")) { 02267 xsltCheckTopLevelElement(style, inst, 1); 02268 return; 02269 } else if (IS_XSLT_NAME(inst, "output")) { 02270 xsltCheckTopLevelElement(style, inst, 1); 02271 return; 02272 } else if (IS_XSLT_NAME(inst, "preserve-space")) { 02273 xsltCheckTopLevelElement(style, inst, 1); 02274 return; 02275 } else if (IS_XSLT_NAME(inst, "strip-space")) { 02276 xsltCheckTopLevelElement(style, inst, 1); 02277 return; 02278 } else if ((IS_XSLT_NAME(inst, "stylesheet")) || 02279 (IS_XSLT_NAME(inst, "transform"))) { 02280 xmlNodePtr parent = inst->parent; 02281 02282 if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) { 02283 xsltTransformError(NULL, style, inst, 02284 "element %s only allowed only as root element\n", 02285 inst->name); 02286 style->errors++; 02287 } 02288 return; 02289 } else if (IS_XSLT_NAME(inst, "key")) { 02290 xsltCheckTopLevelElement(style, inst, 1); 02291 return; 02292 } else if (IS_XSLT_NAME(inst, "message")) { 02293 xsltCheckInstructionElement(style, inst); 02294 return; 02295 } else if (IS_XSLT_NAME(inst, "attribute-set")) { 02296 xsltCheckTopLevelElement(style, inst, 1); 02297 return; 02298 } else if (IS_XSLT_NAME(inst, "namespace-alias")) { 02299 xsltCheckTopLevelElement(style, inst, 1); 02300 return; 02301 } else if (IS_XSLT_NAME(inst, "include")) { 02302 xsltCheckTopLevelElement(style, inst, 1); 02303 return; 02304 } else if (IS_XSLT_NAME(inst, "import")) { 02305 xsltCheckTopLevelElement(style, inst, 1); 02306 return; 02307 } else if (IS_XSLT_NAME(inst, "decimal-format")) { 02308 xsltCheckTopLevelElement(style, inst, 1); 02309 return; 02310 } else if (IS_XSLT_NAME(inst, "fallback")) { 02311 xsltCheckInstructionElement(style, inst); 02312 return; 02313 } else if (IS_XSLT_NAME(inst, "document")) { 02314 xsltCheckInstructionElement(style, inst); 02315 inst->psvi = (void *) xsltDocumentComp(style, inst, 02316 (xsltTransformFunction) xsltDocumentElem); 02317 } else { 02318 xsltTransformError(NULL, style, inst, 02319 "xsltStylePreCompute: unknown xsl:%s\n", inst->name); 02320 if (style != NULL) style->warnings++; 02321 } 02322 02323 cur = (xsltStylePreCompPtr) inst->psvi; 02324 /* 02325 * A ns-list is build for every XSLT item in the 02326 * node-tree. This is needed for XPath expressions. 02327 */ 02328 if (cur != NULL) { 02329 int i = 0; 02330 02331 cur->nsList = xmlGetNsList(inst->doc, inst); 02332 if (cur->nsList != NULL) { 02333 while (cur->nsList[i] != NULL) 02334 i++; 02335 } 02336 cur->nsNr = i; 02337 } 02338 } else { 02339 inst->psvi = 02340 (void *) xsltPreComputeExtModuleElement(style, inst); 02341 02342 /* 02343 * Unknown element, maybe registered at the context 02344 * level. Mark it for later recognition. 02345 */ 02346 if (inst->psvi == NULL) 02347 inst->psvi = (void *) xsltExtMarker; 02348 } 02349 } 02350 #endif /* XSLT_REFACTORED */ Generated on Sat May 26 2012 04:18:27 for ReactOS by
1.7.6.1
|