summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2001-01-24 16:05:44 +0000
committerDaniel Veillard <veillard@src.gnome.org>2001-01-24 16:05:44 +0000
commitb6f493448ebb71a53f20a3c7205d03bb582e639d (patch)
tree38b8fa712ed23482dbbc61c0f967053ffb84f1a8
parentd6deccfda51342a185a491fba5cf2e0996367a86 (diff)
downloadlibxslt-b6f493448ebb71a53f20a3c7205d03bb582e639d.tar.gz
libxslt-b6f493448ebb71a53f20a3c7205d03bb582e639d.tar.bz2
libxslt-b6f493448ebb71a53f20a3c7205d03bb582e639d.zip
Lotsa improvement and fixes:
- libxslt/xsltInternals.h libxslt/pattern.c: fixed problems with non-named rules (*, ...) added accelerators - libxslt/templates.[ch]: added xsltEvalTemplateString() and xsltEvalAttrValueTemplate() high level functions - libxslt/transform.c: fixed the part where attributes had to be looked at as templates, added comment and PI generation - TODO FEATURES: updated to reflect the new state Daniel
-rw-r--r--ChangeLog11
-rw-r--r--FEATURES11
-rw-r--r--Makefile.am4
-rw-r--r--TODO7
-rw-r--r--libxslt/pattern.c260
-rw-r--r--libxslt/templates.c85
-rw-r--r--libxslt/templates.h6
-rw-r--r--libxslt/transform.c112
-rw-r--r--libxslt/xsltInternals.h8
9 files changed, 404 insertions, 100 deletions
diff --git a/ChangeLog b/ChangeLog
index 1063602e..f64ecb35 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Wed Jan 24 16:59:05 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+ * libxslt/xsltInternals.h libxslt/pattern.c: fixed problems
+ with non-named rules (*, ...) added accelerators
+ * libxslt/templates.[ch]: added xsltEvalTemplateString()
+ and xsltEvalAttrValueTemplate() high level functions
+ * libxslt/transform.c: fixed the part where attributes
+ had to be looked at as templates, added comment and
+ PI generation
+ * TODO FEATURES: updated to reflect the new state
+
Wed Jan 24 05:33:54 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* libxslt/functions.[ch] Makefile.am: added new module functions
diff --git a/FEATURES b/FEATURES
index 889e575c..651e570c 100644
--- a/FEATURES
+++ b/FEATURES
@@ -1,3 +1,7 @@
+ Status of implementation of the XSLT 1.0 Features:
+ ==================================================
+
+ $Id$
Stylesheet Constructs:
======================
@@ -100,10 +104,10 @@ YES namespace = { uri-reference }
YES xsl:text
YES disable-output-escaping = "yes" | "no"
- xsl:processing-instruction
- name = { ncname }
+YES xsl:processing-instruction
+YES name = { ncname }
-NO xsl:comment
+YES xsl:comment
NO xsl:copy
NO use-attribute-sets = qnames
@@ -208,4 +212,3 @@ NO boolean element-available(string)
NO boolean function-available(string)
Daniel.Veillard@imag.fr
-$Id$
diff --git a/Makefile.am b/Makefile.am
index e8e017a2..e2275472 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,7 +25,9 @@ xsltConf.sh: xsltConf.sh.in Makefile
< $(srcdir)/xsltConf.sh.in > xsltConf.tmp \
&& mv xsltConf.tmp xsltConf.sh
-test tests:
+dummy:
+
+test tests: dummy
@(cd tests ; make test)
cleantar:
diff --git a/TODO b/TODO
index 33d6b2b2..57fbb00a 100644
--- a/TODO
+++ b/TODO
@@ -25,8 +25,6 @@ ID and Key support:
Pattern tester:
-> try to optimize for ID scan and tests.
- -> also put fast lookup for "text()", "comment()", "node()"
- based patterns lists.
Pattern scanner:
-> add error checks on all returns
@@ -75,3 +73,8 @@ Support for disable-output-escaping="yes":
Pattern scanner:
-> compute priority
=> done
+
+Pattern tester:
+ -> also put fast lookup for "text()", "comment()", "node()"
+ based patterns lists.
+ => done
diff --git a/libxslt/pattern.c b/libxslt/pattern.c
index 3b6529b6..2c4129c5 100644
--- a/libxslt/pattern.c
+++ b/libxslt/pattern.c
@@ -732,7 +732,7 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
token = xsltScanName(ctxt);
if (token == NULL) {
xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : Name expected\n");
+ "xsltCompileStepPattern : Name expected\n");
ctxt->error = 1;
goto error;
}
@@ -742,10 +742,16 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
if (token == NULL)
token = xsltScanName(ctxt);
if (token == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : Name expected\n");
- ctxt->error = 1;
- goto error;
+ if (CUR == '*') {
+ NEXT;
+ PUSH(XSLT_OP_ALL, token, NULL);
+ goto parse_predicate;
+ } else {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltCompileStepPattern : Name expected\n");
+ ctxt->error = 1;
+ goto error;
+ }
}
SKIP_BLANKS;
if (CUR == '(') {
@@ -756,7 +762,7 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
NEXT;
if (NXT(1) != ':') {
xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : sequence '::' expected\n");
+ "xsltCompileStepPattern : sequence '::' expected\n");
ctxt->error = 1;
goto error;
}
@@ -766,7 +772,7 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
name = xsltScanName(ctxt);
if (name == NULL) {
xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : QName expected\n");
+ "xsltCompileStepPattern : QName expected\n");
ctxt->error = 1;
goto error;
}
@@ -776,14 +782,14 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
name = xsltScanName(ctxt);
if (name == NULL) {
xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : QName expected\n");
+ "xsltCompileStepPattern : QName expected\n");
ctxt->error = 1;
goto error;
}
PUSH(XSLT_OP_ATTR, name, NULL);
} else {
xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : 'child' or 'attribute' expected\n");
+ "xsltCompileStepPattern : 'child' or 'attribute' expected\n");
ctxt->error = 1;
goto error;
}
@@ -795,6 +801,7 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
/* TODO: handle namespace */
PUSH(XSLT_OP_ELEM, token, NULL);
}
+parse_predicate:
SKIP_BLANKS;
while (CUR == '[') {
const xmlChar *q;
@@ -807,7 +814,7 @@ xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
NEXT;
if (!IS_CHAR(CUR)) {
xsltGenericError(xsltGenericErrorContext,
- "xsltCompilePattern : ']' expected\n");
+ "xsltCompileStepPattern : ']' expected\n");
ctxt->error = 1;
goto error;
}
@@ -899,6 +906,8 @@ xsltCompileLocationPathPattern(xsltParserContextPtr ctxt) {
PUSH(XSLT_OP_PARENT, NULL, NULL);
xsltCompileRelativePathPattern(ctxt, NULL);
}
+ } else if (CUR == '*') {
+ xsltCompileRelativePathPattern(ctxt, NULL);
} else {
xmlChar *name;
name = xsltScanName(ctxt);
@@ -1044,7 +1053,7 @@ error:
*/
int
xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) {
- xsltCompMatchPtr pat, list;
+ xsltCompMatchPtr pat, list, *top;
const xmlChar *name = NULL;
xmlChar *p, *pattern, tmp;
@@ -1083,9 +1092,14 @@ next_pattern:
* insert it in the hash table list corresponding to its lookup name
*/
switch (pat->steps[0].op) {
+ case XSLT_OP_ATTR:
+ if (pat->steps[0].value != NULL)
+ name = pat->steps[0].value;
+ else
+ top = (xsltCompMatchPtr *) &(style->attrMatch);
+ break;
case XSLT_OP_ELEM:
case XSLT_OP_CHILD:
- case XSLT_OP_ATTR:
case XSLT_OP_PARENT:
case XSLT_OP_ANCESTOR:
case XSLT_OP_ID:
@@ -1094,10 +1108,10 @@ next_pattern:
name = pat->steps[0].value;
break;
case XSLT_OP_ROOT:
- name = (const xmlChar *) "/";
+ top = (xsltCompMatchPtr *) &(style->rootMatch);
break;
case XSLT_OP_ALL:
- name = (const xmlChar *) "*";
+ top = (xsltCompMatchPtr *) &(style->elemMatch);
break;
case XSLT_OP_END:
case XSLT_OP_PREDICATE:
@@ -1110,68 +1124,93 @@ next_pattern:
* would be faster than inclusion in the hash table.
*/
case XSLT_OP_PI:
- name = (const xmlChar *) "processing-instruction()";
+ if (pat->steps[0].value != NULL)
+ name = pat->steps[0].value;
+ else
+ top = (xsltCompMatchPtr *) &(style->piMatch);
break;
case XSLT_OP_COMMENT:
- name = (const xmlChar *) "comment()";
+ top = (xsltCompMatchPtr *) &(style->commentMatch);
break;
case XSLT_OP_TEXT:
- name = (const xmlChar *) "text()";
+ top = (xsltCompMatchPtr *) &(style->textMatch);
break;
case XSLT_OP_NODE:
- name = (const xmlChar *) "node()";
+ if (pat->steps[0].value != NULL)
+ name = pat->steps[0].value;
+ else
+ top = (xsltCompMatchPtr *) &(style->elemMatch);
+
break;
}
- if (name == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsltAddTemplate: invalid compiled pattern\n");
- xsltFreeCompMatch(pat);
- return(-1);
- }
- if (style->templatesHash == NULL) {
- style->templatesHash = xmlHashCreate(0);
- if (style->templatesHash == NULL) {
- xsltFreeCompMatch(pat);
- return(-1);
- }
-#ifdef DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltAddTemplate: created template hash\n");
-#endif
- xmlHashAddEntry(style->templatesHash, name, pat);
+ if (name != NULL) {
+ if (style->templatesHash == NULL) {
+ style->templatesHash = xmlHashCreate(0);
+ if (style->templatesHash == NULL) {
+ xsltFreeCompMatch(pat);
+ return(-1);
+ }
#ifdef DEBUG_PARSING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltAddTemplate: added new hash %s\n", name);
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsltAddTemplate: created template hash\n");
#endif
- } else {
- list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
- if (list == NULL) {
xmlHashAddEntry(style->templatesHash, name, pat);
#ifdef DEBUG_PARSING
xsltGenericDebug(xsltGenericDebugContext,
"xsltAddTemplate: added new hash %s\n", name);
#endif
} else {
- /*
- * Note '<=' since one must choose among the matching template
- * rules that are left, the one that occurs last in the stylesheet
- */
- if (list->priority <= pat->priority) {
- pat->next = list;
- xmlHashUpdateEntry(style->templatesHash, name, pat, NULL);
+ list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
+ if (list == NULL) {
+ xmlHashAddEntry(style->templatesHash, name, pat);
#ifdef DEBUG_PARSING
xsltGenericDebug(xsltGenericDebugContext,
- "xsltAddTemplate: added head hash for %s\n", name);
+ "xsltAddTemplate: added new hash %s\n", name);
#endif
} else {
- while (list->next != NULL) {
- if (list->next->priority <= pat->priority)
- break;
+ /*
+ * Note '<=' since one must choose among the matching
+ * template rules that are left, the one that occurs
+ * last in the stylesheet
+ */
+ if (list->priority <= pat->priority) {
+ pat->next = list;
+ xmlHashUpdateEntry(style->templatesHash, name, pat, NULL);
+#ifdef DEBUG_PARSING
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsltAddTemplate: added head hash for %s\n", name);
+#endif
+ } else {
+ while (list->next != NULL) {
+ if (list->next->priority <= pat->priority)
+ break;
+ }
+ pat->next = list->next;
+ list->next = pat;
}
- pat->next = list->next;
- list->next = pat;
}
}
+ } else if (top != NULL) {
+ list = *top;
+ if (list == NULL) {
+ *top = pat;
+ pat->next = NULL;
+ } else if (list->priority <= pat->priority) {
+ pat->next = list;
+ *top = pat;
+ } else {
+ while (list->next != NULL) {
+ if (list->next->priority <= pat->priority)
+ break;
+ }
+ pat->next = list->next;
+ list->next = pat;
+ }
+ } else {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltAddTemplate: invalid compiled pattern\n");
+ xsltFreeCompMatch(pat);
+ return(-1);
}
if (*p != 0)
goto next_pattern;
@@ -1189,34 +1228,88 @@ next_pattern:
*/
xsltTemplatePtr
xsltGetTemplate(xsltStylesheetPtr style, xmlNodePtr node) {
- const xmlChar *name;
- xsltCompMatchPtr list;
+ xsltTemplatePtr ret = NULL;
+ const xmlChar *name = NULL;
+ xsltCompMatchPtr list = NULL;
if ((style == NULL) || (node == NULL))
return(NULL);
/* TODO : handle IDs/keys here ! */
- if (style->templatesHash == NULL)
- return(NULL);
+ if (style->templatesHash != NULL) {
+ /*
+ * Use the top name as selector
+ */
+ switch (node->type) {
+ case XML_ELEMENT_NODE:
+ case XML_ATTRIBUTE_NODE:
+ case XML_PI_NODE:
+ name = node->name;
+ break;
+ case XML_DOCUMENT_NODE:
+ case XML_HTML_DOCUMENT_NODE:
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_COMMENT_NODE:
+ case XML_ENTITY_REF_NODE:
+ case XML_ENTITY_NODE:
+ case XML_DOCUMENT_TYPE_NODE:
+ case XML_DOCUMENT_FRAG_NODE:
+ case XML_NOTATION_NODE:
+ case XML_DTD_NODE:
+ case XML_ELEMENT_DECL:
+ case XML_ATTRIBUTE_DECL:
+ case XML_ENTITY_DECL:
+ case XML_NAMESPACE_DECL:
+ case XML_XINCLUDE_START:
+ case XML_XINCLUDE_END:
+ return(NULL);
+ default:
+ return(NULL);
+
+ }
+ }
+ if (name != NULL) {
+ /*
+ * find the list of appliable expressions based on the name
+ */
+ list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
+ }
+ while (list != NULL) {
+ if (xsltTestCompMatch(list, node)) {
+ ret = list->template;
+ break;
+ }
+ list = list->next;
+ }
+ list = NULL;
/*
- * Use a name as selector
+ * find alternate generic matches
*/
switch (node->type) {
case XML_ELEMENT_NODE:
+ list = style->elemMatch;
+ break;
case XML_ATTRIBUTE_NODE:
+ list = style->attrMatch;
+ break;
case XML_PI_NODE:
- name = node->name;
+ list = style->piMatch;
break;
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
- name = (const xmlChar *)"/";
+ list = style->rootMatch;
break;
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
+ list = style->textMatch;
+ break;
+ case XML_COMMENT_NODE:
+ list = style->commentMatch;
+ break;
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
- case XML_COMMENT_NODE:
case XML_DOCUMENT_TYPE_NODE:
case XML_DOCUMENT_FRAG_NODE:
case XML_NOTATION_NODE:
@@ -1227,32 +1320,19 @@ xsltGetTemplate(xsltStylesheetPtr style, xmlNodePtr node) {
case XML_NAMESPACE_DECL:
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
- return(NULL);
+ break;
default:
- return(NULL);
-
- }
- if (name == NULL)
- return(NULL);
+ break;
- /*
- * find the list of appliable expressions based on the name
- */
- list = (xsltCompMatchPtr) xmlHashLookup(style->templatesHash, name);
- if (list == NULL) {
-#ifdef DEBUG_MATCHING
- xsltGenericDebug(xsltGenericDebugContext,
- "xsltGetTemplate: empty set for %s\n", name);
-#endif
- return(NULL);
}
- while (list != NULL) {
- if (xsltTestCompMatch(list, node))
- return(list->template);
- list = list->next;
+ while ((list != NULL) &&
+ ((ret == NULL) || (list->priority > ret->priority))) {
+ if (xsltTestCompMatch(list, node)) {
+ ret = list->template;
+ break;
+ }
}
-
- return(NULL);
+ return(ret);
}
@@ -1267,6 +1347,20 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) {
if (style->templatesHash != NULL)
xmlHashFree((xmlHashTablePtr) style->templatesHash,
(xmlHashDeallocator) xsltFreeCompMatchList);
+ if (style->rootMatch != NULL)
+ xsltFreeCompMatchList(style->rootMatch);
+ if (style->elemMatch != NULL)
+ xsltFreeCompMatchList(style->elemMatch);
+ if (style->attrMatch != NULL)
+ xsltFreeCompMatchList(style->attrMatch);
+ if (style->parentMatch != NULL)
+ xsltFreeCompMatchList(style->parentMatch);
+ if (style->textMatch != NULL)
+ xsltFreeCompMatchList(style->textMatch);
+ if (style->piMatch != NULL)
+ xsltFreeCompMatchList(style->piMatch);
+ if (style->commentMatch != NULL)
+ xsltFreeCompMatchList(style->commentMatch);
}
/**
diff --git a/libxslt/templates.c b/libxslt/templates.c
index 97349f23..ebc0b4d3 100644
--- a/libxslt/templates.c
+++ b/libxslt/templates.c
@@ -24,6 +24,7 @@
#include "variables.h"
#include "functions.h"
#include "templates.h"
+#include "transform.h"
#define DEBUG_TEMPLATES
@@ -89,6 +90,48 @@ xsltEvalXPathString(xsltTransformContextPtr ctxt, const xmlChar *expr) {
}
/**
+ * xsltEvalTemplateString:
+ * @ctxt: the XSLT transformation context
+ * @node: the stylesheet node
+ * @parent: the content parent
+ *
+ * Evaluate a template string value, i.e. the parent list is interpreter
+ * as template content and the resulting tree string value is returned
+ * This is needed for example by xsl:comment and xsl:processing-instruction
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ * caller.
+ */
+xmlChar *
+xsltEvalTemplateString(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ xmlNodePtr parent) {
+ xmlChar *ret;
+ xmlNodePtr oldInsert, insert = NULL;
+
+ if ((ctxt == NULL) || (node == NULL) || (parent == NULL))
+ return(NULL);
+
+ if (parent->children == NULL)
+ return(NULL);
+
+ insert = xmlNewDocNode(ctxt->output, NULL,
+ (const xmlChar *)"fake", NULL);
+ if (insert == NULL)
+ return(NULL);
+ oldInsert = ctxt->insert;
+ ctxt->insert = insert;
+
+ xsltApplyOneTemplate(ctxt, node, parent->children);
+
+ ctxt->insert = oldInsert;
+
+ ret = xmlNodeGetContent(insert);
+ if (insert != NULL)
+ xmlFreeNode(insert);
+ return(ret);
+}
+
+/**
* xsltAttrTemplateValueProcess:
* @ctxt: the XSLT transformation context
* @str: the attribute template node value
@@ -151,6 +194,47 @@ xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {
}
/**
+ * xsltEvalAttrValueTemplate:
+ * @ctxt: the XSLT transformation context
+ * @node: the stylesheet node
+ * @name: the attribute QName
+ *
+ * Evaluate a attribute value template, i.e. the attribute value can
+ * contain expressions contained in curly braces ({}) and those are
+ * substituted by they computed value.
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ * caller.
+ */
+xmlChar *
+xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ const xmlChar *name) {
+ xmlChar *ret;
+ xmlChar *expr;
+
+ if ((ctxt == NULL) || (node == NULL) || (name == NULL))
+ return(NULL);
+
+ expr = xmlGetNsProp(node, name, XSLT_NAMESPACE);
+ if (expr == NULL)
+ return(NULL);
+
+ /*
+ * TODO: accelerator if there is no AttrValueTemplate in the stylesheet
+ * return expr directly
+ */
+
+ ret = xsltAttrTemplateValueProcess(ctxt, expr);
+#ifdef DEBUG_TEMPLATES
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsltEvalXPathString: %s returns %s\n", expr, ret);
+#endif
+ if (expr != NULL)
+ xmlFree(expr);
+ return(ret);
+}
+
+/**
* xsltAttrTemplateProcess:
* @ctxt: the XSLT transformation context
* @target: the result node
@@ -202,6 +286,7 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
xmlChar *in = xmlNodeListGetString(ctxt->doc, cur->children, 1);
xmlChar *out;
+ /* TODO: optimize if no template value was detected */
if (in != NULL) {
xmlNodePtr child;
diff --git a/libxslt/templates.h b/libxslt/templates.h
index 9d135e4e..7daea117 100644
--- a/libxslt/templates.h
+++ b/libxslt/templates.h
@@ -17,6 +17,12 @@
extern "C" {
#endif
+xmlChar * xsltEvalTemplateString (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr parent);
+xmlChar * xsltEvalAttrValueTemplate (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ const xmlChar *name);
xmlChar * xsltEvalXPathString (xsltTransformContextPtr ctxt,
const xmlChar *expr);
xmlNodePtr * xsltTemplateProcess (xsltTransformContextPtr ctxt,
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 8b981c39..8a42a990 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -129,7 +129,7 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node,
len = list->nodeNr;
/* TODO: process attributes as attribute value templates */
- prop = xmlGetNsProp(inst, (const xmlChar *)"data-type", XSLT_NAMESPACE);
+ prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"data-type");
if (prop != NULL) {
if (xmlStrEqual(prop, (const xmlChar *) "text"))
number = 0;
@@ -142,7 +142,7 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node,
}
xmlFree(prop);
}
- prop = xmlGetNsProp(inst, (const xmlChar *)"order", XSLT_NAMESPACE);
+ prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"order");
if (prop != NULL) {
if (xmlStrEqual(prop, (const xmlChar *) "ascending"))
descending = 0;
@@ -160,9 +160,12 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node,
prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE);
if (prop == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "xsltSort: select is not defined\n");
- return;
+ prop = xmlNodeGetContent(inst);
+ if (prop == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltSort: select is not defined\n");
+ return;
+ }
}
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
@@ -233,6 +236,86 @@ error:
}
/**
+ * xsltComment:
+ * @ctxt: a XSLT process context
+ * @node: the node in the source tree.
+ * @inst: the xslt comment node
+ *
+ * Process the xslt comment node on the source node
+ */
+void
+xsltComment(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ xmlNodePtr inst) {
+ xmlChar *value = NULL;
+ xmlNodePtr comment;
+
+ value = xsltEvalTemplateString(ctxt, node, inst);
+ /* TODO: check that there is no -- sequence and doesn't end up with - */
+#ifdef DEBUG_PROCESS
+ if (value == NULL)
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsl:comment: empty\n");
+ else
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsl:comment: content %s\n", value);
+#endif
+
+ comment = xmlNewComment(value);
+ xmlAddChild(ctxt->insert, comment);
+
+ if (value != NULL)
+ xmlFree(value);
+}
+
+/**
+ * xsltProcessingInstruction:
+ * @ctxt: a XSLT process context
+ * @node: the node in the source tree.
+ * @inst: the xslt processing-instruction node
+ *
+ * Process the xslt processing-instruction node on the source node
+ */
+void
+xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ xmlNodePtr inst) {
+ xmlChar *ncname = NULL;
+ xmlChar *value = NULL;
+ xmlNodePtr pi;
+
+
+ if (ctxt->insert == NULL)
+ return;
+ ncname = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"name");
+ if (ncname == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "xslt:processing-instruction : name is missing\n");
+ goto error;
+ }
+ /* TODO: check that it's both an an NCName and a PITarget. */
+
+
+ value = xsltEvalTemplateString(ctxt, node, inst);
+ /* TODO: check that there is no ?> sequence */
+#ifdef DEBUG_PROCESS
+ if (value == NULL)
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsl:processing-instruction: %s empty\n", ncname);
+ else
+ xsltGenericDebug(xsltGenericDebugContext,
+ "xsl:processing-instruction: %s content %s\n", ncname, value);
+#endif
+
+ pi = xmlNewPI(ncname, value);
+ xmlAddChild(ctxt->insert, pi);
+
+error:
+ if (ncname != NULL)
+ xmlFree(ncname);
+ if (value != NULL)
+ xmlFree(value);
+}
+
+/**
* xsltAttribute:
* @ctxt: a XSLT process context
* @node: the node in the source tree.
@@ -258,14 +341,13 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
"xslt:attribute : node has already children\n");
return;
}
- prop = xmlGetNsProp(inst, (const xmlChar *)"namespace", XSLT_NAMESPACE);
+ prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"namespace");
if (prop != NULL) {
- /* TODO: attribute value template */
- TODO
+ TODO /* xsl:attribute namespace */
xmlFree(prop);
return;
}
- prop = xmlGetNsProp(inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+ prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"name");
if (prop == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xslt:attribute : name is missing\n");
@@ -898,9 +980,19 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
ctxt->insert = insert;
xsltAttribute(ctxt, node, cur);
ctxt->insert = oldInsert;
+ /*******
} else if (IS_XSLT_NAME(cur, "element")) {
ctxt->insert = insert;
- xsltAttribute(ctxt, node, cur);
+ xsltElement(ctxt, node, cur);
+ ctxt->insert = oldInsert;
+ *******/
+ } else if (IS_XSLT_NAME(cur, "comment")) {
+ ctxt->insert = insert;
+ xsltComment(ctxt, node, cur);
+ ctxt->insert = oldInsert;
+ } else if (IS_XSLT_NAME(cur, "processing-instruction")) {
+ ctxt->insert = insert;
+ xsltProcessingInstruction(ctxt, node, cur);
ctxt->insert = oldInsert;
} else if (IS_XSLT_NAME(cur, "variable")) {
if (has_variables == 0) {
diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
index 179ba2c3..da00c133 100644
--- a/libxslt/xsltInternals.h
+++ b/libxslt/xsltInternals.h
@@ -93,6 +93,14 @@ struct _xsltStylesheet {
xsltTemplatePtr templates; /* the ordered list of templates */
void *templatesHash; /* hash table or wherever compiled templates
informations are stored */
+ void *rootMatch; /* template based on / */
+ void *elemMatch; /* template based on * */
+ void *attrMatch; /* template based on @* */
+ void *parentMatch; /* template based on .. */
+ void *textMatch; /* template based on text() */
+ void *piMatch; /* template based on processing-instruction() */
+ void *commentMatch; /* template based on comment() */
+
/*
* Output related stuff.
*/