diff options
author | Nick Wellnhofer <wellnhofer@aevum.de> | 2021-07-07 00:41:00 +0200 |
---|---|---|
committer | Nick Wellnhofer <wellnhofer@aevum.de> | 2021-07-07 01:11:55 +0200 |
commit | b0074eeca3c6b21b4da14fdf712b853900c51635 (patch) | |
tree | 415aacc7a171c5b1cbcfdbd0e31d824280753168 | |
parent | 669407a87ba31a68a5c24d60403e24508f61fbeb (diff) | |
download | libxslt-b0074eeca3c6b21b4da14fdf712b853900c51635.tar.gz |
Fix conflict resolution for templates with same priority
The spec states in "5.5 Conflict Resolution for Template Rules":
> It is an error if this leaves more than one matching template rule.
> An XSLT processor may signal the error; if it does not signal the
> error, it must recover by choosing, from amongst the matching
> template rules that are left, the one that occurs last in the
> stylesheet.
We don't signal an error, so we must make sure to return the last
template in the stylesheet.
Fixes #55
-rw-r--r-- | libxslt/pattern.c | 23 | ||||
-rw-r--r-- | libxslt/xsltInternals.h | 3 | ||||
-rw-r--r-- | tests/REC/test-5.5-1.out | 7 | ||||
-rw-r--r-- | tests/REC/test-5.5-1.xml | 7 | ||||
-rw-r--r-- | tests/REC/test-5.5-1.xsl | 14 |
5 files changed, 50 insertions, 4 deletions
diff --git a/libxslt/pattern.c b/libxslt/pattern.c index 9ed750c4..22c68da8 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -2134,6 +2134,9 @@ xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, if ((style == NULL) || (cur == NULL)) return(-1); + if (cur->next != NULL) + cur->position = cur->next->position + 1; + /* Register named template */ if (cur->name != NULL) { if (style->namedTemplates == NULL) { @@ -2495,7 +2498,10 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, break; } while ((list != NULL) && - ((ret == NULL) || (list->priority > priority))) { + ((ret == NULL) || + (list->priority > priority) || + ((list->priority == priority) && + (list->template->position > ret->position)))) { if (xsltTestCompMatch(ctxt, list, node, ctxt->mode, ctxt->modeURI) == 1) { ret = list->template; @@ -2512,7 +2518,10 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, (node->type == XML_TEXT_NODE)) { list = curstyle->elemMatch; while ((list != NULL) && - ((ret == NULL) || (list->priority > priority))) { + ((ret == NULL) || + (list->priority > priority) || + ((list->priority == priority) && + (list->template->position > ret->position)))) { if (xsltTestCompMatch(ctxt, list, node, ctxt->mode, ctxt->modeURI) == 1) { ret = list->template; @@ -2525,7 +2534,10 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, (node->type == XML_COMMENT_NODE)) { list = curstyle->elemMatch; while ((list != NULL) && - ((ret == NULL) || (list->priority > priority))) { + ((ret == NULL) || + (list->priority > priority) || + ((list->priority == priority) && + (list->template->position > ret->position)))) { if (xsltTestCompMatch(ctxt, list, node, ctxt->mode, ctxt->modeURI) == 1) { ret = list->template; @@ -2540,7 +2552,10 @@ keyed_match: if (keyed) { list = curstyle->keyMatch; while ((list != NULL) && - ((ret == NULL) || (list->priority > priority))) { + ((ret == NULL) || + (list->priority > priority) || + ((list->priority == priority) && + (list->template->position > ret->position)))) { if (xsltTestCompMatch(ctxt, list, node, ctxt->mode, ctxt->modeURI) == 1) { ret = list->template; diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 946e43c5..14343d27 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -291,6 +291,9 @@ struct _xsltTemplate { int templMax; /* Size of the templtes stack */ xsltTemplatePtr *templCalledTab; /* templates called */ int *templCountTab; /* .. and how often */ + + /* Conflict resolution */ + int position; }; /** diff --git a/tests/REC/test-5.5-1.out b/tests/REC/test-5.5-1.out new file mode 100644 index 00000000..8f353180 --- /dev/null +++ b/tests/REC/test-5.5-1.out @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<winelist> + <wine> + <winery>Benziger</winery> + <product>Carneros</product> + </wine> +</winelist> diff --git a/tests/REC/test-5.5-1.xml b/tests/REC/test-5.5-1.xml new file mode 100644 index 00000000..874a183e --- /dev/null +++ b/tests/REC/test-5.5-1.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<winelist> + <wine grape="Chardonnay"> + <winery>Benziger</winery> + <product>Carneros</product> + </wine> +</winelist> diff --git a/tests/REC/test-5.5-1.xsl b/tests/REC/test-5.5-1.xsl new file mode 100644 index 00000000..7c00d92f --- /dev/null +++ b/tests/REC/test-5.5-1.xsl @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- transformation of the calloutlist element --> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:template match="text()"> + </xsl:template> + + <xsl:template match="@*|node()"> + <xsl:copy> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + +</xsl:stylesheet> |