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