| Index: third_party/libxslt/libxslt/pattern.c
|
| diff --git a/third_party/libxslt/libxslt/pattern.c b/third_party/libxslt/libxslt/pattern.c
|
| index 63ec25a31b7e25d02ec6e218c6d044a52ac0dbf6..720b0cb08d0e851322323119f88517fe18255a37 100644
|
| --- a/third_party/libxslt/libxslt/pattern.c
|
| +++ b/third_party/libxslt/libxslt/pattern.c
|
| @@ -451,11 +451,14 @@ xsltReverseCompMatch(xsltParserContextPtr ctxt, xsltCompMatchPtr comp) {
|
| xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0);
|
|
|
| /*
|
| - * detect consecutive XSLT_OP_PREDICATE indicating a direct
|
| - * matching should be done.
|
| + * Detect consecutive XSLT_OP_PREDICATE and predicates on ops which
|
| + * haven't been optimized yet indicating a direct matching should be done.
|
| */
|
| for (i = 0;i < comp->nbStep - 1;i++) {
|
| - if ((comp->steps[i].op == XSLT_OP_PREDICATE) &&
|
| + xsltOp op = comp->steps[i].op;
|
| +
|
| + if ((op != XSLT_OP_ELEM) &&
|
| + (op != XSLT_OP_ALL) &&
|
| (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
|
|
|
| comp->direct = 1;
|
| @@ -621,6 +624,280 @@ xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
|
| }
|
|
|
| /**
|
| + * xsltTestPredicateMatch:
|
| + * @ctxt: a XSLT process context
|
| + * @comp: the precompiled pattern
|
| + * @node: a node
|
| + * @step: the predicate step
|
| + * @sel: the previous step
|
| + *
|
| + * Test whether the node matches the predicate
|
| + *
|
| + * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
|
| + */
|
| +static int
|
| +xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
|
| + xmlNodePtr node, xsltStepOpPtr step,
|
| + xsltStepOpPtr sel) {
|
| + xmlNodePtr oldNode;
|
| + xmlDocPtr doc;
|
| + int oldCS, oldCP;
|
| + int pos = 0, len = 0;
|
| + int isRVT;
|
| + int match;
|
| +
|
| + if (step->value == NULL)
|
| + return(0);
|
| + if (step->comp == NULL)
|
| + return(0);
|
| +
|
| + doc = node->doc;
|
| + if (XSLT_IS_RES_TREE_FRAG(doc))
|
| + isRVT = 1;
|
| + else
|
| + isRVT = 0;
|
| +
|
| + /*
|
| + * Recompute contextSize and proximityPosition.
|
| + *
|
| + * TODO: Make this work for additional ops. Currently, only XSLT_OP_ELEM
|
| + * and XSLT_OP_ALL are supported.
|
| + */
|
| + oldCS = ctxt->xpathCtxt->contextSize;
|
| + oldCP = ctxt->xpathCtxt->proximityPosition;
|
| + if ((sel != NULL) &&
|
| + (sel->op == XSLT_OP_ELEM) &&
|
| + (sel->value != NULL) &&
|
| + (node->type == XML_ELEMENT_NODE) &&
|
| + (node->parent != NULL)) {
|
| + xmlNodePtr previous;
|
| + int nocache = 0;
|
| +
|
| + previous = (xmlNodePtr)
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
|
| + if ((previous != NULL) &&
|
| + (previous->parent == node->parent)) {
|
| + /*
|
| + * just walk back to adjust the index
|
| + */
|
| + int indx = 0;
|
| + xmlNodePtr sibling = node;
|
| +
|
| + while (sibling != NULL) {
|
| + if (sibling == previous)
|
| + break;
|
| + if ((sibling->type == XML_ELEMENT_NODE) &&
|
| + (previous->name != NULL) &&
|
| + (sibling->name != NULL) &&
|
| + (previous->name[0] == sibling->name[0]) &&
|
| + (xmlStrEqual(previous->name, sibling->name)))
|
| + {
|
| + if ((sel->value2 == NULL) ||
|
| + ((sibling->ns != NULL) &&
|
| + (xmlStrEqual(sel->value2, sibling->ns->href))))
|
| + indx++;
|
| + }
|
| + sibling = sibling->prev;
|
| + }
|
| + if (sibling == NULL) {
|
| + /* hum going backward in document order ... */
|
| + indx = 0;
|
| + sibling = node;
|
| + while (sibling != NULL) {
|
| + if (sibling == previous)
|
| + break;
|
| + if ((sibling->type == XML_ELEMENT_NODE) &&
|
| + (previous->name != NULL) &&
|
| + (sibling->name != NULL) &&
|
| + (previous->name[0] == sibling->name[0]) &&
|
| + (xmlStrEqual(previous->name, sibling->name)))
|
| + {
|
| + if ((sel->value2 == NULL) ||
|
| + ((sibling->ns != NULL) &&
|
| + (xmlStrEqual(sel->value2,
|
| + sibling->ns->href))))
|
| + {
|
| + indx--;
|
| + }
|
| + }
|
| + sibling = sibling->next;
|
| + }
|
| + }
|
| + if (sibling != NULL) {
|
| + pos = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) + indx;
|
| + /*
|
| + * If the node is in a Value Tree we need to
|
| + * save len, but cannot cache the node!
|
| + * (bugs 153137 and 158840)
|
| + */
|
| + if (node->doc != NULL) {
|
| + len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
|
| + if (!isRVT) {
|
| + XSLT_RUNTIME_EXTRA(ctxt,
|
| + sel->previousExtra, ptr) = node;
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
|
| + }
|
| + }
|
| + } else
|
| + pos = 0;
|
| + } else {
|
| + /*
|
| + * recompute the index
|
| + */
|
| + xmlNodePtr parent = node->parent;
|
| + xmlNodePtr siblings = NULL;
|
| +
|
| + if (parent) siblings = parent->children;
|
| +
|
| + while (siblings != NULL) {
|
| + if (siblings->type == XML_ELEMENT_NODE) {
|
| + if (siblings == node) {
|
| + len++;
|
| + pos = len;
|
| + } else if ((node->name != NULL) &&
|
| + (siblings->name != NULL) &&
|
| + (node->name[0] == siblings->name[0]) &&
|
| + (xmlStrEqual(node->name, siblings->name))) {
|
| + if ((sel->value2 == NULL) ||
|
| + ((siblings->ns != NULL) &&
|
| + (xmlStrEqual(sel->value2, siblings->ns->href))))
|
| + len++;
|
| + }
|
| + }
|
| + siblings = siblings->next;
|
| + }
|
| + if ((parent == NULL) || (node->doc == NULL))
|
| + nocache = 1;
|
| + else {
|
| + while (parent->parent != NULL)
|
| + parent = parent->parent;
|
| + if (((parent->type != XML_DOCUMENT_NODE) &&
|
| + (parent->type != XML_HTML_DOCUMENT_NODE)) ||
|
| + (parent != (xmlNodePtr) node->doc))
|
| + nocache = 1;
|
| + }
|
| + }
|
| + if (pos != 0) {
|
| + ctxt->xpathCtxt->contextSize = len;
|
| + ctxt->xpathCtxt->proximityPosition = pos;
|
| + /*
|
| + * If the node is in a Value Tree we cannot
|
| + * cache it !
|
| + */
|
| + if ((!isRVT) && (node->doc != NULL) &&
|
| + (nocache == 0)) {
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
|
| + }
|
| + }
|
| + } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
|
| + (node->type == XML_ELEMENT_NODE)) {
|
| + xmlNodePtr previous;
|
| + int nocache = 0;
|
| +
|
| + previous = (xmlNodePtr)
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
|
| + if ((previous != NULL) &&
|
| + (previous->parent == node->parent)) {
|
| + /*
|
| + * just walk back to adjust the index
|
| + */
|
| + int indx = 0;
|
| + xmlNodePtr sibling = node;
|
| +
|
| + while (sibling != NULL) {
|
| + if (sibling == previous)
|
| + break;
|
| + if (sibling->type == XML_ELEMENT_NODE)
|
| + indx++;
|
| + sibling = sibling->prev;
|
| + }
|
| + if (sibling == NULL) {
|
| + /* hum going backward in document order ... */
|
| + indx = 0;
|
| + sibling = node;
|
| + while (sibling != NULL) {
|
| + if (sibling == previous)
|
| + break;
|
| + if (sibling->type == XML_ELEMENT_NODE)
|
| + indx--;
|
| + sibling = sibling->next;
|
| + }
|
| + }
|
| + if (sibling != NULL) {
|
| + pos = XSLT_RUNTIME_EXTRA(ctxt,
|
| + sel->indexExtra, ival) + indx;
|
| + /*
|
| + * If the node is in a Value Tree we cannot
|
| + * cache it !
|
| + */
|
| + if ((node->doc != NULL) && !isRVT) {
|
| + len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
|
| + }
|
| + } else
|
| + pos = 0;
|
| + } else {
|
| + /*
|
| + * recompute the index
|
| + */
|
| + xmlNodePtr parent = node->parent;
|
| + xmlNodePtr siblings = NULL;
|
| +
|
| + if (parent) siblings = parent->children;
|
| +
|
| + while (siblings != NULL) {
|
| + if (siblings->type == XML_ELEMENT_NODE) {
|
| + len++;
|
| + if (siblings == node) {
|
| + pos = len;
|
| + }
|
| + }
|
| + siblings = siblings->next;
|
| + }
|
| + if ((parent == NULL) || (node->doc == NULL))
|
| + nocache = 1;
|
| + else {
|
| + while (parent->parent != NULL)
|
| + parent = parent->parent;
|
| + if (((parent->type != XML_DOCUMENT_NODE) &&
|
| + (parent->type != XML_HTML_DOCUMENT_NODE)) ||
|
| + (parent != (xmlNodePtr) node->doc))
|
| + nocache = 1;
|
| + }
|
| + }
|
| + if (pos != 0) {
|
| + ctxt->xpathCtxt->contextSize = len;
|
| + ctxt->xpathCtxt->proximityPosition = pos;
|
| + /*
|
| + * If the node is in a Value Tree we cannot
|
| + * cache it !
|
| + */
|
| + if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
|
| + XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
|
| + }
|
| + }
|
| + }
|
| +
|
| + oldNode = ctxt->node;
|
| + ctxt->node = node;
|
| +
|
| + match = xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, comp->nsNr);
|
| +
|
| + if (pos != 0) {
|
| + ctxt->xpathCtxt->contextSize = oldCS;
|
| + ctxt->xpathCtxt->proximityPosition = oldCP;
|
| + }
|
| + ctxt->node = oldNode;
|
| +
|
| + return match;
|
| +}
|
| +
|
| +/**
|
| * xsltTestCompMatch:
|
| * @ctxt: a XSLT process context
|
| * @comp: the precompiled pattern
|
| @@ -634,9 +911,10 @@ xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
|
| */
|
| static int
|
| xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
|
| - xmlNodePtr node, const xmlChar *mode,
|
| + xmlNodePtr matchNode, const xmlChar *mode,
|
| const xmlChar *modeURI) {
|
| int i;
|
| + xmlNodePtr node = matchNode;
|
| xsltStepOpPtr step, sel = NULL;
|
| xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
|
|
|
| @@ -854,14 +1132,9 @@ restart:
|
| goto rollback;
|
| break;
|
| case XSLT_OP_PREDICATE: {
|
| - xmlNodePtr oldNode;
|
| - xmlDocPtr doc;
|
| - int oldCS, oldCP;
|
| - int pos = 0, len = 0;
|
| - int isRVT;
|
| -
|
| /*
|
| - * when there is cascading XSLT_OP_PREDICATE, then use a
|
| + * When there is cascading XSLT_OP_PREDICATE or a predicate
|
| + * after an op which hasn't been optimized yet, then use a
|
| * direct computation approach. It's not done directly
|
| * at the beginning of the routine to filter out as much
|
| * as possible this costly computation.
|
| @@ -871,278 +1144,14 @@ restart:
|
| /* Free the rollback states */
|
| xmlFree(states.states);
|
| }
|
| - return(xsltTestCompMatchDirect(ctxt, comp, node,
|
| + return(xsltTestCompMatchDirect(ctxt, comp, matchNode,
|
| comp->nsList, comp->nsNr));
|
| }
|
|
|
| - doc = node->doc;
|
| - if (XSLT_IS_RES_TREE_FRAG(doc))
|
| - isRVT = 1;
|
| - else
|
| - isRVT = 0;
|
| -
|
| - /*
|
| - * Depending on the last selection, one may need to
|
| - * recompute contextSize and proximityPosition.
|
| - */
|
| - oldCS = ctxt->xpathCtxt->contextSize;
|
| - oldCP = ctxt->xpathCtxt->proximityPosition;
|
| - if ((sel != NULL) &&
|
| - (sel->op == XSLT_OP_ELEM) &&
|
| - (sel->value != NULL) &&
|
| - (node->type == XML_ELEMENT_NODE) &&
|
| - (node->parent != NULL)) {
|
| - xmlNodePtr previous;
|
| - int nocache = 0;
|
| -
|
| - previous = (xmlNodePtr)
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
|
| - if ((previous != NULL) &&
|
| - (previous->parent == node->parent)) {
|
| - /*
|
| - * just walk back to adjust the index
|
| - */
|
| - int indx = 0;
|
| - xmlNodePtr sibling = node;
|
| -
|
| - while (sibling != NULL) {
|
| - if (sibling == previous)
|
| - break;
|
| - if ((sibling->type == XML_ELEMENT_NODE) &&
|
| - (previous->name != NULL) &&
|
| - (sibling->name != NULL) &&
|
| - (previous->name[0] == sibling->name[0]) &&
|
| - (xmlStrEqual(previous->name, sibling->name)))
|
| - {
|
| - if ((sel->value2 == NULL) ||
|
| - ((sibling->ns != NULL) &&
|
| - (xmlStrEqual(sel->value2,
|
| - sibling->ns->href))))
|
| - indx++;
|
| - }
|
| - sibling = sibling->prev;
|
| - }
|
| - if (sibling == NULL) {
|
| - /* hum going backward in document order ... */
|
| - indx = 0;
|
| - sibling = node;
|
| - while (sibling != NULL) {
|
| - if (sibling == previous)
|
| - break;
|
| - if ((sibling->type == XML_ELEMENT_NODE) &&
|
| - (previous->name != NULL) &&
|
| - (sibling->name != NULL) &&
|
| - (previous->name[0] == sibling->name[0]) &&
|
| - (xmlStrEqual(previous->name, sibling->name)))
|
| - {
|
| - if ((sel->value2 == NULL) ||
|
| - ((sibling->ns != NULL) &&
|
| - (xmlStrEqual(sel->value2,
|
| - sibling->ns->href))))
|
| - {
|
| - indx--;
|
| - }
|
| - }
|
| - sibling = sibling->next;
|
| - }
|
| - }
|
| - if (sibling != NULL) {
|
| - pos = XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->indexExtra, ival) + indx;
|
| - /*
|
| - * If the node is in a Value Tree we need to
|
| - * save len, but cannot cache the node!
|
| - * (bugs 153137 and 158840)
|
| - */
|
| - if (node->doc != NULL) {
|
| - len = XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->lenExtra, ival);
|
| - if (!isRVT) {
|
| - XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->previousExtra, ptr) = node;
|
| - XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->indexExtra, ival) = pos;
|
| - }
|
| - }
|
| - } else
|
| - pos = 0;
|
| - } else {
|
| - /*
|
| - * recompute the index
|
| - */
|
| - xmlNodePtr parent = node->parent;
|
| - xmlNodePtr siblings = NULL;
|
| -
|
| - if (parent) siblings = parent->children;
|
| -
|
| - while (siblings != NULL) {
|
| - if (siblings->type == XML_ELEMENT_NODE) {
|
| - if (siblings == node) {
|
| - len++;
|
| - pos = len;
|
| - } else if ((node->name != NULL) &&
|
| - (siblings->name != NULL) &&
|
| - (node->name[0] == siblings->name[0]) &&
|
| - (xmlStrEqual(node->name, siblings->name))) {
|
| - if ((sel->value2 == NULL) ||
|
| - ((siblings->ns != NULL) &&
|
| - (xmlStrEqual(sel->value2,
|
| - siblings->ns->href))))
|
| - len++;
|
| - }
|
| - }
|
| - siblings = siblings->next;
|
| - }
|
| - if ((parent == NULL) || (node->doc == NULL))
|
| - nocache = 1;
|
| - else {
|
| - while (parent->parent != NULL)
|
| - parent = parent->parent;
|
| - if (((parent->type != XML_DOCUMENT_NODE) &&
|
| - (parent->type != XML_HTML_DOCUMENT_NODE)) ||
|
| - (parent != (xmlNodePtr) node->doc))
|
| - nocache = 1;
|
| - }
|
| - }
|
| - if (pos != 0) {
|
| - ctxt->xpathCtxt->contextSize = len;
|
| - ctxt->xpathCtxt->proximityPosition = pos;
|
| - /*
|
| - * If the node is in a Value Tree we cannot
|
| - * cache it !
|
| - */
|
| - if ((!isRVT) && (node->doc != NULL) &&
|
| - (nocache == 0)) {
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
|
| - node;
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
|
| - pos;
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =
|
| - len;
|
| - }
|
| - }
|
| - } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
|
| - (node->type == XML_ELEMENT_NODE)) {
|
| - xmlNodePtr previous;
|
| - int nocache = 0;
|
| -
|
| - previous = (xmlNodePtr)
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
|
| - if ((previous != NULL) &&
|
| - (previous->parent == node->parent)) {
|
| - /*
|
| - * just walk back to adjust the index
|
| - */
|
| - int indx = 0;
|
| - xmlNodePtr sibling = node;
|
| -
|
| - while (sibling != NULL) {
|
| - if (sibling == previous)
|
| - break;
|
| - if (sibling->type == XML_ELEMENT_NODE)
|
| - indx++;
|
| - sibling = sibling->prev;
|
| - }
|
| - if (sibling == NULL) {
|
| - /* hum going backward in document order ... */
|
| - indx = 0;
|
| - sibling = node;
|
| - while (sibling != NULL) {
|
| - if (sibling == previous)
|
| - break;
|
| - if (sibling->type == XML_ELEMENT_NODE)
|
| - indx--;
|
| - sibling = sibling->next;
|
| - }
|
| - }
|
| - if (sibling != NULL) {
|
| - pos = XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->indexExtra, ival) + indx;
|
| - /*
|
| - * If the node is in a Value Tree we cannot
|
| - * cache it !
|
| - */
|
| - if ((node->doc != NULL) && !isRVT) {
|
| - len = XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->lenExtra, ival);
|
| - XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->previousExtra, ptr) = node;
|
| - XSLT_RUNTIME_EXTRA(ctxt,
|
| - sel->indexExtra, ival) = pos;
|
| - }
|
| - } else
|
| - pos = 0;
|
| - } else {
|
| - /*
|
| - * recompute the index
|
| - */
|
| - xmlNodePtr parent = node->parent;
|
| - xmlNodePtr siblings = NULL;
|
| -
|
| - if (parent) siblings = parent->children;
|
| -
|
| - while (siblings != NULL) {
|
| - if (siblings->type == XML_ELEMENT_NODE) {
|
| - len++;
|
| - if (siblings == node) {
|
| - pos = len;
|
| - }
|
| - }
|
| - siblings = siblings->next;
|
| - }
|
| - if ((parent == NULL) || (node->doc == NULL))
|
| - nocache = 1;
|
| - else {
|
| - while (parent->parent != NULL)
|
| - parent = parent->parent;
|
| - if (((parent->type != XML_DOCUMENT_NODE) &&
|
| - (parent->type != XML_HTML_DOCUMENT_NODE)) ||
|
| - (parent != (xmlNodePtr) node->doc))
|
| - nocache = 1;
|
| - }
|
| - }
|
| - if (pos != 0) {
|
| - ctxt->xpathCtxt->contextSize = len;
|
| - ctxt->xpathCtxt->proximityPosition = pos;
|
| - /*
|
| - * If the node is in a Value Tree we cannot
|
| - * cache it !
|
| - */
|
| - if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
|
| - node;
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
|
| - pos;
|
| - XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =
|
| - len;
|
| - }
|
| - }
|
| - }
|
| - oldNode = ctxt->node;
|
| - ctxt->node = node;
|
| -
|
| - if (step->value == NULL)
|
| - goto wrong_index;
|
| - if (step->comp == NULL)
|
| - goto wrong_index;
|
| -
|
| - if (!xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList,
|
| - comp->nsNr))
|
| - goto wrong_index;
|
| + if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
|
| + goto rollback;
|
|
|
| - if (pos != 0) {
|
| - ctxt->xpathCtxt->contextSize = oldCS;
|
| - ctxt->xpathCtxt->proximityPosition = oldCP;
|
| - }
|
| - ctxt->node = oldNode;
|
| break;
|
| -wrong_index:
|
| - if (pos != 0) {
|
| - ctxt->xpathCtxt->contextSize = oldCS;
|
| - ctxt->xpathCtxt->proximityPosition = oldCP;
|
| - }
|
| - ctxt->node = oldNode;
|
| - goto rollback;
|
| }
|
| case XSLT_OP_PI:
|
| if (node->type != XML_PI_NODE)
|
| @@ -1424,6 +1433,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
|
| if (CUR != ',') {
|
| xsltTransformError(NULL, NULL, NULL,
|
| "xsltCompileIdKeyPattern : , expected\n");
|
| + xmlFree(lit);
|
| ctxt->error = 1;
|
| return;
|
| }
|
| @@ -2080,9 +2090,34 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur,
|
| const xmlChar *name = NULL;
|
| float priority; /* the priority */
|
|
|
| - if ((style == NULL) || (cur == NULL) || (cur->match == NULL))
|
| + if ((style == NULL) || (cur == NULL))
|
| return(-1);
|
|
|
| + /* Register named template */
|
| + if (cur->name != NULL) {
|
| + if (style->namedTemplates == NULL) {
|
| + style->namedTemplates = xmlHashCreate(10);
|
| + if (style->namedTemplates == NULL)
|
| + return(-1);
|
| + }
|
| + else {
|
| + void *dup = xmlHashLookup2(style->namedTemplates, cur->name,
|
| + cur->nameURI);
|
| + if (dup != NULL) {
|
| + xsltTransformError(NULL, style, NULL,
|
| + "xsl:template: error duplicate name '%s'\n",
|
| + cur->name);
|
| + style->errors++;
|
| + return(-1);
|
| + }
|
| + }
|
| +
|
| + xmlHashAddEntry2(style->namedTemplates, cur->name, cur->nameURI, cur);
|
| + }
|
| +
|
| + if (cur->match == NULL)
|
| + return(0);
|
| +
|
| priority = cur->priority;
|
| pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
|
| style, NULL, 1);
|
| @@ -2552,5 +2587,7 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) {
|
| xsltFreeCompMatchList(style->piMatch);
|
| if (style->commentMatch != NULL)
|
| xsltFreeCompMatchList(style->commentMatch);
|
| + if (style->namedTemplates != NULL)
|
| + xmlHashFree(style->namedTemplates, NULL);
|
| }
|
|
|
|
|