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