summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--FEATURES342
-rw-r--r--TODO5
-rw-r--r--libxslt/imports.c4
-rw-r--r--libxslt/pattern.c130
-rw-r--r--libxslt/templates.c47
-rw-r--r--libxslt/templates.h2
-rw-r--r--libxslt/transform.c119
-rw-r--r--libxslt/xslt.c24
-rw-r--r--tests/REC/test-2.3-1.out5
-rw-r--r--tests/REC/test-2.3-1.xml3
-rw-r--r--tests/REC/test-2.3-1.xsl10
-rw-r--r--tests/REC/test-2.3-2.out5
-rw-r--r--tests/REC/test-2.3-2.xml3
-rw-r--r--tests/REC/test-2.3-2.xsl14
-rw-r--r--tests/REC/test-2.5-1.out5
-rw-r--r--tests/REC/test-2.5-1.xml1
-rw-r--r--tests/REC/test-2.5-1.xsl20
-rw-r--r--tests/REC/test-2.6.2-1.out4
-rw-r--r--tests/REC/test-2.6.2-1.xml5
-rw-r--r--tests/REC/test-2.6.2-1.xsl8
-rw-r--r--tests/REC/test-5.2-1.out4
-rw-r--r--tests/REC/test-5.2-1.xml1
-rw-r--r--tests/REC/test-5.2-1.xsl6
-rw-r--r--tests/REC/test-5.2-10.out4
-rw-r--r--tests/REC/test-5.2-10.xml5
-rw-r--r--tests/REC/test-5.2-10.xsl6
-rw-r--r--tests/REC/test-5.2-11.out8
-rw-r--r--tests/REC/test-5.2-11.xml5
-rw-r--r--tests/REC/test-5.2-11.xsl6
-rw-r--r--tests/REC/test-5.2-12.out4
-rw-r--r--tests/REC/test-5.2-12.xml5
-rw-r--r--tests/REC/test-5.2-12.xsl7
-rw-r--r--tests/REC/test-5.2-13.out8
-rw-r--r--tests/REC/test-5.2-13.xml5
-rw-r--r--tests/REC/test-5.2-13.xsl6
-rw-r--r--tests/REC/test-5.2-14.out9
-rw-r--r--tests/REC/test-5.2-14.xml6
-rw-r--r--tests/REC/test-5.2-14.xsl6
-rw-r--r--tests/REC/test-5.2-15.out4
-rw-r--r--tests/REC/test-5.2-15.xml1
-rw-r--r--tests/REC/test-5.2-15.xsl6
-rw-r--r--tests/REC/test-5.2-16.out11
-rw-r--r--tests/REC/test-5.2-16.xml9
-rw-r--r--tests/REC/test-5.2-16.xsl6
-rw-r--r--tests/REC/test-5.2-17.out2
-rw-r--r--tests/REC/test-5.2-17.xml1
-rw-r--r--tests/REC/test-5.2-17.xsl6
-rw-r--r--tests/REC/test-5.2-18.out2
-rw-r--r--tests/REC/test-5.2-18.xml1
-rw-r--r--tests/REC/test-5.2-18.xsl6
-rw-r--r--tests/REC/test-5.2-2.out4
-rw-r--r--tests/REC/test-5.2-2.xml1
-rw-r--r--tests/REC/test-5.2-2.xsl6
-rw-r--r--tests/REC/test-5.2-3.out4
-rw-r--r--tests/REC/test-5.2-3.xml1
-rw-r--r--tests/REC/test-5.2-3.xsl6
-rw-r--r--tests/REC/test-5.2-4.out4
-rw-r--r--tests/REC/test-5.2-4.xml1
-rw-r--r--tests/REC/test-5.2-4.xsl6
-rw-r--r--tests/REC/test-5.2-5.out11
-rw-r--r--tests/REC/test-5.2-5.xml8
-rw-r--r--tests/REC/test-5.2-5.xsl6
-rw-r--r--tests/REC/test-5.2-6.out4
-rw-r--r--tests/REC/test-5.2-6.xml1
-rw-r--r--tests/REC/test-5.2-6.xsl6
-rw-r--r--tests/REC/test-5.2-7.out4
-rw-r--r--tests/REC/test-5.2-7.xml1
-rw-r--r--tests/REC/test-5.2-7.xsl6
-rw-r--r--tests/REC/test-5.2-8.out4
-rw-r--r--tests/REC/test-5.2-8.xml1
-rw-r--r--tests/REC/test-5.2-8.xsl6
-rw-r--r--tests/REC/test-5.2-9.out4
-rw-r--r--tests/REC/test-5.2-9.xml1
-rw-r--r--tests/REC/test-5.2-9.xsl6
75 files changed, 815 insertions, 212 deletions
diff --git a/ChangeLog b/ChangeLog
index 57a01753..55230746 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Sat Feb 3 16:13:35 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+ * FEATURES: updated
+ * imports.c: bugfix
+ * pattern.c: lots of changes to make most patterns work
+ * templates.[ch]: added xsltEvalXPathPredicate() for predicate testing
+ * transform.c: cleanup and attribute patterns testing
+ * xslt.c: added xsltFreeStylesheetList() and now cleanup
+ the imports
+ * tests/REC/test-2.3* tests/REC/test-2.6.2*: more tests
+ * tests/REC/test-5.2-*: 18 pattern tests from the spec, all should
+ work now.
+
Fri Feb 2 11:15:24 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* FEATURES: updated
diff --git a/FEATURES b/FEATURES
index eeeda7cc..39d9fb5c 100644
--- a/FEATURES
+++ b/FEATURES
@@ -6,215 +6,237 @@
Stylesheet Constructs:
======================
-YES xsl:stylesheet
-? id = id
-NO extension-element-prefixes = tokens
-NO exclude-result-prefixes = tokens
-YES version = number
+YES xsl:stylesheet
+? id = id
+NO extension-element-prefixes = tokens
+NO exclude-result-prefixes = tokens
+YES version = number
-YES xsl:transform
-? id = id
-NO extension-element-prefixes = tokens
-NO exclude-result-prefixes = tokens
-YES version = number
+YES xsl:transform
+? id = id
+NO extension-element-prefixes = tokens
+NO exclude-result-prefixes = tokens
+YES version = number
-YES Literal Result Element as Stylesheet
+YES Literal Result Element as Stylesheet
-NO Embedding Stylesheets
+NO Embedding Stylesheets
Top Level Elements:
===================
-YES xsl:include
-YES href = uri-reference
-
-YES xsl:import
-YES href = uri-reference
-
-YES xsl:strip-space
-YES elements = tokens
-
-YES xsl:preserve-space
-YES elements = tokens
-
-YES xsl:template
-YES match = pattern
-YES name = qname
-YES priority = number
-NO mode = qname
-
-YES xsl:namespace-alias
-YES stylesheet-prefix = prefix | "#default"
-YES result-prefix = prefix | "#default"
-
-YES xsl:attribute-set
-YES name = qname
-NO use-attribute-sets = qnames
-
-YES xsl:variable
-YES name = qname
-YES select = expression
-YES Content: template
-
-YES xsl:param
-YES name = qname
-YES select = expression
-YES Content: template
-
-NO xsl:key
-NO name = qname
-NO match = pattern
-NO use = expression
-
-YES xsl:output
-YES method = "xml" | "html" | "text" | qname-but-not-ncname
-YES version = nmtoken
-YES encoding = string
-YES omit-xml-declaration = "yes" | "no"
-YES standalone = "yes" | "no"
-YES doctype-public = string
-YES doctype-system = string
-NO cdata-section-elements = qnames
-YES indent = "yes" | "no"
-YES media-type = string
+YES xsl:include
+YES href = uri-reference
+
+YES xsl:import
+YES href = uri-reference
+
+YES xsl:strip-space
+YES elements = tokens
+
+YES xsl:preserve-space
+YES elements = tokens
+
+YES xsl:template
+YES match = pattern
+YES name = qname
+YES priority = number
+NO mode = qname
+
+YES xsl:namespace-alias
+YES stylesheet-prefix = prefix | "#default"
+YES result-prefix = prefix | "#default"
+
+YES xsl:attribute-set
+YES name = qname
+NO use-attribute-sets = qnames
+
+YES xsl:variable
+YES name = qname
+YES select = expression
+YES Content: template
+
+YES xsl:param
+YES name = qname
+YES select = expression
+YES Content: template
+
+NO xsl:key
+NO name = qname
+NO match = pattern
+NO use = expression
+
+YES xsl:output
+YES method = "xml" | "html" | "text" | qname-but-not-ncname
+YES version = nmtoken
+YES encoding = string
+YES omit-xml-declaration = "yes" | "no"
+YES standalone = "yes" | "no"
+YES doctype-public = string
+YES doctype-system = string
+NO cdata-section-elements = qnames
+YES indent = "yes" | "no"
+YES media-type = string
Instructions:
=============
-YES xsl:apply-templates
-YES select = node-set-expression
-NO mode = qname
+YES xsl:apply-templates
+YES select = node-set-expression
+NO mode = qname
-NO xsl:apply-imports
+NO xsl:apply-imports
-YES xsl:call-template
-YES name = qname
+YES xsl:call-template
+YES name = qname
-YES xsl:element
-YES name = { qname }
-YES namespace = { uri-reference }
-YES use-attribute-sets = qnames
+YES xsl:element
+YES name = { qname }
+YES namespace = { uri-reference }
+YES use-attribute-sets = qnames
-YES xsl:attribute
-YES name = { qname }
-YES namespace = { uri-reference }
+YES xsl:attribute
+YES name = { qname }
+YES namespace = { uri-reference }
-YES xsl:text
-YES disable-output-escaping = "yes" | "no"
+YES xsl:text
+YES disable-output-escaping = "yes" | "no"
-YES xsl:processing-instruction
-YES name = { ncname }
+YES xsl:processing-instruction
+YES name = { ncname }
-YES xsl:comment
+YES xsl:comment
-YES xsl:copy
-YES use-attribute-sets = qnames
+YES xsl:copy
+YES use-attribute-sets = qnames
-YES xsl:value-of
-YES select = string-expression
-NO disable-output-escaping = "yes" | "no"
+YES xsl:value-of
+YES select = string-expression
+NO disable-output-escaping = "yes" | "no"
-NO xsl:number
-NO level = "single" | "multiple" | "any"
-NO count = pattern
-NO from = pattern
-NO value = number-expression
-NO format = { string }
-NO lang = { nmtoken }
-NO letter-value = { "alphabetic" | "traditional" }
-NO grouping-separator = { char }
-NO grouping-size = { number }
+NO xsl:number
+NO level = "single" | "multiple" | "any"
+NO count = pattern
+NO from = pattern
+NO value = number-expression
+NO format = { string }
+NO lang = { nmtoken }
+NO letter-value = { "alphabetic" | "traditional" }
+NO grouping-separator = { char }
+NO grouping-size = { number }
-YES xsl:for-each
-YES select = node-set-expression
+YES xsl:for-each
+YES select = node-set-expression
-YES xsl:if
-YES test = boolean-expression
+YES xsl:if
+YES test = boolean-expression
-YES xsl:choose
+YES xsl:choose
-YES xsl:when
-YES test = boolean-expression
+YES xsl:when
+YES test = boolean-expression
-YES xsl:otherwise
+YES xsl:otherwise
-YES xsl:sort
-YES select = string-expression
-NO lang = { nmtoken }
-YES data-type = { "text" | "number" | qname-but-not-ncname }
-YES order = { "ascending" | "descending" }
-NO case-order = { "upper-first" | "lower-first" }
+YES xsl:sort
+YES select = string-expression
+NO lang = { nmtoken }
+YES data-type = { "text" | "number" | qname-but-not-ncname }
+YES order = { "ascending" | "descending" }
+NO case-order = { "upper-first" | "lower-first" }
-YES xsl:variable
-YES name = qname
-YES select = expression
-YES Content: template
+YES xsl:variable
+YES name = qname
+YES select = expression
+YES Content: template
-YES xsl:param
-YES name = qname
-YES select = expression
-YES Content: template
+YES xsl:param
+YES name = qname
+YES select = expression
+YES Content: template
-YES xsl:copy-of
-YES select = expression
+YES xsl:copy-of
+YES select = expression
-YES xsl:with-param
-YES name = qname
-YES select = expression
+YES xsl:with-param
+YES name = qname
+YES select = expression
-NO xsl:decimal-format
-NO name = qname
-NO decimal-separator = char
-NO grouping-separator = char
-NO infinity = string
-NO minus-sign = char
-NO NaN = string
-NO percent = char
-NO per-mille = char
-NO zero-digit = char
-NO digit = char
-NO pattern-separator = char
+NO xsl:decimal-format
+NO name = qname
+NO decimal-separator = char
+NO grouping-separator = char
+NO infinity = string
+NO minus-sign = char
+NO NaN = string
+NO percent = char
+NO per-mille = char
+NO zero-digit = char
+NO digit = char
+NO pattern-separator = char
-YES xsl:message
-YES terminate = "yes" | "no"
+YES xsl:message
+YES terminate = "yes" | "no"
-NO xsl:fallback
+NO xsl:fallback
General:
========
-YES (w.o import) Conflict Resolution for Template Rules
+YES Conflict Resolution for Template Rules
-YES Whitespace Stripping
+YES Whitespace Stripping
-YES Built-in Template Rules
-YES match="*|/"
-YES match="text()|@*"
-YES match="processing-instruction()|comment()"
-YES Namespace
-NO Mode
+YES Built-in Template Rules
+YES match="*|/"
+YES match="text()|@*"
+YES match="processing-instruction()|comment()"
+YES Namespace
+NO Mode
-NO Extension Elements
+NO Extension Elements
-NO Extension Functions
+NO Extension Functions
-YES Attribute Value Templates
+YES Attribute Value Templates
-YES Result Tree Fragments
+YES Result Tree Fragments
Functions:
==========
-PARTIAL node-set document(object, node-set?)
-NO node-set key(string, object)
-YES string format-number(number, string, string?)
-YES node-set current()
-YES string unparsed-entity-uri(string)
-YES string generate-id(node-set?)
-YES object system-property(string)
-YES boolean element-available(string)
-YES boolean function-available(string)
+PARTIAL node-set document(object, node-set?)
+NO node-set key(string, object)
+YES string format-number(number, string, string?)
+YES node-set current()
+YES string unparsed-entity-uri(string)
+YES string generate-id(node-set?)
+YES object system-property(string)
+YES boolean element-available(string)
+YES boolean function-available(string)
+
+Patterns:
+=========
+
+YES para
+YES *
+YES chapter|appendix
+YES olist/item
+YES appendix//para
+YES /
+YES text()
+YES processing-instruction()
+YES node()
+YES id("W11")
+YES para[1]
+YES *[position()=1 and self::para]
+YES para[last()=1]
+YES items/item[position()>1]
+YES item[position() mod 2 = 1]
+YES div[@class="appendix"]//p
+YES @class
+YES @*
Daniel.Veillard@imag.fr
diff --git a/TODO b/TODO
index acc15a60..555d86cd 100644
--- a/TODO
+++ b/TODO
@@ -13,7 +13,10 @@ Design:
informations and cleaned up later ?
- seems that saving back XSLT stylesheet from a compiled form might
be a bit ugly ...
-
+
+Embedding Stylesheets:
+ - example in 2.7 would force to validate
+
Import:
-> make sure we use the cascade wherever it's needed
diff --git a/libxslt/imports.c b/libxslt/imports.c
index 44316a07..a7f4ad8c 100644
--- a/libxslt/imports.c
+++ b/libxslt/imports.c
@@ -99,8 +99,6 @@ xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
}
error:
- if (import != NULL)
- xmlFreeDoc(import);
if (uriRef != NULL)
xmlFree(uriRef);
if (base != NULL)
@@ -155,8 +153,6 @@ xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
style->doc = oldDoc;
error:
- if (include != NULL)
- xmlFreeDoc(include);
if (uriRef != NULL)
xmlFree(uriRef);
if (base != NULL)
diff --git a/libxslt/pattern.c b/libxslt/pattern.c
index 62f870a6..f7e97868 100644
--- a/libxslt/pattern.c
+++ b/libxslt/pattern.c
@@ -23,6 +23,7 @@
#include "xsltInternals.h"
#include "xsltutils.h"
#include "imports.h"
+#include "templates.h"
/* #define DEBUG_PARSING */
@@ -211,6 +212,33 @@ xsltCompMatchAdd(xsltCompMatchPtr comp, xsltOp op, xmlChar *value,
}
/**
+ * xsltSwapTopCompMatch:
+ * @comp: the compiled match expression
+ *
+ * reverse the two top steps.
+ */
+void
+xsltSwapTopCompMatch(xsltCompMatchPtr comp) {
+ int i;
+ int j = comp->nbStep - 1;
+
+ if (j > 0) {
+ register xmlChar *tmp;
+ register xsltOp op;
+ i = j - 1;
+ tmp = comp->steps[i].value;
+ comp->steps[i].value = comp->steps[j].value;
+ comp->steps[j].value = tmp;
+ tmp = comp->steps[i].value2;
+ comp->steps[i].value2 = comp->steps[j].value2;
+ comp->steps[j].value2 = tmp;
+ op = comp->steps[i].op;
+ comp->steps[i].op = comp->steps[j].op;
+ comp->steps[j].op = op;
+ }
+}
+
+/**
* xsltReverseCompMatch:
* @comp: the compiled match expression
*
@@ -247,6 +275,7 @@ xsltReverseCompMatch(xsltCompMatchPtr comp) {
/**
* xsltTestCompMatch:
+ * @ctxt: a XSLT process context
* @comp: the precompiled pattern
* @node: a node
*
@@ -255,17 +284,20 @@ xsltReverseCompMatch(xsltCompMatchPtr comp) {
* Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
*/
int
-xsltTestCompMatch(xsltCompMatchPtr comp, xmlNodePtr node) {
+xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
+ xmlNodePtr node) {
int i;
- xsltStepOpPtr step;
+ xsltStepOpPtr step, select = NULL;
- if ((comp == NULL) || (node == NULL)) {
+ if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {
xsltGenericError(xsltGenericErrorContext,
"xsltTestCompMatch: null arg\n");
return(-1);
}
for (i = 0;i < comp->nbStep;i++) {
step = &comp->steps[i];
+ if (step->op != XSLT_OP_PREDICATE)
+ select = step;
switch (step->op) {
case XSLT_OP_END:
return(1);
@@ -363,13 +395,20 @@ xsltTestCompMatch(xsltCompMatchPtr comp, xmlNodePtr node) {
break;
}
}
+ node = node->parent;
}
if (node == NULL)
return(0);
continue;
- case XSLT_OP_ID:
- TODO /* Handle IDs, might be done differently */
+ case XSLT_OP_ID: {
+ /* TODO Handle IDs decently, must be done differently */
+ xmlAttrPtr id;
+
+ id = xmlGetID(node->doc, step->value);
+ if ((id == NULL) || (id->parent != node))
+ return(0);
break;
+ }
case XSLT_OP_KEY:
TODO /* Handle Keys, might be done differently */
break;
@@ -395,13 +434,65 @@ xsltTestCompMatch(xsltCompMatchPtr comp, xmlNodePtr node) {
return(0);
}
break;
- case XSLT_OP_PREDICATE:
- TODO /* Handle Predicate */
+ case XSLT_OP_PREDICATE: {
+ xmlNodePtr oldNode;
+ int oldCS, oldCP;
+ int pos = 0, len = 0;
+ /*
+ * Depending on the last selection, one may need to
+ * recompute contextSize and proximityPosition.
+ */
+ if ((select != NULL) &&
+ (select->op == XSLT_OP_ELEM) &&
+ (select->value != NULL) &&
+ (node->type == XML_ELEMENT_NODE) &&
+ (node->parent != NULL)) {
+
+ /* TODO: cache those informations ?!? */
+ xmlNodePtr siblings = node->parent->children;
+
+ oldCS = ctxt->xpathCtxt->contextSize;
+ oldCP = ctxt->xpathCtxt->proximityPosition;
+ while (siblings != NULL) {
+ if (siblings->type == XML_ELEMENT_NODE) {
+ if (siblings == node) {
+ len++;
+ pos = len;
+ } else if (xmlStrEqual(node->name,
+ siblings->name)) {
+ len++;
+ }
+ }
+ siblings = siblings->next;
+ }
+ if (pos != 0) {
+ ctxt->xpathCtxt->contextSize = len;
+ ctxt->xpathCtxt->proximityPosition = pos;
+ }
+ }
+ oldNode = ctxt->node;
+ ctxt->node = node;
+
+ if ((step->value == NULL) ||
+ (!xsltEvalXPathPredicate(ctxt, step->value))) {
+ if (pos != 0) {
+ ctxt->xpathCtxt->contextSize = oldCS;
+ ctxt->xpathCtxt->proximityPosition = oldCP;
+ }
+ ctxt->node = oldNode;
+ return(0);
+ }
+ if (pos != 0) {
+ ctxt->xpathCtxt->contextSize = oldCS;
+ ctxt->xpathCtxt->proximityPosition = oldCP;
+ }
+ ctxt->node = oldNode;
break;
+ }
case XSLT_OP_PI:
if (node->type != XML_PI_NODE)
return(0);
- if (step->value == NULL) {
+ if (step->value != NULL) {
if (!xmlStrEqual(step->value, node->name))
return(0);
}
@@ -456,6 +547,9 @@ xsltTestCompMatch(xsltCompMatchPtr comp, xmlNodePtr node) {
#define PUSH(op, val, val2) \
if (xsltCompMatchAdd(ctxt->comp, (op), (val), (val2))) goto error;
+#define SWAP() \
+ xsltSwapTopCompMatch(ctxt->comp);
+
#define XSLT_ERROR(X) \
{ xsltError(ctxt, __FILE__, __LINE__, X); \
ctxt->error = (X); return; }
@@ -634,7 +728,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid) {
return;
}
NEXT;
- PUSH(XSLT_OP_KEY, lit, NULL);
+ PUSH(XSLT_OP_KEY, lit, lit2);
} else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
NEXT;
SKIP_BLANKS;
@@ -699,10 +793,6 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid) {
error:
if (name != NULL)
xmlFree(name);
- if (lit != NULL)
- xmlFree(lit);
- if (lit2 != NULL)
- xmlFree(lit2);
}
/**
@@ -827,9 +917,11 @@ parse_predicate:
ctxt->error = 1;
goto error;
}
- NEXT;
ret = xmlStrndup(q, CUR_PTR - q);
PUSH(XSLT_OP_PREDICATE, ret, NULL);
+ /* push the predicate lower than local test */
+ SWAP();
+ NEXT;
}
return;
error:
@@ -1113,14 +1205,15 @@ next_pattern:
case XSLT_OP_CHILD:
case XSLT_OP_PARENT:
case XSLT_OP_ANCESTOR:
- case XSLT_OP_ID:
- case XSLT_OP_KEY:
case XSLT_OP_NS:
name = pat->steps[0].value;
break;
case XSLT_OP_ROOT:
top = (xsltCompMatchPtr *) &(style->rootMatch);
break;
+ case XSLT_OP_ID:
+ case XSLT_OP_KEY:
+ /* TODO optimize ID/KEY !!! */
case XSLT_OP_ALL:
top = (xsltCompMatchPtr *) &(style->elemMatch);
break;
@@ -1290,7 +1383,7 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node) {
list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
}
while (list != NULL) {
- if (xsltTestCompMatch(list, node)) {
+ if (xsltTestCompMatch(ctxt, list, node)) {
ret = list->template;
break;
}
@@ -1341,10 +1434,11 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node) {
}
while ((list != NULL) &&
((ret == NULL) || (list->priority > ret->priority))) {
- if (xsltTestCompMatch(list, node)) {
+ if (xsltTestCompMatch(ctxt, list, node)) {
ret = list->template;
break;
}
+ list = list->next;
}
if (ret != NULL)
return(ret);
diff --git a/libxslt/templates.c b/libxslt/templates.c
index df00c2d3..e91bb10f 100644
--- a/libxslt/templates.c
+++ b/libxslt/templates.c
@@ -37,6 +37,53 @@
************************************************************************/
/**
+ * xsltEvalXPathPredicate:
+ * @ctxt: the XSLT transformation context
+ * @str: the XPath expression
+ *
+ * Process the expression using XPath and evaluate the result as
+ * an XPath predicate
+ *
+ * Returns 1 is the predicate was true, 0 otherwise
+ */
+int
+xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, const xmlChar *expr) {
+ int ret;
+ xmlXPathObjectPtr res, tmp;
+ xmlXPathParserContextPtr xpathParserCtxt;
+
+ xpathParserCtxt =
+ xmlXPathNewParserContext(expr, ctxt->xpathCtxt);
+ if (xpathParserCtxt == NULL)
+ return(NULL);
+ ctxt->xpathCtxt->node = ctxt->node;
+ xmlXPathEvalExpr(xpathParserCtxt);
+ res = valuePop(xpathParserCtxt);
+ do {
+ tmp = valuePop(xpathParserCtxt);
+ if (tmp != NULL) {
+ xmlXPathFreeObject(tmp);
+ }
+ } while (tmp != NULL);
+ if (res != NULL) {
+ ret = xmlXPathEvaluatePredicateResult(xpathParserCtxt, res);
+ xmlXPathFreeObject(res);
+#ifdef DEBUG_TEMPLATES
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsltEvalXPathPredicate: %s returns %d\n", expr, ret);
+#endif
+ } else {
+#ifdef DEBUG_TEMPLATES
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsltEvalXPathPredicate: %s failed\n", expr);
+#endif
+ ret = 0;
+ }
+ xmlXPathFreeParserContext(xpathParserCtxt);
+ return(ret);
+}
+
+/**
* xsltEvalXPathString:
* @ctxt: the XSLT transformation context
* @str: the XPath expression
diff --git a/libxslt/templates.h b/libxslt/templates.h
index 7daea117..0fdb763d 100644
--- a/libxslt/templates.h
+++ b/libxslt/templates.h
@@ -17,6 +17,8 @@
extern "C" {
#endif
+int xsltEvalXPathPredicate (xsltTransformContextPtr ctxt,
+ const xmlChar *expr);
xmlChar * xsltEvalTemplateString (xsltTransformContextPtr ctxt,
xmlNodePtr node,
xmlNodePtr parent);
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 9383bf3c..348d260f 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -824,10 +824,12 @@ error:
void
xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
xmlNodePtr copy;
+ xmlAttrPtr attrs;
xmlNodePtr delete = NULL, cur;
int strip_spaces = -1;
int nbchild = 0, oldSize;
int childno = 0, oldPos;
+ xsltTemplatePtr template;
CHECK_STOPPED;
/*
@@ -839,36 +841,56 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
case XML_ELEMENT_NODE:
break;
case XML_TEXT_NODE:
- copy = xmlCopyNode(node, 0);
- if (copy != NULL) {
- xmlAddChild(ctxt->insert, copy);
+ template = xsltGetTemplate(ctxt, node);
+ if (template) {
+ xmlNodePtr oldNode;
+
+ oldNode = ctxt->node;
+ ctxt->node = node;
+ xsltApplyOneTemplate(ctxt, node, template->content);
+ ctxt->node = oldNode;
} else {
- xsltGenericError(xsltGenericErrorContext,
- "xsltDefaultProcessOneNode: text copy failed\n");
+ copy = xmlCopyNode(node, 0);
+ if (copy != NULL) {
+ xmlAddChild(ctxt->insert, copy);
+ } else {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltDefaultProcessOneNode: text copy failed\n");
+ }
}
return;
case XML_ATTRIBUTE_NODE:
if (ctxt->insert->type == XML_ELEMENT_NODE) {
xmlAttrPtr attr = (xmlAttrPtr) node, ret, cur;
- if (attr->ns != NULL) {
- if ((!xmlStrEqual(attr->ns->href, XSLT_NAMESPACE)) &&
- (xmlStrncasecmp(attr->ns->prefix,
- (xmlChar *)"xml", 3))) {
+ template = xsltGetTemplate(ctxt, node);
+ if (template) {
+ xmlNodePtr oldNode;
+
+ oldNode = ctxt->node;
+ ctxt->node = node;
+ xsltApplyOneTemplate(ctxt, node, template->content);
+ ctxt->node = oldNode;
+ } else {
+ if (attr->ns != NULL) {
+ if ((!xmlStrEqual(attr->ns->href, XSLT_NAMESPACE)) &&
+ (xmlStrncasecmp(attr->ns->prefix,
+ (xmlChar *)"xml", 3))) {
+ ret = xmlCopyProp(ctxt->insert, attr);
+ ret->ns = xsltGetNamespace(ctxt, node, attr->ns,
+ ctxt->insert);
+ }
+ } else
ret = xmlCopyProp(ctxt->insert, attr);
- ret->ns = xsltGetNamespace(ctxt, node, attr->ns,
- ctxt->insert);
- }
- } else
- ret = xmlCopyProp(ctxt->insert, attr);
- cur = ctxt->insert->properties;
- if (cur != NULL) {
- while (cur->next != NULL)
- cur = cur->next;
- cur->next = ret;
- ret->prev = cur;
- }else
- ctxt->insert->properties = ret;
+ cur = ctxt->insert->properties;
+ if (cur != NULL) {
+ while (cur->next != NULL)
+ cur = cur->next;
+ cur->next = ret;
+ ret->prev = cur;
+ }else
+ ctxt->insert->properties = ret;
+ }
}
return;
default:
@@ -899,6 +921,10 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
case XML_ELEMENT_NODE:
nbchild++;
break;
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ nbchild++;
+ break;
default:
#ifdef DEBUG_PROCESS
xsltGenericDebug(xsltGenericDebugContext,
@@ -921,6 +947,19 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
/*
* Handling of Elements: second pass, actual processing
*/
+ attrs = node->properties;
+ while (attrs != NULL) {
+ template = xsltGetTemplate(ctxt, (xmlNodePtr) attrs);
+ if (template) {
+ xmlNodePtr oldNode;
+
+ oldNode = ctxt->node;
+ ctxt->node = node;
+ xsltApplyOneTemplate(ctxt, node, template->content);
+ ctxt->node = oldNode;
+ }
+ attrs = attrs->next;
+ }
oldSize = ctxt->xpathCtxt->contextSize;
oldPos = ctxt->xpathCtxt->proximityPosition;
cur = node->children;
@@ -936,12 +975,38 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
break;
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
- copy = xmlCopyNode(cur, 0);
- if (copy != NULL) {
- xmlAddChild(ctxt->insert, copy);
+ template = xsltGetTemplate(ctxt, cur);
+ if (template) {
+ xmlNodePtr oldNode;
+
+ oldNode = ctxt->node;
+ ctxt->node = cur;
+ ctxt->xpathCtxt->contextSize = nbchild;
+ ctxt->xpathCtxt->proximityPosition = childno;
+ xsltApplyOneTemplate(ctxt, cur, template->content);
+ ctxt->node = oldNode;
} else {
- xsltGenericError(xsltGenericErrorContext,
- "xsltDefaultProcessOneNode: text copy failed\n");
+ copy = xmlCopyNode(cur, 0);
+ if (copy != NULL) {
+ xmlAddChild(ctxt->insert, copy);
+ } else {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltDefaultProcessOneNode: text copy failed\n");
+ }
+ }
+ break;
+ case XML_PI_NODE:
+ case XML_COMMENT_NODE:
+ template = xsltGetTemplate(ctxt, cur);
+ if (template) {
+ xmlNodePtr oldNode;
+
+ oldNode = ctxt->node;
+ ctxt->node = cur;
+ ctxt->xpathCtxt->contextSize = nbchild;
+ ctxt->xpathCtxt->proximityPosition = childno;
+ xsltApplyOneTemplate(ctxt, cur, template->content);
+ ctxt->node = oldNode;
}
break;
default:
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
index eeb13dce..d4b9643f 100644
--- a/libxslt/xslt.c
+++ b/libxslt/xslt.c
@@ -252,6 +252,23 @@ xsltNewStylesheet(void) {
}
/**
+ * xsltFreeStylesheetList:
+ * @sheet: an XSLT stylesheet list
+ *
+ * Free up the memory allocated by the list @sheet
+ */
+void
+xsltFreeStylesheetList(xsltStylesheetPtr sheet) {
+ xsltStylesheetPtr next;
+
+ while (sheet != NULL) {
+ next = sheet->next;
+ xsltFreeStylesheet(sheet);
+ sheet = next;
+ }
+}
+
+/**
* xsltFreeStylesheet:
* @sheet: an XSLT stylesheet
*
@@ -282,6 +299,9 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet) {
if (sheet->doctypeSystem != NULL) xmlFree(sheet->doctypeSystem);
if (sheet->mediaType != NULL) xmlFree(sheet->mediaType);
+ if (sheet->imports != NULL)
+ xsltFreeStylesheetList(sheet->imports);
+
memset(sheet, -1, sizeof(xsltStylesheet));
xmlFree(sheet);
}
@@ -977,7 +997,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) {
xsltGenericError(xsltGenericErrorContext,
"xsl:version: only 1.0 features are supported\n");
- TODO /* set up compatibility when not XSLT 1.0 */
+ /* TODO set up compatibility when not XSLT 1.0 */
}
xmlFree(prop);
}
@@ -1120,7 +1140,7 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) {
xsltGenericError(xsltGenericErrorContext,
"xsl:version: only 1.0 features are supported\n");
- TODO /* set up compatibility when not XSLT 1.0 */
+ /* TODO set up compatibility when not XSLT 1.0 */
}
xmlFree(prop);
diff --git a/tests/REC/test-2.3-1.out b/tests/REC/test-2.3-1.out
new file mode 100644
index 00000000..4ba82bee
--- /dev/null
+++ b/tests/REC/test-2.3-1.out
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head><title>Expense Report Summary</title></head>
+<body><p>Total Amount: 1234</p></body>
+</html>
diff --git a/tests/REC/test-2.3-1.xml b/tests/REC/test-2.3-1.xml
new file mode 100644
index 00000000..12031e67
--- /dev/null
+++ b/tests/REC/test-2.3-1.xml
@@ -0,0 +1,3 @@
+<expense-report>
+<total>1234</total>
+</expense-report>
diff --git a/tests/REC/test-2.3-1.xsl b/tests/REC/test-2.3-1.xsl
new file mode 100644
index 00000000..0bf42c15
--- /dev/null
+++ b/tests/REC/test-2.3-1.xsl
@@ -0,0 +1,10 @@
+<html xsl:version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/TR/xhtml1/strict">
+ <head>
+ <title>Expense Report Summary</title>
+ </head>
+ <body>
+ <p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
+ </body>
+</html>
diff --git a/tests/REC/test-2.3-2.out b/tests/REC/test-2.3-2.out
new file mode 100644
index 00000000..4ba82bee
--- /dev/null
+++ b/tests/REC/test-2.3-2.out
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head><title>Expense Report Summary</title></head>
+<body><p>Total Amount: 1234</p></body>
+</html>
diff --git a/tests/REC/test-2.3-2.xml b/tests/REC/test-2.3-2.xml
new file mode 100644
index 00000000..12031e67
--- /dev/null
+++ b/tests/REC/test-2.3-2.xml
@@ -0,0 +1,3 @@
+<expense-report>
+<total>1234</total>
+</expense-report>
diff --git a/tests/REC/test-2.3-2.xsl b/tests/REC/test-2.3-2.xsl
new file mode 100644
index 00000000..9688a047
--- /dev/null
+++ b/tests/REC/test-2.3-2.xsl
@@ -0,0 +1,14 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/TR/xhtml1/strict">
+<xsl:template match="/">
+<html>
+ <head>
+ <title>Expense Report Summary</title>
+ </head>
+ <body>
+ <p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
+ </body>
+</html>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-2.5-1.out b/tests/REC/test-2.5-1.out
new file mode 100644
index 00000000..d4141916
--- /dev/null
+++ b/tests/REC/test-2.5-1.out
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head><title>XSLT 1.8 required</title></head>
+<body><p>Sorry, this stylesheet requires XSLT 1.8.</p></body>
+</html>
diff --git a/tests/REC/test-2.5-1.xml b/tests/REC/test-2.5-1.xml
new file mode 100644
index 00000000..69d62f2c
--- /dev/null
+++ b/tests/REC/test-2.5-1.xml
@@ -0,0 +1 @@
+<doc/>
diff --git a/tests/REC/test-2.5-1.xsl b/tests/REC/test-2.5-1.xsl
new file mode 100644
index 00000000..8121188c
--- /dev/null
+++ b/tests/REC/test-2.5-1.xsl
@@ -0,0 +1,20 @@
+<xsl:stylesheet version="1.8"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="system-property('xsl:version') >= 1.8">
+ <xsl:exciting-new-1.8-feature/>
+ </xsl:when>
+ <xsl:otherwise>
+ <html>
+ <head>
+ <title>XSLT 1.8 required</title>
+ </head>
+ <body>
+ <p>Sorry, this stylesheet requires XSLT 1.8.</p>
+ </body>
+ </html>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-2.6.2-1.out b/tests/REC/test-2.6.2-1.out
new file mode 100644
index 00000000..66fd8b63
--- /dev/null
+++ b/tests/REC/test-2.6.2-1.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<h3>The article title</h3>
+<p>first para <em>important stuff</em> ...</p>
+<p>second para ...</p>
diff --git a/tests/REC/test-2.6.2-1.xml b/tests/REC/test-2.6.2-1.xml
new file mode 100644
index 00000000..426ee7cf
--- /dev/null
+++ b/tests/REC/test-2.6.2-1.xml
@@ -0,0 +1,5 @@
+<article>
+<title>The article title</title>
+<para>first para <big>important stuff</big> ...</para>
+<para>second para ...</para>
+</article>
diff --git a/tests/REC/test-2.6.2-1.xsl b/tests/REC/test-2.6.2-1.xsl
new file mode 100644
index 00000000..122d7161
--- /dev/null
+++ b/tests/REC/test-2.6.2-1.xsl
@@ -0,0 +1,8 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:import href="article.xsl"/>
+ <xsl:import href="bigfont.xsl"/>
+ <xsl:attribute-set name="note-style">
+ <xsl:attribute name="font-style">italic</xsl:attribute>
+ </xsl:attribute-set>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-1.out b/tests/REC/test-5.2-1.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-1.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-1.xml b/tests/REC/test-5.2-1.xml
new file mode 100644
index 00000000..96441e97
--- /dev/null
+++ b/tests/REC/test-5.2-1.xml
@@ -0,0 +1 @@
+<doc><para>Failed</para></doc>
diff --git a/tests/REC/test-5.2-1.xsl b/tests/REC/test-5.2-1.xsl
new file mode 100644
index 00000000..ef80e943
--- /dev/null
+++ b/tests/REC/test-5.2-1.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="para">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-10.out b/tests/REC/test-5.2-10.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-10.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-10.xml b/tests/REC/test-5.2-10.xml
new file mode 100644
index 00000000..c4267ce0
--- /dev/null
+++ b/tests/REC/test-5.2-10.xml
@@ -0,0 +1,5 @@
+<!DOCTYPE doc [
+<!ELEMENT para (#PCDATA)>
+<!ATTLIST para label ID #IMPLIED>
+]>
+<doc><para label="W11">Failed</para></doc>
diff --git a/tests/REC/test-5.2-10.xsl b/tests/REC/test-5.2-10.xsl
new file mode 100644
index 00000000..35b91b97
--- /dev/null
+++ b/tests/REC/test-5.2-10.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match='id("W11")'>
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-11.out b/tests/REC/test-5.2-11.out
new file mode 100644
index 00000000..342571e0
--- /dev/null
+++ b/tests/REC/test-5.2-11.out
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+
+
+
+Success
+
+
+
diff --git a/tests/REC/test-5.2-11.xml b/tests/REC/test-5.2-11.xml
new file mode 100644
index 00000000..77011c0b
--- /dev/null
+++ b/tests/REC/test-5.2-11.xml
@@ -0,0 +1,5 @@
+<doc>
+<title/>
+<para>Failed</para>
+<para></para>
+</doc>
diff --git a/tests/REC/test-5.2-11.xsl b/tests/REC/test-5.2-11.xsl
new file mode 100644
index 00000000..2aa527e0
--- /dev/null
+++ b/tests/REC/test-5.2-11.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="para[1]">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-12.out b/tests/REC/test-5.2-12.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-12.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-12.xml b/tests/REC/test-5.2-12.xml
new file mode 100644
index 00000000..79ad78a7
--- /dev/null
+++ b/tests/REC/test-5.2-12.xml
@@ -0,0 +1,5 @@
+<doc>
+<para>Failed</para>
+<title/>
+<para/>
+</doc>
diff --git a/tests/REC/test-5.2-12.xsl b/tests/REC/test-5.2-12.xsl
new file mode 100644
index 00000000..e96f92be
--- /dev/null
+++ b/tests/REC/test-5.2-12.xsl
@@ -0,0 +1,7 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:strip-space elements="doc"/>
+<xsl:template match="*[position()=1 and self::para]">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-13.out b/tests/REC/test-5.2-13.out
new file mode 100644
index 00000000..342571e0
--- /dev/null
+++ b/tests/REC/test-5.2-13.out
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+
+
+
+Success
+
+
+
diff --git a/tests/REC/test-5.2-13.xml b/tests/REC/test-5.2-13.xml
new file mode 100644
index 00000000..7f7e867d
--- /dev/null
+++ b/tests/REC/test-5.2-13.xml
@@ -0,0 +1,5 @@
+<doc>
+<title/>
+<para>Failed</para>
+<title/>
+</doc>
diff --git a/tests/REC/test-5.2-13.xsl b/tests/REC/test-5.2-13.xsl
new file mode 100644
index 00000000..cae4dcc0
--- /dev/null
+++ b/tests/REC/test-5.2-13.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="para[last()=1]">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-14.out b/tests/REC/test-5.2-14.out
new file mode 100644
index 00000000..aa7fe2d4
--- /dev/null
+++ b/tests/REC/test-5.2-14.out
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+
+
+
+
+Success
+
+
+
diff --git a/tests/REC/test-5.2-14.xml b/tests/REC/test-5.2-14.xml
new file mode 100644
index 00000000..17af328d
--- /dev/null
+++ b/tests/REC/test-5.2-14.xml
@@ -0,0 +1,6 @@
+<doc>
+<items>
+<item/>
+<item>Failed</item>
+</items>
+</doc>
diff --git a/tests/REC/test-5.2-14.xsl b/tests/REC/test-5.2-14.xsl
new file mode 100644
index 00000000..4c104d03
--- /dev/null
+++ b/tests/REC/test-5.2-14.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="items/item[position()>1]">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-15.out b/tests/REC/test-5.2-15.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-15.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-15.xml b/tests/REC/test-5.2-15.xml
new file mode 100644
index 00000000..9edc446e
--- /dev/null
+++ b/tests/REC/test-5.2-15.xml
@@ -0,0 +1 @@
+<doc><item>Failed</item><item/></doc>
diff --git a/tests/REC/test-5.2-15.xsl b/tests/REC/test-5.2-15.xsl
new file mode 100644
index 00000000..40b94a7d
--- /dev/null
+++ b/tests/REC/test-5.2-15.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="item[position() mod 2 = 1]">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-16.out b/tests/REC/test-5.2-16.out
new file mode 100644
index 00000000..b91af735
--- /dev/null
+++ b/tests/REC/test-5.2-16.out
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+
+
+
+
+
+Success
+
+
+
+
diff --git a/tests/REC/test-5.2-16.xml b/tests/REC/test-5.2-16.xml
new file mode 100644
index 00000000..3900fa4a
--- /dev/null
+++ b/tests/REC/test-5.2-16.xml
@@ -0,0 +1,9 @@
+<doc>
+<p/>
+<div class="appendix">
+<para>
+<p>Failed</p>
+</para>
+</div>
+</doc>
+
diff --git a/tests/REC/test-5.2-16.xsl b/tests/REC/test-5.2-16.xsl
new file mode 100644
index 00000000..e2fbcdcd
--- /dev/null
+++ b/tests/REC/test-5.2-16.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match='div[@class="appendix"]//p'>
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-17.out b/tests/REC/test-5.2-17.out
new file mode 100644
index 00000000..77c975e6
--- /dev/null
+++ b/tests/REC/test-5.2-17.out
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+Success
diff --git a/tests/REC/test-5.2-17.xml b/tests/REC/test-5.2-17.xml
new file mode 100644
index 00000000..14552063
--- /dev/null
+++ b/tests/REC/test-5.2-17.xml
@@ -0,0 +1 @@
+<doc><para class="Failed"/></doc>
diff --git a/tests/REC/test-5.2-17.xsl b/tests/REC/test-5.2-17.xsl
new file mode 100644
index 00000000..de7a7277
--- /dev/null
+++ b/tests/REC/test-5.2-17.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="@class">
+<xsl:text>Success</xsl:text>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-18.out b/tests/REC/test-5.2-18.out
new file mode 100644
index 00000000..77c975e6
--- /dev/null
+++ b/tests/REC/test-5.2-18.out
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+Success
diff --git a/tests/REC/test-5.2-18.xml b/tests/REC/test-5.2-18.xml
new file mode 100644
index 00000000..d6458709
--- /dev/null
+++ b/tests/REC/test-5.2-18.xml
@@ -0,0 +1 @@
+<doc><para attr="Failed"/></doc>
diff --git a/tests/REC/test-5.2-18.xsl b/tests/REC/test-5.2-18.xsl
new file mode 100644
index 00000000..fce9d573
--- /dev/null
+++ b/tests/REC/test-5.2-18.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="@*">
+<xsl:text>Success</xsl:text>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-2.out b/tests/REC/test-5.2-2.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-2.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-2.xml b/tests/REC/test-5.2-2.xml
new file mode 100644
index 00000000..6569dc7e
--- /dev/null
+++ b/tests/REC/test-5.2-2.xml
@@ -0,0 +1 @@
+<a>Failed</a>
diff --git a/tests/REC/test-5.2-2.xsl b/tests/REC/test-5.2-2.xsl
new file mode 100644
index 00000000..3960fd4f
--- /dev/null
+++ b/tests/REC/test-5.2-2.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="*">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-3.out b/tests/REC/test-5.2-3.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-3.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-3.xml b/tests/REC/test-5.2-3.xml
new file mode 100644
index 00000000..01517be4
--- /dev/null
+++ b/tests/REC/test-5.2-3.xml
@@ -0,0 +1 @@
+<doc><appendix>Failed</appendix></doc>
diff --git a/tests/REC/test-5.2-3.xsl b/tests/REC/test-5.2-3.xsl
new file mode 100644
index 00000000..0e9b2fef
--- /dev/null
+++ b/tests/REC/test-5.2-3.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="chapter|appendix">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-4.out b/tests/REC/test-5.2-4.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-4.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-4.xml b/tests/REC/test-5.2-4.xml
new file mode 100644
index 00000000..9257c074
--- /dev/null
+++ b/tests/REC/test-5.2-4.xml
@@ -0,0 +1 @@
+<doc><olist><item>Failed</item></olist></doc>
diff --git a/tests/REC/test-5.2-4.xsl b/tests/REC/test-5.2-4.xsl
new file mode 100644
index 00000000..bc24df30
--- /dev/null
+++ b/tests/REC/test-5.2-4.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="olist/item">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-5.out b/tests/REC/test-5.2-5.out
new file mode 100644
index 00000000..cc2e92e1
--- /dev/null
+++ b/tests/REC/test-5.2-5.out
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+
+
+
+
+
+Success
+
+
+
+
diff --git a/tests/REC/test-5.2-5.xml b/tests/REC/test-5.2-5.xml
new file mode 100644
index 00000000..e7499bd0
--- /dev/null
+++ b/tests/REC/test-5.2-5.xml
@@ -0,0 +1,8 @@
+<doc>
+ <appendix>
+ <title/>
+ <content>
+ <para>Failed</para>
+ </content>
+ </appendix>
+</doc>
diff --git a/tests/REC/test-5.2-5.xsl b/tests/REC/test-5.2-5.xsl
new file mode 100644
index 00000000..e0acf193
--- /dev/null
+++ b/tests/REC/test-5.2-5.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="appendix//para">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-6.out b/tests/REC/test-5.2-6.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-6.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-6.xml b/tests/REC/test-5.2-6.xml
new file mode 100644
index 00000000..e646c541
--- /dev/null
+++ b/tests/REC/test-5.2-6.xml
@@ -0,0 +1 @@
+<doc>Failure</doc>
diff --git a/tests/REC/test-5.2-6.xsl b/tests/REC/test-5.2-6.xsl
new file mode 100644
index 00000000..f6663ac2
--- /dev/null
+++ b/tests/REC/test-5.2-6.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="/">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-7.out b/tests/REC/test-5.2-7.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-7.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-7.xml b/tests/REC/test-5.2-7.xml
new file mode 100644
index 00000000..ce140601
--- /dev/null
+++ b/tests/REC/test-5.2-7.xml
@@ -0,0 +1 @@
+<doc>Failed</doc>
diff --git a/tests/REC/test-5.2-7.xsl b/tests/REC/test-5.2-7.xsl
new file mode 100644
index 00000000..df279fc0
--- /dev/null
+++ b/tests/REC/test-5.2-7.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="text()">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-8.out b/tests/REC/test-5.2-8.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-8.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-8.xml b/tests/REC/test-5.2-8.xml
new file mode 100644
index 00000000..e2edece3
--- /dev/null
+++ b/tests/REC/test-5.2-8.xml
@@ -0,0 +1 @@
+<doc><?failed?></doc>
diff --git a/tests/REC/test-5.2-8.xsl b/tests/REC/test-5.2-8.xsl
new file mode 100644
index 00000000..b6687bc2
--- /dev/null
+++ b/tests/REC/test-5.2-8.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="processing-instruction()">
+Success
+</xsl:template>
+</xsl:stylesheet>
diff --git a/tests/REC/test-5.2-9.out b/tests/REC/test-5.2-9.out
new file mode 100644
index 00000000..ac71f0f6
--- /dev/null
+++ b/tests/REC/test-5.2-9.out
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+
+Success
+
diff --git a/tests/REC/test-5.2-9.xml b/tests/REC/test-5.2-9.xml
new file mode 100644
index 00000000..ce140601
--- /dev/null
+++ b/tests/REC/test-5.2-9.xml
@@ -0,0 +1 @@
+<doc>Failed</doc>
diff --git a/tests/REC/test-5.2-9.xsl b/tests/REC/test-5.2-9.xsl
new file mode 100644
index 00000000..5b7110c2
--- /dev/null
+++ b/tests/REC/test-5.2-9.xsl
@@ -0,0 +1,6 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="node()">
+Success
+</xsl:template>
+</xsl:stylesheet>