summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Wellnhofer <wellnhofer@aevum.de>2021-07-07 00:41:00 +0200
committerNick Wellnhofer <wellnhofer@aevum.de>2021-07-07 01:11:55 +0200
commitb0074eeca3c6b21b4da14fdf712b853900c51635 (patch)
tree415aacc7a171c5b1cbcfdbd0e31d824280753168
parent669407a87ba31a68a5c24d60403e24508f61fbeb (diff)
downloadlibxslt-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.c23
-rw-r--r--libxslt/xsltInternals.h3
-rw-r--r--tests/REC/test-5.5-1.out7
-rw-r--r--tests/REC/test-5.5-1.xml7
-rw-r--r--tests/REC/test-5.5-1.xsl14
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>