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 |