| OLD | NEW |
| 1 /* | 1 /* |
| 2 * pattern.c: Implemetation of the template match compilation and lookup | 2 * pattern.c: Implemetation of the template match compilation and lookup |
| 3 * | 3 * |
| 4 * Reference: | 4 * Reference: |
| 5 * http://www.w3.org/TR/1999/REC-xslt-19991116 | 5 * http://www.w3.org/TR/1999/REC-xslt-19991116 |
| 6 * | 6 * |
| 7 * See Copyright for the status of this software. | 7 * See Copyright for the status of this software. |
| 8 * | 8 * |
| 9 * daniel@veillard.com | 9 * daniel@veillard.com |
| 10 */ | 10 */ |
| 11 | 11 |
| 12 /* | 12 /* |
| 13 * TODO: handle pathological cases like *[*[@a="b"]] | 13 * TODO: handle pathological cases like *[*[@a="b"]] |
| 14 * TODO: detect [number] at compilation, optimize accordingly | 14 * TODO: detect [number] at compilation, optimize accordingly |
| 15 */ | 15 */ |
| 16 | 16 |
| 17 #define IN_LIBXSLT | 17 #define IN_LIBXSLT |
| 18 #include "libxslt.h" | 18 #include "libxslt.h" |
| 19 | 19 |
| 20 #include <string.h> | 20 #include <string.h> |
| 21 | 21 |
| 22 #include <libxml/xmlmemory.h> | 22 #include <libxml/xmlmemory.h> |
| 23 #include <libxml/tree.h> | 23 #include <libxml/tree.h> |
| 24 #include <libxml/valid.h> | 24 #include <libxml/valid.h> |
| 25 #include <libxml/hash.h> | 25 #include <libxml/hash.h> |
| 26 #include <libxml/xmlerror.h> | 26 #include <libxml/xmlerror.h> |
| 27 #include <libxml/parserInternals.h> | 27 #include <libxml/parserInternals.h> |
| 28 #include <libxml/xpath.h> |
| 28 #include "xslt.h" | 29 #include "xslt.h" |
| 29 #include "xsltInternals.h" | 30 #include "xsltInternals.h" |
| 30 #include "xsltutils.h" | 31 #include "xsltutils.h" |
| 31 #include "imports.h" | 32 #include "imports.h" |
| 32 #include "templates.h" | 33 #include "templates.h" |
| 33 #include "keys.h" | 34 #include "keys.h" |
| 34 #include "pattern.h" | 35 #include "pattern.h" |
| 35 #include "documents.h" | 36 #include "documents.h" |
| 36 | 37 |
| 37 #ifdef WITH_XSLT_DEBUG | 38 #ifdef WITH_XSLT_DEBUG |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 xsltTransformContextPtr ctxt; /* the transformation or NULL */ | 121 xsltTransformContextPtr ctxt; /* the transformation or NULL */ |
| 121 const xmlChar *cur; /* the current char being parsed */ | 122 const xmlChar *cur; /* the current char being parsed */ |
| 122 const xmlChar *base; /* the full expression */ | 123 const xmlChar *base; /* the full expression */ |
| 123 xmlDocPtr doc; /* the source document */ | 124 xmlDocPtr doc; /* the source document */ |
| 124 xmlNodePtr elem; /* the source element */ | 125 xmlNodePtr elem; /* the source element */ |
| 125 int error; /* error code */ | 126 int error; /* error code */ |
| 126 xsltCompMatchPtr comp; /* the result */ | 127 xsltCompMatchPtr comp; /* the result */ |
| 127 }; | 128 }; |
| 128 | 129 |
| 129 /************************************************************************ | 130 /************************************************************************ |
| 130 * » » » » » » » » » * | 131 *» » » » » » » » » * |
| 131 * » » » Type functions »» » » » * | 132 *» » » Type functions» » » » » * |
| 132 * » » » » » » » » » * | 133 *» » » » » » » » » * |
| 133 ************************************************************************/ | 134 ************************************************************************/ |
| 134 | 135 |
| 135 /** | 136 /** |
| 136 * xsltNewCompMatch: | 137 * xsltNewCompMatch: |
| 137 * | 138 * |
| 138 * Create a new XSLT CompMatch | 139 * Create a new XSLT CompMatch |
| 139 * | 140 * |
| 140 * Returns the newly allocated xsltCompMatchPtr or NULL in case of error | 141 * Returns the newly allocated xsltCompMatchPtr or NULL in case of error |
| 141 */ | 142 */ |
| 142 static xsltCompMatchPtr | 143 static xsltCompMatchPtr |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 if (comp->nbStep >= comp->maxStep) { | 297 if (comp->nbStep >= comp->maxStep) { |
| 297 xsltStepOpPtr tmp; | 298 xsltStepOpPtr tmp; |
| 298 | 299 |
| 299 tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 * | 300 tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 * |
| 300 sizeof(xsltStepOp)); | 301 sizeof(xsltStepOp)); |
| 301 if (tmp == NULL) { | 302 if (tmp == NULL) { |
| 302 xsltGenericError(xsltGenericErrorContext, | 303 xsltGenericError(xsltGenericErrorContext, |
| 303 "xsltCompMatchAdd: memory re-allocation failure.\n"); | 304 "xsltCompMatchAdd: memory re-allocation failure.\n"); |
| 304 if (ctxt->style != NULL) | 305 if (ctxt->style != NULL) |
| 305 ctxt->style->errors++; | 306 ctxt->style->errors++; |
| 307 if (value) |
| 308 xmlFree(value); |
| 309 if (value2) |
| 310 xmlFree(value2); |
| 306 return (-1); | 311 return (-1); |
| 307 } | 312 } |
| 308 comp->maxStep *= 2; | 313 comp->maxStep *= 2; |
| 309 comp->steps = tmp; | 314 comp->steps = tmp; |
| 310 } | 315 } |
| 311 comp->steps[comp->nbStep].op = op; | 316 comp->steps[comp->nbStep].op = op; |
| 312 comp->steps[comp->nbStep].value = value; | 317 comp->steps[comp->nbStep].value = value; |
| 313 comp->steps[comp->nbStep].value2 = value2; | 318 comp->steps[comp->nbStep].value2 = value2; |
| 314 comp->steps[comp->nbStep].value3 = NULL; | 319 comp->steps[comp->nbStep].value3 = NULL; |
| 315 comp->steps[comp->nbStep].comp = NULL; | 320 comp->steps[comp->nbStep].comp = NULL; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 * reverse the two top steps. | 366 * reverse the two top steps. |
| 362 */ | 367 */ |
| 363 static void | 368 static void |
| 364 xsltSwapTopCompMatch(xsltCompMatchPtr comp) { | 369 xsltSwapTopCompMatch(xsltCompMatchPtr comp) { |
| 365 int i; | 370 int i; |
| 366 int j = comp->nbStep - 1; | 371 int j = comp->nbStep - 1; |
| 367 | 372 |
| 368 if (j > 0) { | 373 if (j > 0) { |
| 369 register xmlChar *tmp; | 374 register xmlChar *tmp; |
| 370 register xsltOp op; | 375 register xsltOp op; |
| 371 » register xmlXPathCompExprPtr expr; | 376 » register xmlXPathCompExprPtr expr; |
| 372 register int t; | 377 register int t; |
| 373 i = j - 1; | 378 i = j - 1; |
| 374 tmp = comp->steps[i].value; | 379 tmp = comp->steps[i].value; |
| 375 comp->steps[i].value = comp->steps[j].value; | 380 comp->steps[i].value = comp->steps[j].value; |
| 376 comp->steps[j].value = tmp; | 381 comp->steps[j].value = tmp; |
| 377 tmp = comp->steps[i].value2; | 382 tmp = comp->steps[i].value2; |
| 378 comp->steps[i].value2 = comp->steps[j].value2; | 383 comp->steps[i].value2 = comp->steps[j].value2; |
| 379 comp->steps[j].value2 = tmp; | 384 comp->steps[j].value2 = tmp; |
| 380 tmp = comp->steps[i].value3; | 385 tmp = comp->steps[i].value3; |
| 381 comp->steps[i].value3 = comp->steps[j].value3; | 386 comp->steps[i].value3 = comp->steps[j].value3; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 comp->steps[j].indexExtra = t; | 444 comp->steps[j].indexExtra = t; |
| 440 t = comp->steps[i].lenExtra; | 445 t = comp->steps[i].lenExtra; |
| 441 comp->steps[i].lenExtra = comp->steps[j].lenExtra; | 446 comp->steps[i].lenExtra = comp->steps[j].lenExtra; |
| 442 comp->steps[j].lenExtra = t; | 447 comp->steps[j].lenExtra = t; |
| 443 j--; | 448 j--; |
| 444 i++; | 449 i++; |
| 445 } | 450 } |
| 446 xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0); | 451 xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0); |
| 447 | 452 |
| 448 /* | 453 /* |
| 449 * detect consecutive XSLT_OP_PREDICATE indicating a direct | 454 * Detect consecutive XSLT_OP_PREDICATE and predicates on ops which |
| 450 * matching should be done. | 455 * haven't been optimized yet indicating a direct matching should be done. |
| 451 */ | 456 */ |
| 452 for (i = 0;i < comp->nbStep - 1;i++) { | 457 for (i = 0;i < comp->nbStep - 1;i++) { |
| 453 if ((comp->steps[i].op == XSLT_OP_PREDICATE) && | 458 xsltOp op = comp->steps[i].op; |
| 459 |
| 460 if ((op != XSLT_OP_ELEM) && |
| 461 (op != XSLT_OP_ALL) && |
| 454 (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) { | 462 (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) { |
| 455 | 463 |
| 456 comp->direct = 1; | 464 comp->direct = 1; |
| 457 if (comp->pattern[0] != '/') { | 465 if (comp->pattern[0] != '/') { |
| 458 xmlChar *query; | 466 xmlChar *query; |
| 459 | 467 |
| 460 query = xmlStrdup((const xmlChar *)"//"); | 468 query = xmlStrdup((const xmlChar *)"//"); |
| 461 query = xmlStrcat(query, comp->pattern); | 469 query = xmlStrcat(query, comp->pattern); |
| 462 | 470 |
| 463 xmlFree((xmlChar *) comp->pattern); | 471 xmlFree((xmlChar *) comp->pattern); |
| 464 comp->pattern = query; | 472 comp->pattern = query; |
| 465 } | 473 } |
| 466 break; | 474 break; |
| 467 } | 475 } |
| 468 } | 476 } |
| 469 } | 477 } |
| 470 | 478 |
| 471 /************************************************************************ | 479 /************************************************************************ |
| 472 * » » » » » » » » » * | 480 *» » » » » » » » » * |
| 473 * » » The interpreter for the precompiled patterns» » * | 481 *» » The interpreter for the precompiled patterns» » * |
| 474 * » » » » » » » » » * | 482 *» » » » » » » » » * |
| 475 ************************************************************************/ | 483 ************************************************************************/ |
| 476 | 484 |
| 477 static int | 485 static int |
| 478 xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states, | 486 xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states, |
| 479 int step, xmlNodePtr node) { | 487 int step, xmlNodePtr node) { |
| 480 if ((states->states == NULL) || (states->maxstates <= 0)) { | 488 if ((states->states == NULL) || (states->maxstates <= 0)) { |
| 481 states->maxstates = 4; | 489 states->maxstates = 4; |
| 482 states->nbstates = 0; | 490 states->nbstates = 0; |
| 483 states->states = xmlMalloc(4 * sizeof(xsltStepState)); | 491 states->states = xmlMalloc(4 * sizeof(xsltStepState)); |
| 484 } | 492 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 isRVT = 1; | 541 isRVT = 1; |
| 534 else | 542 else |
| 535 isRVT = 0; | 543 isRVT = 0; |
| 536 sel = &comp->steps[0]; /* store extra in first step arbitrarily */ | 544 sel = &comp->steps[0]; /* store extra in first step arbitrarily */ |
| 537 | 545 |
| 538 prevdoc = (xmlDocPtr) | 546 prevdoc = (xmlDocPtr) |
| 539 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); | 547 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); |
| 540 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); | 548 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); |
| 541 list = (xmlXPathObjectPtr) | 549 list = (xmlXPathObjectPtr) |
| 542 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra); | 550 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra); |
| 543 | 551 |
| 544 if ((list == NULL) || (prevdoc != doc)) { | 552 if ((list == NULL) || (prevdoc != doc)) { |
| 545 xmlXPathObjectPtr newlist; | 553 xmlXPathObjectPtr newlist; |
| 546 xmlNodePtr parent = node->parent; | 554 xmlNodePtr parent = node->parent; |
| 547 xmlDocPtr olddoc; | 555 xmlDocPtr olddoc; |
| 548 xmlNodePtr oldnode; | 556 xmlNodePtr oldnode; |
| 549 » int oldNsNr; | 557 » int oldNsNr, oldContextSize, oldProximityPosition; |
| 550 xmlNsPtr *oldNamespaces; | 558 xmlNsPtr *oldNamespaces; |
| 551 | 559 |
| 552 oldnode = ctxt->xpathCtxt->node; | 560 oldnode = ctxt->xpathCtxt->node; |
| 553 olddoc = ctxt->xpathCtxt->doc; | 561 olddoc = ctxt->xpathCtxt->doc; |
| 554 oldNsNr = ctxt->xpathCtxt->nsNr; | 562 oldNsNr = ctxt->xpathCtxt->nsNr; |
| 555 oldNamespaces = ctxt->xpathCtxt->namespaces; | 563 oldNamespaces = ctxt->xpathCtxt->namespaces; |
| 564 oldContextSize = ctxt->xpathCtxt->contextSize; |
| 565 oldProximityPosition = ctxt->xpathCtxt->proximityPosition; |
| 556 ctxt->xpathCtxt->node = node; | 566 ctxt->xpathCtxt->node = node; |
| 557 ctxt->xpathCtxt->doc = doc; | 567 ctxt->xpathCtxt->doc = doc; |
| 558 ctxt->xpathCtxt->namespaces = nsList; | 568 ctxt->xpathCtxt->namespaces = nsList; |
| 559 ctxt->xpathCtxt->nsNr = nsNr; | 569 ctxt->xpathCtxt->nsNr = nsNr; |
| 560 newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt); | 570 newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt); |
| 561 ctxt->xpathCtxt->node = oldnode; | 571 ctxt->xpathCtxt->node = oldnode; |
| 562 ctxt->xpathCtxt->doc = olddoc; | 572 ctxt->xpathCtxt->doc = olddoc; |
| 563 ctxt->xpathCtxt->namespaces = oldNamespaces; | 573 ctxt->xpathCtxt->namespaces = oldNamespaces; |
| 564 ctxt->xpathCtxt->nsNr = oldNsNr; | 574 ctxt->xpathCtxt->nsNr = oldNsNr; |
| 575 ctxt->xpathCtxt->contextSize = oldContextSize; |
| 576 ctxt->xpathCtxt->proximityPosition = oldProximityPosition; |
| 565 if (newlist == NULL) | 577 if (newlist == NULL) |
| 566 return(-1); | 578 return(-1); |
| 567 if (newlist->type != XPATH_NODESET) { | 579 if (newlist->type != XPATH_NODESET) { |
| 568 xmlXPathFreeObject(newlist); | 580 xmlXPathFreeObject(newlist); |
| 569 return(-1); | 581 return(-1); |
| 570 } | 582 } |
| 571 ix = 0; | 583 ix = 0; |
| 572 | 584 |
| 573 if ((parent == NULL) || (node->doc == NULL) || isRVT) | 585 if ((parent == NULL) || (node->doc == NULL) || isRVT) |
| 574 nocache = 1; | 586 nocache = 1; |
| 575 » | 587 |
| 576 if (nocache == 0) { | 588 if (nocache == 0) { |
| 577 if (list != NULL) | 589 if (list != NULL) |
| 578 xmlXPathFreeObject(list); | 590 xmlXPathFreeObject(list); |
| 579 list = newlist; | 591 list = newlist; |
| 580 | 592 |
| 581 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = | 593 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = |
| 582 (void *) list; | 594 (void *) list; |
| 583 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = | 595 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = |
| 584 (void *) doc; | 596 (void *) doc; |
| 585 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = | 597 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 605 } | 617 } |
| 606 } | 618 } |
| 607 } else { | 619 } else { |
| 608 } | 620 } |
| 609 if (nocache == 1) | 621 if (nocache == 1) |
| 610 xmlXPathFreeObject(list); | 622 xmlXPathFreeObject(list); |
| 611 return(0); | 623 return(0); |
| 612 } | 624 } |
| 613 | 625 |
| 614 /** | 626 /** |
| 627 * xsltTestPredicateMatch: |
| 628 * @ctxt: a XSLT process context |
| 629 * @comp: the precompiled pattern |
| 630 * @node: a node |
| 631 * @step: the predicate step |
| 632 * @sel: the previous step |
| 633 * |
| 634 * Test whether the node matches the predicate |
| 635 * |
| 636 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure |
| 637 */ |
| 638 static int |
| 639 xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, |
| 640 xmlNodePtr node, xsltStepOpPtr step, |
| 641 xsltStepOpPtr sel) { |
| 642 xmlNodePtr oldNode; |
| 643 xmlDocPtr doc; |
| 644 int oldCS, oldCP; |
| 645 int pos = 0, len = 0; |
| 646 int isRVT; |
| 647 int match; |
| 648 |
| 649 if (step->value == NULL) |
| 650 return(0); |
| 651 if (step->comp == NULL) |
| 652 return(0); |
| 653 |
| 654 doc = node->doc; |
| 655 if (XSLT_IS_RES_TREE_FRAG(doc)) |
| 656 isRVT = 1; |
| 657 else |
| 658 isRVT = 0; |
| 659 |
| 660 /* |
| 661 * Recompute contextSize and proximityPosition. |
| 662 * |
| 663 * TODO: Make this work for additional ops. Currently, only XSLT_OP_ELEM |
| 664 * and XSLT_OP_ALL are supported. |
| 665 */ |
| 666 oldCS = ctxt->xpathCtxt->contextSize; |
| 667 oldCP = ctxt->xpathCtxt->proximityPosition; |
| 668 if ((sel != NULL) && |
| 669 (sel->op == XSLT_OP_ELEM) && |
| 670 (sel->value != NULL) && |
| 671 (node->type == XML_ELEMENT_NODE) && |
| 672 (node->parent != NULL)) { |
| 673 xmlNodePtr previous; |
| 674 int nocache = 0; |
| 675 |
| 676 previous = (xmlNodePtr) |
| 677 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); |
| 678 if ((previous != NULL) && |
| 679 (previous->parent == node->parent)) { |
| 680 /* |
| 681 * just walk back to adjust the index |
| 682 */ |
| 683 int indx = 0; |
| 684 xmlNodePtr sibling = node; |
| 685 |
| 686 while (sibling != NULL) { |
| 687 if (sibling == previous) |
| 688 break; |
| 689 if ((sibling->type == XML_ELEMENT_NODE) && |
| 690 (previous->name != NULL) && |
| 691 (sibling->name != NULL) && |
| 692 (previous->name[0] == sibling->name[0]) && |
| 693 (xmlStrEqual(previous->name, sibling->name))) |
| 694 { |
| 695 if ((sel->value2 == NULL) || |
| 696 ((sibling->ns != NULL) && |
| 697 (xmlStrEqual(sel->value2, sibling->ns->href)))) |
| 698 indx++; |
| 699 } |
| 700 sibling = sibling->prev; |
| 701 } |
| 702 if (sibling == NULL) { |
| 703 /* hum going backward in document order ... */ |
| 704 indx = 0; |
| 705 sibling = node; |
| 706 while (sibling != NULL) { |
| 707 if (sibling == previous) |
| 708 break; |
| 709 if ((sibling->type == XML_ELEMENT_NODE) && |
| 710 (previous->name != NULL) && |
| 711 (sibling->name != NULL) && |
| 712 (previous->name[0] == sibling->name[0]) && |
| 713 (xmlStrEqual(previous->name, sibling->name))) |
| 714 { |
| 715 if ((sel->value2 == NULL) || |
| 716 ((sibling->ns != NULL) && |
| 717 (xmlStrEqual(sel->value2, |
| 718 sibling->ns->href)))) |
| 719 { |
| 720 indx--; |
| 721 } |
| 722 } |
| 723 sibling = sibling->next; |
| 724 } |
| 725 } |
| 726 if (sibling != NULL) { |
| 727 pos = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) + indx; |
| 728 /* |
| 729 * If the node is in a Value Tree we need to |
| 730 * save len, but cannot cache the node! |
| 731 * (bugs 153137 and 158840) |
| 732 */ |
| 733 if (node->doc != NULL) { |
| 734 len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival); |
| 735 if (!isRVT) { |
| 736 XSLT_RUNTIME_EXTRA(ctxt, |
| 737 sel->previousExtra, ptr) = node; |
| 738 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos; |
| 739 } |
| 740 } |
| 741 } else |
| 742 pos = 0; |
| 743 } else { |
| 744 /* |
| 745 * recompute the index |
| 746 */ |
| 747 xmlNodePtr parent = node->parent; |
| 748 xmlNodePtr siblings = NULL; |
| 749 |
| 750 if (parent) siblings = parent->children; |
| 751 |
| 752 while (siblings != NULL) { |
| 753 if (siblings->type == XML_ELEMENT_NODE) { |
| 754 if (siblings == node) { |
| 755 len++; |
| 756 pos = len; |
| 757 } else if ((node->name != NULL) && |
| 758 (siblings->name != NULL) && |
| 759 (node->name[0] == siblings->name[0]) && |
| 760 (xmlStrEqual(node->name, siblings->name))) { |
| 761 if ((sel->value2 == NULL) || |
| 762 ((siblings->ns != NULL) && |
| 763 (xmlStrEqual(sel->value2, siblings->ns->href)))) |
| 764 len++; |
| 765 } |
| 766 } |
| 767 siblings = siblings->next; |
| 768 } |
| 769 if ((parent == NULL) || (node->doc == NULL)) |
| 770 nocache = 1; |
| 771 else { |
| 772 while (parent->parent != NULL) |
| 773 parent = parent->parent; |
| 774 if (((parent->type != XML_DOCUMENT_NODE) && |
| 775 (parent->type != XML_HTML_DOCUMENT_NODE)) || |
| 776 (parent != (xmlNodePtr) node->doc)) |
| 777 nocache = 1; |
| 778 } |
| 779 } |
| 780 if (pos != 0) { |
| 781 ctxt->xpathCtxt->contextSize = len; |
| 782 ctxt->xpathCtxt->proximityPosition = pos; |
| 783 /* |
| 784 * If the node is in a Value Tree we cannot |
| 785 * cache it ! |
| 786 */ |
| 787 if ((!isRVT) && (node->doc != NULL) && |
| 788 (nocache == 0)) { |
| 789 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node; |
| 790 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos; |
| 791 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len; |
| 792 } |
| 793 } |
| 794 } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) && |
| 795 (node->type == XML_ELEMENT_NODE)) { |
| 796 xmlNodePtr previous; |
| 797 int nocache = 0; |
| 798 |
| 799 previous = (xmlNodePtr) |
| 800 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); |
| 801 if ((previous != NULL) && |
| 802 (previous->parent == node->parent)) { |
| 803 /* |
| 804 * just walk back to adjust the index |
| 805 */ |
| 806 int indx = 0; |
| 807 xmlNodePtr sibling = node; |
| 808 |
| 809 while (sibling != NULL) { |
| 810 if (sibling == previous) |
| 811 break; |
| 812 if (sibling->type == XML_ELEMENT_NODE) |
| 813 indx++; |
| 814 sibling = sibling->prev; |
| 815 } |
| 816 if (sibling == NULL) { |
| 817 /* hum going backward in document order ... */ |
| 818 indx = 0; |
| 819 sibling = node; |
| 820 while (sibling != NULL) { |
| 821 if (sibling == previous) |
| 822 break; |
| 823 if (sibling->type == XML_ELEMENT_NODE) |
| 824 indx--; |
| 825 sibling = sibling->next; |
| 826 } |
| 827 } |
| 828 if (sibling != NULL) { |
| 829 pos = XSLT_RUNTIME_EXTRA(ctxt, |
| 830 sel->indexExtra, ival) + indx; |
| 831 /* |
| 832 * If the node is in a Value Tree we cannot |
| 833 * cache it ! |
| 834 */ |
| 835 if ((node->doc != NULL) && !isRVT) { |
| 836 len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival); |
| 837 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node; |
| 838 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos; |
| 839 } |
| 840 } else |
| 841 pos = 0; |
| 842 } else { |
| 843 /* |
| 844 * recompute the index |
| 845 */ |
| 846 xmlNodePtr parent = node->parent; |
| 847 xmlNodePtr siblings = NULL; |
| 848 |
| 849 if (parent) siblings = parent->children; |
| 850 |
| 851 while (siblings != NULL) { |
| 852 if (siblings->type == XML_ELEMENT_NODE) { |
| 853 len++; |
| 854 if (siblings == node) { |
| 855 pos = len; |
| 856 } |
| 857 } |
| 858 siblings = siblings->next; |
| 859 } |
| 860 if ((parent == NULL) || (node->doc == NULL)) |
| 861 nocache = 1; |
| 862 else { |
| 863 while (parent->parent != NULL) |
| 864 parent = parent->parent; |
| 865 if (((parent->type != XML_DOCUMENT_NODE) && |
| 866 (parent->type != XML_HTML_DOCUMENT_NODE)) || |
| 867 (parent != (xmlNodePtr) node->doc)) |
| 868 nocache = 1; |
| 869 } |
| 870 } |
| 871 if (pos != 0) { |
| 872 ctxt->xpathCtxt->contextSize = len; |
| 873 ctxt->xpathCtxt->proximityPosition = pos; |
| 874 /* |
| 875 * If the node is in a Value Tree we cannot |
| 876 * cache it ! |
| 877 */ |
| 878 if ((node->doc != NULL) && (nocache == 0) && !isRVT) { |
| 879 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node; |
| 880 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos; |
| 881 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len; |
| 882 } |
| 883 } |
| 884 } |
| 885 |
| 886 oldNode = ctxt->node; |
| 887 ctxt->node = node; |
| 888 |
| 889 match = xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, comp->nsNr); |
| 890 |
| 891 if (pos != 0) { |
| 892 ctxt->xpathCtxt->contextSize = oldCS; |
| 893 ctxt->xpathCtxt->proximityPosition = oldCP; |
| 894 } |
| 895 ctxt->node = oldNode; |
| 896 |
| 897 return match; |
| 898 } |
| 899 |
| 900 /** |
| 615 * xsltTestCompMatch: | 901 * xsltTestCompMatch: |
| 616 * @ctxt: a XSLT process context | 902 * @ctxt: a XSLT process context |
| 617 * @comp: the precompiled pattern | 903 * @comp: the precompiled pattern |
| 618 * @node: a node | 904 * @node: a node |
| 619 * @mode: the mode name or NULL | 905 * @mode: the mode name or NULL |
| 620 * @modeURI: the mode URI or NULL | 906 * @modeURI: the mode URI or NULL |
| 621 * | 907 * |
| 622 * Test whether the node matches the pattern | 908 * Test whether the node matches the pattern |
| 623 * | 909 * |
| 624 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure | 910 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure |
| 625 */ | 911 */ |
| 626 static int | 912 static int |
| 627 xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, | 913 xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, |
| 628 » xmlNodePtr node, const xmlChar *mode, | 914 » xmlNodePtr matchNode, const xmlChar *mode, |
| 629 const xmlChar *modeURI) { | 915 const xmlChar *modeURI) { |
| 630 int i; | 916 int i; |
| 917 xmlNodePtr node = matchNode; |
| 631 xsltStepOpPtr step, sel = NULL; | 918 xsltStepOpPtr step, sel = NULL; |
| 632 xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */ | 919 xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */ |
| 633 | 920 |
| 634 if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) { | 921 if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) { |
| 635 xsltTransformError(ctxt, NULL, node, | 922 xsltTransformError(ctxt, NULL, node, |
| 636 "xsltTestCompMatch: null arg\n"); | 923 "xsltTestCompMatch: null arg\n"); |
| 637 return(-1); | 924 return(-1); |
| 638 } | 925 } |
| 639 if (mode != NULL) { | 926 if (mode != NULL) { |
| 640 if (comp->mode == NULL) | 927 if (comp->mode == NULL) |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 goto rollback; | 1034 goto rollback; |
| 748 } | 1035 } |
| 749 continue; | 1036 continue; |
| 750 case XSLT_OP_ANCESTOR: | 1037 case XSLT_OP_ANCESTOR: |
| 751 /* TODO: implement coalescing of ANCESTOR/NODE ops */ | 1038 /* TODO: implement coalescing of ANCESTOR/NODE ops */ |
| 752 if (step->value == NULL) { | 1039 if (step->value == NULL) { |
| 753 step = &comp->steps[i+1]; | 1040 step = &comp->steps[i+1]; |
| 754 if (step->op == XSLT_OP_ROOT) | 1041 if (step->op == XSLT_OP_ROOT) |
| 755 goto found; | 1042 goto found; |
| 756 /* added NS, ID and KEY as a result of bug 168208 */ | 1043 /* added NS, ID and KEY as a result of bug 168208 */ |
| 757 » » if ((step->op != XSLT_OP_ELEM) && | 1044 » » if ((step->op != XSLT_OP_ELEM) && |
| 758 » » » (step->op != XSLT_OP_ALL) && | 1045 » » » (step->op != XSLT_OP_ALL) && |
| 759 (step->op != XSLT_OP_NS) && | 1046 (step->op != XSLT_OP_NS) && |
| 760 (step->op != XSLT_OP_ID) && | 1047 (step->op != XSLT_OP_ID) && |
| 761 (step->op != XSLT_OP_KEY)) | 1048 (step->op != XSLT_OP_KEY)) |
| 762 goto rollback; | 1049 goto rollback; |
| 763 } | 1050 } |
| 764 if (node == NULL) | 1051 if (node == NULL) |
| 765 goto rollback; | 1052 goto rollback; |
| 766 if ((node->type == XML_DOCUMENT_NODE) || | 1053 if ((node->type == XML_DOCUMENT_NODE) || |
| 767 (node->type == XML_HTML_DOCUMENT_NODE) || | 1054 (node->type == XML_HTML_DOCUMENT_NODE) || |
| 768 #ifdef LIBXML_DOCB_ENABLED | 1055 #ifdef LIBXML_DOCB_ENABLED |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 goto rollback; | 1125 goto rollback; |
| 839 if (!xmlStrEqual(step->value, node->ns->href)) | 1126 if (!xmlStrEqual(step->value, node->ns->href)) |
| 840 goto rollback; | 1127 goto rollback; |
| 841 } | 1128 } |
| 842 break; | 1129 break; |
| 843 case XSLT_OP_ALL: | 1130 case XSLT_OP_ALL: |
| 844 if (node->type != XML_ELEMENT_NODE) | 1131 if (node->type != XML_ELEMENT_NODE) |
| 845 goto rollback; | 1132 goto rollback; |
| 846 break; | 1133 break; |
| 847 case XSLT_OP_PREDICATE: { | 1134 case XSLT_OP_PREDICATE: { |
| 848 xmlNodePtr oldNode; | |
| 849 xmlDocPtr doc; | |
| 850 int oldCS, oldCP; | |
| 851 int pos = 0, len = 0; | |
| 852 int isRVT; | |
| 853 | |
| 854 /* | 1135 /* |
| 855 » » * when there is cascading XSLT_OP_PREDICATE, then use a | 1136 » » * When there is cascading XSLT_OP_PREDICATE or a predicate |
| 1137 » » * after an op which hasn't been optimized yet, then use a |
| 856 * direct computation approach. It's not done directly | 1138 * direct computation approach. It's not done directly |
| 857 * at the beginning of the routine to filter out as much | 1139 * at the beginning of the routine to filter out as much |
| 858 * as possible this costly computation. | 1140 * as possible this costly computation. |
| 859 */ | 1141 */ |
| 860 if (comp->direct) { | 1142 if (comp->direct) { |
| 861 if (states.states != NULL) { | 1143 if (states.states != NULL) { |
| 862 /* Free the rollback states */ | 1144 /* Free the rollback states */ |
| 863 xmlFree(states.states); | 1145 xmlFree(states.states); |
| 864 } | 1146 } |
| 865 » » return(xsltTestCompMatchDirect(ctxt, comp, node, | 1147 » » return(xsltTestCompMatchDirect(ctxt, comp, matchNode, |
| 866 » » » » » » comp->nsList, comp->nsNr)); | 1148 » » » » » » comp->nsList, comp->nsNr)); |
| 867 } | 1149 } |
| 868 | 1150 |
| 869 » » doc = node->doc; | 1151 » » if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel)) |
| 870 » » if (XSLT_IS_RES_TREE_FRAG(doc)) | 1152 » » goto rollback; |
| 871 » » isRVT = 1; | |
| 872 » » else | |
| 873 » » isRVT = 0; | |
| 874 | 1153 |
| 875 /* | |
| 876 * Depending on the last selection, one may need to | |
| 877 * recompute contextSize and proximityPosition. | |
| 878 */ | |
| 879 oldCS = ctxt->xpathCtxt->contextSize; | |
| 880 oldCP = ctxt->xpathCtxt->proximityPosition; | |
| 881 if ((sel != NULL) && | |
| 882 (sel->op == XSLT_OP_ELEM) && | |
| 883 (sel->value != NULL) && | |
| 884 (node->type == XML_ELEMENT_NODE) && | |
| 885 (node->parent != NULL)) { | |
| 886 xmlNodePtr previous; | |
| 887 int ix, nocache = 0; | |
| 888 | |
| 889 previous = (xmlNodePtr) | |
| 890 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); | |
| 891 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); | |
| 892 if ((previous != NULL) && | |
| 893 (previous->parent == node->parent)) { | |
| 894 /* | |
| 895 * just walk back to adjust the index | |
| 896 */ | |
| 897 int indx = 0; | |
| 898 xmlNodePtr sibling = node; | |
| 899 | |
| 900 while (sibling != NULL) { | |
| 901 if (sibling == previous) | |
| 902 break; | |
| 903 if ((previous->type == XML_ELEMENT_NODE) && | |
| 904 (previous->name != NULL) && | |
| 905 (sibling->name != NULL) && | |
| 906 (previous->name[0] == sibling->name[0]) && | |
| 907 (xmlStrEqual(previous->name, sibling->name))) | |
| 908 { | |
| 909 if ((sel->value2 == NULL) || | |
| 910 ((sibling->ns != NULL) && | |
| 911 (xmlStrEqual(sel->value2, | |
| 912 sibling->ns->href)))) | |
| 913 indx++; | |
| 914 } | |
| 915 sibling = sibling->prev; | |
| 916 } | |
| 917 if (sibling == NULL) { | |
| 918 /* hum going backward in document order ... */ | |
| 919 indx = 0; | |
| 920 sibling = node; | |
| 921 while (sibling != NULL) { | |
| 922 if (sibling == previous) | |
| 923 break; | |
| 924 if ((previous->type == XML_ELEMENT_NODE) && | |
| 925 (previous->name != NULL) && | |
| 926 (sibling->name != NULL) && | |
| 927 (previous->name[0] == sibling->name[0]) && | |
| 928 (xmlStrEqual(previous->name, sibling->name))
) | |
| 929 { | |
| 930 if ((sel->value2 == NULL) || | |
| 931 ((sibling->ns != NULL) && | |
| 932 (xmlStrEqual(sel->value2, | |
| 933 sibling->ns->href)))) | |
| 934 { | |
| 935 indx--; | |
| 936 } | |
| 937 } | |
| 938 sibling = sibling->next; | |
| 939 } | |
| 940 } | |
| 941 if (sibling != NULL) { | |
| 942 pos = ix + indx; | |
| 943 /* | |
| 944 * If the node is in a Value Tree we need to | |
| 945 * save len, but cannot cache the node! | |
| 946 * (bugs 153137 and 158840) | |
| 947 */ | |
| 948 if (node->doc != NULL) { | |
| 949 len = XSLT_RUNTIME_EXTRA(ctxt, | |
| 950 sel->lenExtra, ival); | |
| 951 if (!isRVT) { | |
| 952 XSLT_RUNTIME_EXTRA(ctxt, | |
| 953 sel->previousExtra, ptr) = node; | |
| 954 XSLT_RUNTIME_EXTRA(ctxt, | |
| 955 sel->indexExtra, ival) = pos; | |
| 956 } | |
| 957 } | |
| 958 ix = pos; | |
| 959 } else | |
| 960 pos = 0; | |
| 961 } else { | |
| 962 /* | |
| 963 * recompute the index | |
| 964 */ | |
| 965 xmlNodePtr parent = node->parent; | |
| 966 xmlNodePtr siblings = NULL; | |
| 967 | |
| 968 if (parent) siblings = parent->children; | |
| 969 | |
| 970 while (siblings != NULL) { | |
| 971 if (siblings->type == XML_ELEMENT_NODE) { | |
| 972 if (siblings == node) { | |
| 973 len++; | |
| 974 pos = len; | |
| 975 } else if ((node->name != NULL) && | |
| 976 (siblings->name != NULL) && | |
| 977 (node->name[0] == siblings->name[0]) && | |
| 978 (xmlStrEqual(node->name, siblings->name))) { | |
| 979 if ((sel->value2 == NULL) || | |
| 980 ((siblings->ns != NULL) && | |
| 981 (xmlStrEqual(sel->value2, | |
| 982 siblings->ns->href)))) | |
| 983 len++; | |
| 984 } | |
| 985 } | |
| 986 siblings = siblings->next; | |
| 987 } | |
| 988 if ((parent == NULL) || (node->doc == NULL)) | |
| 989 nocache = 1; | |
| 990 else { | |
| 991 while (parent->parent != NULL) | |
| 992 parent = parent->parent; | |
| 993 if (((parent->type != XML_DOCUMENT_NODE) && | |
| 994 (parent->type != XML_HTML_DOCUMENT_NODE)) || | |
| 995 (parent != (xmlNodePtr) node->doc)) | |
| 996 nocache = 1; | |
| 997 } | |
| 998 } | |
| 999 if (pos != 0) { | |
| 1000 ctxt->xpathCtxt->contextSize = len; | |
| 1001 ctxt->xpathCtxt->proximityPosition = pos; | |
| 1002 /* | |
| 1003 * If the node is in a Value Tree we cannot | |
| 1004 * cache it ! | |
| 1005 */ | |
| 1006 if ((!isRVT) && (node->doc != NULL) && | |
| 1007 (nocache == 0)) { | |
| 1008 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = | |
| 1009 node; | |
| 1010 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = | |
| 1011 pos; | |
| 1012 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = | |
| 1013 len; | |
| 1014 } | |
| 1015 } | |
| 1016 } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) && | |
| 1017 (node->type == XML_ELEMENT_NODE)) { | |
| 1018 xmlNodePtr previous; | |
| 1019 int ix, nocache = 0; | |
| 1020 | |
| 1021 previous = (xmlNodePtr) | |
| 1022 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); | |
| 1023 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); | |
| 1024 if ((previous != NULL) && | |
| 1025 (previous->parent == node->parent)) { | |
| 1026 /* | |
| 1027 * just walk back to adjust the index | |
| 1028 */ | |
| 1029 int indx = 0; | |
| 1030 xmlNodePtr sibling = node; | |
| 1031 | |
| 1032 while (sibling != NULL) { | |
| 1033 if (sibling == previous) | |
| 1034 break; | |
| 1035 if (sibling->type == XML_ELEMENT_NODE) | |
| 1036 indx++; | |
| 1037 sibling = sibling->prev; | |
| 1038 } | |
| 1039 if (sibling == NULL) { | |
| 1040 /* hum going backward in document order ... */ | |
| 1041 indx = 0; | |
| 1042 sibling = node; | |
| 1043 while (sibling != NULL) { | |
| 1044 if (sibling == previous) | |
| 1045 break; | |
| 1046 if (sibling->type == XML_ELEMENT_NODE) | |
| 1047 indx--; | |
| 1048 sibling = sibling->next; | |
| 1049 } | |
| 1050 } | |
| 1051 if (sibling != NULL) { | |
| 1052 pos = ix + indx; | |
| 1053 /* | |
| 1054 * If the node is in a Value Tree we cannot | |
| 1055 * cache it ! | |
| 1056 */ | |
| 1057 if ((node->doc != NULL) && !isRVT) { | |
| 1058 len = XSLT_RUNTIME_EXTRA(ctxt, | |
| 1059 sel->lenExtra, ival); | |
| 1060 XSLT_RUNTIME_EXTRA(ctxt, | |
| 1061 sel->previousExtra, ptr) = node; | |
| 1062 XSLT_RUNTIME_EXTRA(ctxt, | |
| 1063 sel->indexExtra, ival) = pos; | |
| 1064 } | |
| 1065 } else | |
| 1066 pos = 0; | |
| 1067 } else { | |
| 1068 /* | |
| 1069 * recompute the index | |
| 1070 */ | |
| 1071 xmlNodePtr parent = node->parent; | |
| 1072 xmlNodePtr siblings = NULL; | |
| 1073 | |
| 1074 if (parent) siblings = parent->children; | |
| 1075 | |
| 1076 while (siblings != NULL) { | |
| 1077 if (siblings->type == XML_ELEMENT_NODE) { | |
| 1078 len++; | |
| 1079 if (siblings == node) { | |
| 1080 pos = len; | |
| 1081 } | |
| 1082 } | |
| 1083 siblings = siblings->next; | |
| 1084 } | |
| 1085 if ((parent == NULL) || (node->doc == NULL)) | |
| 1086 nocache = 1; | |
| 1087 else { | |
| 1088 while (parent->parent != NULL) | |
| 1089 parent = parent->parent; | |
| 1090 if (((parent->type != XML_DOCUMENT_NODE) && | |
| 1091 (parent->type != XML_HTML_DOCUMENT_NODE)) || | |
| 1092 (parent != (xmlNodePtr) node->doc)) | |
| 1093 nocache = 1; | |
| 1094 } | |
| 1095 } | |
| 1096 if (pos != 0) { | |
| 1097 ctxt->xpathCtxt->contextSize = len; | |
| 1098 ctxt->xpathCtxt->proximityPosition = pos; | |
| 1099 /* | |
| 1100 * If the node is in a Value Tree we cannot | |
| 1101 * cache it ! | |
| 1102 */ | |
| 1103 if ((node->doc != NULL) && (nocache == 0) && !isRVT) { | |
| 1104 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = | |
| 1105 node; | |
| 1106 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = | |
| 1107 pos; | |
| 1108 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = | |
| 1109 len; | |
| 1110 } | |
| 1111 } | |
| 1112 } | |
| 1113 oldNode = ctxt->node; | |
| 1114 ctxt->node = node; | |
| 1115 | |
| 1116 if (step->value == NULL) | |
| 1117 goto wrong_index; | |
| 1118 if (step->comp == NULL) | |
| 1119 goto wrong_index; | |
| 1120 | |
| 1121 if (!xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, | |
| 1122 comp->nsNr)) | |
| 1123 goto wrong_index; | |
| 1124 | |
| 1125 if (pos != 0) { | |
| 1126 ctxt->xpathCtxt->contextSize = oldCS; | |
| 1127 ctxt->xpathCtxt->proximityPosition = oldCP; | |
| 1128 } | |
| 1129 ctxt->node = oldNode; | |
| 1130 break; | 1154 break; |
| 1131 wrong_index: | |
| 1132 if (pos != 0) { | |
| 1133 ctxt->xpathCtxt->contextSize = oldCS; | |
| 1134 ctxt->xpathCtxt->proximityPosition = oldCP; | |
| 1135 } | |
| 1136 ctxt->node = oldNode; | |
| 1137 goto rollback; | |
| 1138 } | 1155 } |
| 1139 case XSLT_OP_PI: | 1156 case XSLT_OP_PI: |
| 1140 if (node->type != XML_PI_NODE) | 1157 if (node->type != XML_PI_NODE) |
| 1141 goto rollback; | 1158 goto rollback; |
| 1142 if (step->value != NULL) { | 1159 if (step->value != NULL) { |
| 1143 if (!xmlStrEqual(step->value, node->name)) | 1160 if (!xmlStrEqual(step->value, node->name)) |
| 1144 goto rollback; | 1161 goto rollback; |
| 1145 } | 1162 } |
| 1146 break; | 1163 break; |
| 1147 case XSLT_OP_COMMENT: | 1164 case XSLT_OP_COMMENT: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 * * | 1237 * * |
| 1221 * Dedicated parser for templates * | 1238 * Dedicated parser for templates * |
| 1222 * * | 1239 * * |
| 1223 ************************************************************************/ | 1240 ************************************************************************/ |
| 1224 | 1241 |
| 1225 #define CUR (*ctxt->cur) | 1242 #define CUR (*ctxt->cur) |
| 1226 #define SKIP(val) ctxt->cur += (val) | 1243 #define SKIP(val) ctxt->cur += (val) |
| 1227 #define NXT(val) ctxt->cur[(val)] | 1244 #define NXT(val) ctxt->cur[(val)] |
| 1228 #define CUR_PTR ctxt->cur | 1245 #define CUR_PTR ctxt->cur |
| 1229 | 1246 |
| 1230 #define SKIP_BLANKS » » » » » » » \ | 1247 #define SKIP_BLANKS» » » » » » » \ |
| 1231 while (IS_BLANK_CH(CUR)) NEXT | 1248 while (IS_BLANK_CH(CUR)) NEXT |
| 1232 | 1249 |
| 1233 #define CURRENT (*ctxt->cur) | 1250 #define CURRENT (*ctxt->cur) |
| 1234 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) | 1251 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) |
| 1235 | 1252 |
| 1236 | 1253 |
| 1237 #define PUSH(op, val, val2, novar) » » » » » »
\ | 1254 #define PUSH(op, val, val2, novar)» » » » » »
\ |
| 1238 if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto e
rror; | 1255 if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto e
rror; |
| 1239 | 1256 |
| 1240 #define SWAP() »» » » » » \ | 1257 #define SWAP()» » » » » » \ |
| 1241 xsltSwapTopCompMatch(ctxt->comp); | 1258 xsltSwapTopCompMatch(ctxt->comp); |
| 1242 | 1259 |
| 1243 #define XSLT_ERROR(X) \ | 1260 #define XSLT_ERROR(X) \ |
| 1244 { xsltError(ctxt, __FILE__, __LINE__, X); \ | 1261 { xsltError(ctxt, __FILE__, __LINE__, X); \ |
| 1245 ctxt->error = (X); return; } | 1262 ctxt->error = (X); return; } |
| 1246 | 1263 |
| 1247 #define XSLT_ERROR0(X) \ | 1264 #define XSLT_ERROR0(X) \ |
| 1248 { xsltError(ctxt, __FILE__, __LINE__, X); \ | 1265 { xsltError(ctxt, __FILE__, __LINE__, X); \ |
| 1249 ctxt->error = (X); return(0); } | 1266 ctxt->error = (X); return(0); } |
| 1250 | 1267 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) { | 1391 if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) { |
| 1375 if (axis != 0) { | 1392 if (axis != 0) { |
| 1376 xsltTransformError(NULL, NULL, NULL, | 1393 xsltTransformError(NULL, NULL, NULL, |
| 1377 "xsltCompileIdKeyPattern : NodeTest expected\n"); | 1394 "xsltCompileIdKeyPattern : NodeTest expected\n"); |
| 1378 ctxt->error = 1; | 1395 ctxt->error = 1; |
| 1379 return; | 1396 return; |
| 1380 } | 1397 } |
| 1381 NEXT; | 1398 NEXT; |
| 1382 SKIP_BLANKS; | 1399 SKIP_BLANKS; |
| 1383 lit = xsltScanLiteral(ctxt); | 1400 lit = xsltScanLiteral(ctxt); |
| 1384 » if (ctxt->error) | 1401 » if (ctxt->error) { |
| 1402 » xsltTransformError(NULL, NULL, NULL, |
| 1403 » » "xsltCompileIdKeyPattern : Literal expected\n"); |
| 1385 return; | 1404 return; |
| 1405 } |
| 1386 SKIP_BLANKS; | 1406 SKIP_BLANKS; |
| 1387 if (CUR != ')') { | 1407 if (CUR != ')') { |
| 1388 xsltTransformError(NULL, NULL, NULL, | 1408 xsltTransformError(NULL, NULL, NULL, |
| 1389 "xsltCompileIdKeyPattern : ) expected\n"); | 1409 "xsltCompileIdKeyPattern : ) expected\n"); |
| 1410 xmlFree(lit); |
| 1390 ctxt->error = 1; | 1411 ctxt->error = 1; |
| 1391 return; | 1412 return; |
| 1392 } | 1413 } |
| 1393 NEXT; | 1414 NEXT; |
| 1394 PUSH(XSLT_OP_ID, lit, NULL, novar); | 1415 PUSH(XSLT_OP_ID, lit, NULL, novar); |
| 1416 lit = NULL; |
| 1395 } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) { | 1417 } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) { |
| 1396 if (axis != 0) { | 1418 if (axis != 0) { |
| 1397 xsltTransformError(NULL, NULL, NULL, | 1419 xsltTransformError(NULL, NULL, NULL, |
| 1398 "xsltCompileIdKeyPattern : NodeTest expected\n"); | 1420 "xsltCompileIdKeyPattern : NodeTest expected\n"); |
| 1399 ctxt->error = 1; | 1421 ctxt->error = 1; |
| 1400 return; | 1422 return; |
| 1401 } | 1423 } |
| 1402 NEXT; | 1424 NEXT; |
| 1403 SKIP_BLANKS; | 1425 SKIP_BLANKS; |
| 1404 lit = xsltScanLiteral(ctxt); | 1426 lit = xsltScanLiteral(ctxt); |
| 1405 » if (ctxt->error) | 1427 » if (ctxt->error) { |
| 1428 » xsltTransformError(NULL, NULL, NULL, |
| 1429 » » "xsltCompileIdKeyPattern : Literal expected\n"); |
| 1406 return; | 1430 return; |
| 1431 } |
| 1407 SKIP_BLANKS; | 1432 SKIP_BLANKS; |
| 1408 if (CUR != ',') { | 1433 if (CUR != ',') { |
| 1409 xsltTransformError(NULL, NULL, NULL, | 1434 xsltTransformError(NULL, NULL, NULL, |
| 1410 "xsltCompileIdKeyPattern : , expected\n"); | 1435 "xsltCompileIdKeyPattern : , expected\n"); |
| 1436 xmlFree(lit); |
| 1411 ctxt->error = 1; | 1437 ctxt->error = 1; |
| 1412 return; | 1438 return; |
| 1413 } | 1439 } |
| 1414 NEXT; | 1440 NEXT; |
| 1415 SKIP_BLANKS; | 1441 SKIP_BLANKS; |
| 1416 lit2 = xsltScanLiteral(ctxt); | 1442 lit2 = xsltScanLiteral(ctxt); |
| 1417 » if (ctxt->error) | 1443 » if (ctxt->error) { |
| 1444 » xsltTransformError(NULL, NULL, NULL, |
| 1445 » » "xsltCompileIdKeyPattern : Literal expected\n"); |
| 1446 » xmlFree(lit); |
| 1418 return; | 1447 return; |
| 1448 } |
| 1419 SKIP_BLANKS; | 1449 SKIP_BLANKS; |
| 1420 if (CUR != ')') { | 1450 if (CUR != ')') { |
| 1421 xsltTransformError(NULL, NULL, NULL, | 1451 xsltTransformError(NULL, NULL, NULL, |
| 1422 "xsltCompileIdKeyPattern : ) expected\n"); | 1452 "xsltCompileIdKeyPattern : ) expected\n"); |
| 1453 xmlFree(lit); |
| 1454 xmlFree(lit2); |
| 1423 ctxt->error = 1; | 1455 ctxt->error = 1; |
| 1424 return; | 1456 return; |
| 1425 } | 1457 } |
| 1426 NEXT; | 1458 NEXT; |
| 1427 /* URGENT TODO: support namespace in keys */ | 1459 /* URGENT TODO: support namespace in keys */ |
| 1428 PUSH(XSLT_OP_KEY, lit, lit2, novar); | 1460 PUSH(XSLT_OP_KEY, lit, lit2, novar); |
| 1461 lit = NULL; |
| 1462 lit2 = NULL; |
| 1429 } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) { | 1463 } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) { |
| 1430 NEXT; | 1464 NEXT; |
| 1431 SKIP_BLANKS; | 1465 SKIP_BLANKS; |
| 1432 if (CUR != ')') { | 1466 if (CUR != ')') { |
| 1433 lit = xsltScanLiteral(ctxt); | 1467 lit = xsltScanLiteral(ctxt); |
| 1434 » if (ctxt->error) | 1468 » if (ctxt->error) { |
| 1469 » » xsltTransformError(NULL, NULL, NULL, |
| 1470 » » » "xsltCompileIdKeyPattern : Literal expected\n"); |
| 1435 return; | 1471 return; |
| 1472 } |
| 1436 SKIP_BLANKS; | 1473 SKIP_BLANKS; |
| 1437 if (CUR != ')') { | 1474 if (CUR != ')') { |
| 1438 xsltTransformError(NULL, NULL, NULL, | 1475 xsltTransformError(NULL, NULL, NULL, |
| 1439 "xsltCompileIdKeyPattern : ) expected\n"); | 1476 "xsltCompileIdKeyPattern : ) expected\n"); |
| 1440 ctxt->error = 1; | 1477 ctxt->error = 1; |
| 1441 return; | 1478 return; |
| 1442 } | 1479 } |
| 1443 } | 1480 } |
| 1444 NEXT; | 1481 NEXT; |
| 1445 PUSH(XSLT_OP_PI, lit, NULL, novar); | 1482 PUSH(XSLT_OP_PI, lit, NULL, novar); |
| 1483 lit = NULL; |
| 1446 } else if (xmlStrEqual(name, (const xmlChar *)"text")) { | 1484 } else if (xmlStrEqual(name, (const xmlChar *)"text")) { |
| 1447 NEXT; | 1485 NEXT; |
| 1448 SKIP_BLANKS; | 1486 SKIP_BLANKS; |
| 1449 if (CUR != ')') { | 1487 if (CUR != ')') { |
| 1450 xsltTransformError(NULL, NULL, NULL, | 1488 xsltTransformError(NULL, NULL, NULL, |
| 1451 "xsltCompileIdKeyPattern : ) expected\n"); | 1489 "xsltCompileIdKeyPattern : ) expected\n"); |
| 1452 ctxt->error = 1; | 1490 ctxt->error = 1; |
| 1453 return; | 1491 return; |
| 1454 } | 1492 } |
| 1455 NEXT; | 1493 NEXT; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1486 "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n"); | 1524 "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n"); |
| 1487 ctxt->error = 1; | 1525 ctxt->error = 1; |
| 1488 return; | 1526 return; |
| 1489 } else { | 1527 } else { |
| 1490 xsltTransformError(NULL, NULL, NULL, | 1528 xsltTransformError(NULL, NULL, NULL, |
| 1491 "xsltCompileIdKeyPattern : node type\n"); | 1529 "xsltCompileIdKeyPattern : node type\n"); |
| 1492 ctxt->error = 1; | 1530 ctxt->error = 1; |
| 1493 return; | 1531 return; |
| 1494 } | 1532 } |
| 1495 error: | 1533 error: |
| 1496 if (name != NULL) | 1534 return; |
| 1497 » xmlFree(name); | |
| 1498 } | 1535 } |
| 1499 | 1536 |
| 1500 /** | 1537 /** |
| 1501 * xsltCompileStepPattern: | 1538 * xsltCompileStepPattern: |
| 1502 * @ctxt: the compilation context | 1539 * @ctxt: the compilation context |
| 1503 * @token: a posible precompiled name | 1540 * @token: a posible precompiled name |
| 1504 * @novar: flag to prohibit xslt variables from pattern | 1541 * @novar: flag to prohibit xslt variables from pattern |
| 1505 * | 1542 * |
| 1506 * Compile the XSLT StepPattern and generates a precompiled | 1543 * Compile the XSLT StepPattern and generates a precompiled |
| 1507 * form suitable for fast matching. | 1544 * form suitable for fast matching. |
| 1508 * | 1545 * |
| 1509 * [5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate* | 1546 * [5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate* |
| 1510 * [6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier | 1547 * [6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier |
| 1511 * | ('child' | 'attribute') '::' | 1548 * | ('child' | 'attribute') '::' |
| 1512 * from XPath | 1549 * from XPath |
| 1513 * [7] NodeTest ::= NameTest | 1550 * [7] NodeTest ::= NameTest |
| 1514 * | NodeType '(' ')' | 1551 * | NodeType '(' ')' |
| 1515 * | 'processing-instruction' '(' Literal ')' | 1552 * | 'processing-instruction' '(' Literal ')' |
| 1516 * [8] Predicate ::= '[' PredicateExpr ']' | 1553 * [8] Predicate ::= '[' PredicateExpr ']' |
| 1517 * [9] PredicateExpr ::= Expr | 1554 * [9] PredicateExpr ::= Expr |
| 1518 * [13] AbbreviatedAxisSpecifier ::= '@'? | 1555 * [13] AbbreviatedAxisSpecifier ::= '@'? |
| 1519 * [37] NameTest ::= '*' | NCName ':' '*' | QName | 1556 * [37] NameTest ::= '*' | NCName ':' '*' | QName |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1550 "xsltCompileStepPattern : Name expected\n"); | 1587 "xsltCompileStepPattern : Name expected\n"); |
| 1551 ctxt->error = 1; | 1588 ctxt->error = 1; |
| 1552 goto error; | 1589 goto error; |
| 1553 } | 1590 } |
| 1554 } | 1591 } |
| 1555 | 1592 |
| 1556 | 1593 |
| 1557 SKIP_BLANKS; | 1594 SKIP_BLANKS; |
| 1558 if (CUR == '(') { | 1595 if (CUR == '(') { |
| 1559 xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis); | 1596 xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis); |
| 1597 xmlFree(token); |
| 1598 token = NULL; |
| 1560 if (ctxt->error) | 1599 if (ctxt->error) |
| 1561 goto error; | 1600 goto error; |
| 1562 } else if (CUR == ':') { | 1601 } else if (CUR == ':') { |
| 1563 NEXT; | 1602 NEXT; |
| 1564 if (CUR != ':') { | 1603 if (CUR != ':') { |
| 1565 xmlChar *prefix = token; | 1604 xmlChar *prefix = token; |
| 1566 xmlNsPtr ns; | 1605 xmlNsPtr ns; |
| 1567 | 1606 |
| 1568 /* | 1607 /* |
| 1569 * This is a namespace match | 1608 * This is a namespace match |
| 1570 */ | 1609 */ |
| 1571 token = xsltScanNCName(ctxt); | 1610 token = xsltScanNCName(ctxt); |
| 1572 ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); | 1611 ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); |
| 1573 if (ns == NULL) { | 1612 if (ns == NULL) { |
| 1574 xsltTransformError(NULL, NULL, NULL, | 1613 xsltTransformError(NULL, NULL, NULL, |
| 1575 "xsltCompileStepPattern : no namespace bound to prefix %s\n", | 1614 "xsltCompileStepPattern : no namespace bound to prefix %s\n", |
| 1576 prefix); | 1615 prefix); |
| 1577 xmlFree(prefix); | 1616 xmlFree(prefix); |
| 1617 prefix=NULL; |
| 1578 ctxt->error = 1; | 1618 ctxt->error = 1; |
| 1579 goto error; | 1619 goto error; |
| 1580 } else { | 1620 } else { |
| 1581 URL = xmlStrdup(ns->href); | 1621 URL = xmlStrdup(ns->href); |
| 1582 } | 1622 } |
| 1583 xmlFree(prefix); | 1623 xmlFree(prefix); |
| 1624 prefix=NULL; |
| 1584 if (token == NULL) { | 1625 if (token == NULL) { |
| 1585 if (CUR == '*') { | 1626 if (CUR == '*') { |
| 1586 NEXT; | 1627 NEXT; |
| 1587 if (axis == AXIS_ATTRIBUTE) { | 1628 if (axis == AXIS_ATTRIBUTE) { |
| 1588 PUSH(XSLT_OP_ATTR, NULL, URL, novar); | 1629 PUSH(XSLT_OP_ATTR, NULL, URL, novar); |
| 1630 URL = NULL; |
| 1589 } | 1631 } |
| 1590 else { | 1632 else { |
| 1591 PUSH(XSLT_OP_NS, URL, NULL, novar); | 1633 PUSH(XSLT_OP_NS, URL, NULL, novar); |
| 1634 URL = NULL; |
| 1592 } | 1635 } |
| 1593 } else { | 1636 } else { |
| 1594 xsltTransformError(NULL, NULL, NULL, | 1637 xsltTransformError(NULL, NULL, NULL, |
| 1595 "xsltCompileStepPattern : Name expected\n"); | 1638 "xsltCompileStepPattern : Name expected\n"); |
| 1596 ctxt->error = 1; | 1639 ctxt->error = 1; |
| 1597 goto error; | 1640 goto error; |
| 1598 } | 1641 } |
| 1599 } else { | 1642 } else { |
| 1600 if (axis == AXIS_ATTRIBUTE) { | 1643 if (axis == AXIS_ATTRIBUTE) { |
| 1601 PUSH(XSLT_OP_ATTR, token, URL, novar); | 1644 PUSH(XSLT_OP_ATTR, token, URL, novar); |
| 1645 token = NULL; |
| 1646 URL = NULL; |
| 1602 } | 1647 } |
| 1603 else { | 1648 else { |
| 1604 PUSH(XSLT_OP_ELEM, token, URL, novar); | 1649 PUSH(XSLT_OP_ELEM, token, URL, novar); |
| 1650 token = NULL; |
| 1651 URL = NULL; |
| 1605 } | 1652 } |
| 1606 } | 1653 } |
| 1607 } else { | 1654 } else { |
| 1608 if (axis != 0) { | 1655 if (axis != 0) { |
| 1609 xsltTransformError(NULL, NULL, NULL, | 1656 xsltTransformError(NULL, NULL, NULL, |
| 1610 "xsltCompileStepPattern : NodeTest expected\n"); | 1657 "xsltCompileStepPattern : NodeTest expected\n"); |
| 1611 ctxt->error = 1; | 1658 ctxt->error = 1; |
| 1612 goto error; | 1659 goto error; |
| 1613 } | 1660 } |
| 1614 NEXT; | 1661 NEXT; |
| 1615 if (xmlStrEqual(token, (const xmlChar *) "child")) { | 1662 if (xmlStrEqual(token, (const xmlChar *) "child")) { |
| 1616 axis = AXIS_CHILD; | 1663 axis = AXIS_CHILD; |
| 1617 } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) { | 1664 } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) { |
| 1618 axis = AXIS_ATTRIBUTE; | 1665 axis = AXIS_ATTRIBUTE; |
| 1619 } else { | 1666 } else { |
| 1620 xsltTransformError(NULL, NULL, NULL, | 1667 xsltTransformError(NULL, NULL, NULL, |
| 1621 "xsltCompileStepPattern : 'child' or 'attribute' expected\n"
); | 1668 "xsltCompileStepPattern : 'child' or 'attribute' expected\n"
); |
| 1622 ctxt->error = 1; | 1669 ctxt->error = 1; |
| 1623 goto error; | 1670 goto error; |
| 1624 } | 1671 } |
| 1625 xmlFree(token); | 1672 xmlFree(token); |
| 1673 token = NULL; |
| 1626 SKIP_BLANKS; | 1674 SKIP_BLANKS; |
| 1627 token = xsltScanNCName(ctxt); | 1675 token = xsltScanNCName(ctxt); |
| 1628 goto parse_node_test; | 1676 goto parse_node_test; |
| 1629 } | 1677 } |
| 1630 } else { | 1678 } else { |
| 1631 URI = xsltGetQNameURI(ctxt->elem, &token); | 1679 URI = xsltGetQNameURI(ctxt->elem, &token); |
| 1632 if (token == NULL) { | 1680 if (token == NULL) { |
| 1633 ctxt->error = 1; | 1681 ctxt->error = 1; |
| 1634 goto error; | 1682 goto error; |
| 1635 } | 1683 } |
| 1636 if (URI != NULL) | 1684 if (URI != NULL) |
| 1637 URL = xmlStrdup(URI); | 1685 URL = xmlStrdup(URI); |
| 1638 if (axis == AXIS_ATTRIBUTE) { | 1686 if (axis == AXIS_ATTRIBUTE) { |
| 1639 PUSH(XSLT_OP_ATTR, token, URL, novar); | 1687 PUSH(XSLT_OP_ATTR, token, URL, novar); |
| 1688 token = NULL; |
| 1689 URL = NULL; |
| 1640 } | 1690 } |
| 1641 else { | 1691 else { |
| 1642 PUSH(XSLT_OP_ELEM, token, URL, novar); | 1692 PUSH(XSLT_OP_ELEM, token, URL, novar); |
| 1693 token = NULL; |
| 1694 URL = NULL; |
| 1643 } | 1695 } |
| 1644 } | 1696 } |
| 1645 parse_predicate: | 1697 parse_predicate: |
| 1646 SKIP_BLANKS; | 1698 SKIP_BLANKS; |
| 1647 level = 0; | 1699 level = 0; |
| 1648 while (CUR == '[') { | 1700 while (CUR == '[') { |
| 1649 const xmlChar *q; | 1701 const xmlChar *q; |
| 1650 xmlChar *ret = NULL; | 1702 xmlChar *ret = NULL; |
| 1651 | 1703 |
| 1652 level++; | 1704 level++; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1672 NEXT; | 1724 NEXT; |
| 1673 } | 1725 } |
| 1674 if (CUR == 0) { | 1726 if (CUR == 0) { |
| 1675 xsltTransformError(NULL, NULL, NULL, | 1727 xsltTransformError(NULL, NULL, NULL, |
| 1676 "xsltCompileStepPattern : ']' expected\n"); | 1728 "xsltCompileStepPattern : ']' expected\n"); |
| 1677 ctxt->error = 1; | 1729 ctxt->error = 1; |
| 1678 return; | 1730 return; |
| 1679 } | 1731 } |
| 1680 ret = xmlStrndup(q, CUR_PTR - q); | 1732 ret = xmlStrndup(q, CUR_PTR - q); |
| 1681 PUSH(XSLT_OP_PREDICATE, ret, NULL, novar); | 1733 PUSH(XSLT_OP_PREDICATE, ret, NULL, novar); |
| 1734 ret = NULL; |
| 1682 /* push the predicate lower than local test */ | 1735 /* push the predicate lower than local test */ |
| 1683 SWAP(); | 1736 SWAP(); |
| 1684 NEXT; | 1737 NEXT; |
| 1685 SKIP_BLANKS; | 1738 SKIP_BLANKS; |
| 1686 } | 1739 } |
| 1687 return; | 1740 return; |
| 1688 error: | 1741 error: |
| 1689 if (token != NULL) | 1742 if (token != NULL) |
| 1690 xmlFree(token); | 1743 xmlFree(token); |
| 1691 if (name != NULL) | 1744 if (name != NULL) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 name = xsltScanNCName(ctxt); | 1833 name = xsltScanNCName(ctxt); |
| 1781 if (name == NULL) { | 1834 if (name == NULL) { |
| 1782 xsltTransformError(NULL, NULL, NULL, | 1835 xsltTransformError(NULL, NULL, NULL, |
| 1783 "xsltCompileLocationPathPattern : Name expected\n"); | 1836 "xsltCompileLocationPathPattern : Name expected\n"); |
| 1784 ctxt->error = 1; | 1837 ctxt->error = 1; |
| 1785 return; | 1838 return; |
| 1786 } | 1839 } |
| 1787 SKIP_BLANKS; | 1840 SKIP_BLANKS; |
| 1788 if ((CUR == '(') && !xmlXPathIsNodeType(name)) { | 1841 if ((CUR == '(') && !xmlXPathIsNodeType(name)) { |
| 1789 xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0); | 1842 xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0); |
| 1790 » if (ctxt->error) | 1843 » xmlFree(name); |
| 1791 » » return; | 1844 » name = NULL; |
| 1792 if ((CUR == '/') && (NXT(1) == '/')) { | 1845 if ((CUR == '/') && (NXT(1) == '/')) { |
| 1793 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar); | 1846 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar); |
| 1794 NEXT; | 1847 NEXT; |
| 1795 NEXT; | 1848 NEXT; |
| 1796 SKIP_BLANKS; | 1849 SKIP_BLANKS; |
| 1797 xsltCompileRelativePathPattern(ctxt, NULL, novar); | 1850 xsltCompileRelativePathPattern(ctxt, NULL, novar); |
| 1798 } else if (CUR == '/') { | 1851 } else if (CUR == '/') { |
| 1799 PUSH(XSLT_OP_PARENT, NULL, NULL, novar); | 1852 PUSH(XSLT_OP_PARENT, NULL, NULL, novar); |
| 1800 NEXT; | 1853 NEXT; |
| 1801 SKIP_BLANKS; | 1854 SKIP_BLANKS; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1859 level--; | 1912 level--; |
| 1860 else if (pattern[end] == '\'') { | 1913 else if (pattern[end] == '\'') { |
| 1861 end++; | 1914 end++; |
| 1862 while ((pattern[end] != 0) && (pattern[end] != '\'')) | 1915 while ((pattern[end] != 0) && (pattern[end] != '\'')) |
| 1863 end++; | 1916 end++; |
| 1864 } else if (pattern[end] == '"') { | 1917 } else if (pattern[end] == '"') { |
| 1865 end++; | 1918 end++; |
| 1866 while ((pattern[end] != 0) && (pattern[end] != '"')) | 1919 while ((pattern[end] != 0) && (pattern[end] != '"')) |
| 1867 end++; | 1920 end++; |
| 1868 } | 1921 } |
| 1869 if (pattern[end] == 0) | 1922 » if (pattern[end] == 0) |
| 1870 break; | 1923 » break; |
| 1871 end++; | 1924 end++; |
| 1872 } | 1925 } |
| 1873 if (current == end) { | 1926 if (current == end) { |
| 1874 xsltTransformError(NULL, NULL, node, | 1927 xsltTransformError(NULL, NULL, node, |
| 1875 "xsltCompilePattern : NULL pattern\n"); | 1928 "xsltCompilePattern : NULL pattern\n"); |
| 1876 goto error; | 1929 goto error; |
| 1877 } | 1930 } |
| 1878 element = xsltNewCompMatch(); | 1931 element = xsltNewCompMatch(); |
| 1879 if (element == NULL) { | 1932 if (element == NULL) { |
| 1880 goto error; | 1933 goto error; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 const xmlChar *name = NULL; | 2090 const xmlChar *name = NULL; |
| 2038 float priority; /* the priority */ | 2091 float priority; /* the priority */ |
| 2039 | 2092 |
| 2040 if ((style == NULL) || (cur == NULL) || (cur->match == NULL)) | 2093 if ((style == NULL) || (cur == NULL) || (cur->match == NULL)) |
| 2041 return(-1); | 2094 return(-1); |
| 2042 | 2095 |
| 2043 priority = cur->priority; | 2096 priority = cur->priority; |
| 2044 pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem, | 2097 pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem, |
| 2045 style, NULL, 1); | 2098 style, NULL, 1); |
| 2046 if (pat == NULL) | 2099 if (pat == NULL) |
| 2047 » return(-1); | 2100 » return(-1); |
| 2048 while (pat) { | 2101 while (pat) { |
| 2049 next = pat->next; | 2102 next = pat->next; |
| 2050 pat->next = NULL; | 2103 pat->next = NULL; |
| 2051 name = NULL; | 2104 name = NULL; |
| 2052 » | 2105 |
| 2053 pat->template = cur; | 2106 pat->template = cur; |
| 2054 if (mode != NULL) | 2107 if (mode != NULL) |
| 2055 pat->mode = xmlDictLookup(style->dict, mode, -1); | 2108 pat->mode = xmlDictLookup(style->dict, mode, -1); |
| 2056 if (modeURI != NULL) | 2109 if (modeURI != NULL) |
| 2057 pat->modeURI = xmlDictLookup(style->dict, modeURI, -1); | 2110 pat->modeURI = xmlDictLookup(style->dict, modeURI, -1); |
| 2058 if (priority != XSLT_PAT_NO_PRIORITY) | 2111 if (priority != XSLT_PAT_NO_PRIORITY) |
| 2059 pat->priority = priority; | 2112 pat->priority = priority; |
| 2060 | 2113 |
| 2061 /* | 2114 /* |
| 2062 * insert it in the hash table list corresponding to its lookup name | 2115 * insert it in the hash table list corresponding to its lookup name |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2429 { | 2482 { |
| 2430 /* | 2483 /* |
| 2431 * Compute all remaining keys for this document. | 2484 * Compute all remaining keys for this document. |
| 2432 * | 2485 * |
| 2433 * REVISIT TODO: I think this could be further optimized. | 2486 * REVISIT TODO: I think this could be further optimized. |
| 2434 */ | 2487 */ |
| 2435 if (xsltComputeAllKeys(ctxt, node) == -1) | 2488 if (xsltComputeAllKeys(ctxt, node) == -1) |
| 2436 goto error; | 2489 goto error; |
| 2437 | 2490 |
| 2438 switch (node->type) { | 2491 switch (node->type) { |
| 2439 » » case XML_ELEMENT_NODE:» » | 2492 » » case XML_ELEMENT_NODE: |
| 2440 if (node->psvi != NULL) keyed = 1; | 2493 if (node->psvi != NULL) keyed = 1; |
| 2441 break; | 2494 break; |
| 2442 case XML_ATTRIBUTE_NODE: | 2495 case XML_ATTRIBUTE_NODE: |
| 2443 if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1; | 2496 if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1; |
| 2444 break; | 2497 break; |
| 2445 case XML_TEXT_NODE: | 2498 case XML_TEXT_NODE: |
| 2446 case XML_CDATA_SECTION_NODE: | 2499 case XML_CDATA_SECTION_NODE: |
| 2447 case XML_COMMENT_NODE: | 2500 case XML_COMMENT_NODE: |
| 2448 » » case XML_PI_NODE:» » | 2501 » » case XML_PI_NODE: |
| 2449 if (node->psvi != NULL) keyed = 1; | 2502 if (node->psvi != NULL) keyed = 1; |
| 2450 break; | 2503 break; |
| 2451 case XML_DOCUMENT_NODE: | 2504 case XML_DOCUMENT_NODE: |
| 2452 case XML_HTML_DOCUMENT_NODE: | 2505 case XML_HTML_DOCUMENT_NODE: |
| 2453 if (((xmlDocPtr) node)->psvi != NULL) keyed = 1; | 2506 if (((xmlDocPtr) node)->psvi != NULL) keyed = 1; |
| 2454 » » break;» » | 2507 » » break; |
| 2455 default: | 2508 default: |
| 2456 break; | 2509 break; |
| 2457 } | 2510 } |
| 2458 if (keyed) | 2511 if (keyed) |
| 2459 goto keyed_match; | 2512 goto keyed_match; |
| 2460 } | 2513 } |
| 2461 if (ret != NULL) | 2514 if (ret != NULL) |
| 2462 return(ret); | 2515 return(ret); |
| 2463 | 2516 |
| 2464 /* | 2517 /* |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2504 if (style->parentMatch != NULL) | 2557 if (style->parentMatch != NULL) |
| 2505 xsltFreeCompMatchList(style->parentMatch); | 2558 xsltFreeCompMatchList(style->parentMatch); |
| 2506 if (style->textMatch != NULL) | 2559 if (style->textMatch != NULL) |
| 2507 xsltFreeCompMatchList(style->textMatch); | 2560 xsltFreeCompMatchList(style->textMatch); |
| 2508 if (style->piMatch != NULL) | 2561 if (style->piMatch != NULL) |
| 2509 xsltFreeCompMatchList(style->piMatch); | 2562 xsltFreeCompMatchList(style->piMatch); |
| 2510 if (style->commentMatch != NULL) | 2563 if (style->commentMatch != NULL) |
| 2511 xsltFreeCompMatchList(style->commentMatch); | 2564 xsltFreeCompMatchList(style->commentMatch); |
| 2512 } | 2565 } |
| 2513 | 2566 |
| OLD | NEW |