diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | FEATURES | 11 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | TODO | 7 | ||||
-rw-r--r-- | libxslt/pattern.c | 260 | ||||
-rw-r--r-- | libxslt/templates.c | 85 | ||||
-rw-r--r-- | libxslt/templates.h | 6 | ||||
-rw-r--r-- | libxslt/transform.c | 112 | ||||
-rw-r--r-- | libxslt/xsltInternals.h | 8 |
9 files changed, 404 insertions, 100 deletions
@@ -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 @@ -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: @@ -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. */ |