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