diff --git a/ChangeLog b/ChangeLog index fd33194f2755e710db9dc80d50d39c5871bf336a_Q2hhbmdlTG9n..451d45f339fe55c818e71c669a5b5bbbc1361719_Q2hhbmdlTG9n 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 fd33194f2755e710db9dc80d50d39c5871bf336a_RkVBVFVSRVM=..451d45f339fe55c818e71c669a5b5bbbc1361719_RkVBVFVSRVM= 100644 --- a/FEATURES +++ b/FEATURES @@ -1,3 +1,7 @@ + Status of implementation of the XSLT 1.0 Features: + ================================================== + + $Id$ Stylesheet Constructs: ====================== @@ -100,6 +104,6 @@ YES xsl:text YES disable-output-escaping = "yes" | "no" - xsl:processing-instruction - name = { ncname } +YES xsl:processing-instruction +YES name = { ncname } @@ -105,5 +109,5 @@ -NO xsl:comment +YES xsl:comment NO xsl:copy NO use-attribute-sets = qnames @@ -208,4 +212,3 @@ NO boolean function-available(string) Daniel.Veillard@imag.fr -$Id$ diff --git a/Makefile.am b/Makefile.am index fd33194f2755e710db9dc80d50d39c5871bf336a_TWFrZWZpbGUuYW0=..451d45f339fe55c818e71c669a5b5bbbc1361719_TWFrZWZpbGUuYW0= 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,7 +25,9 @@ < $(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 fd33194f2755e710db9dc80d50d39c5871bf336a_VE9ETw==..451d45f339fe55c818e71c669a5b5bbbc1361719_VE9ETw== 100644 --- a/TODO +++ b/TODO @@ -25,8 +25,6 @@ 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 @@ 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 fd33194f2755e710db9dc80d50d39c5871bf336a_bGlieHNsdC9wYXR0ZXJuLmM=..451d45f339fe55c818e71c669a5b5bbbc1361719_bGlieHNsdC9wYXR0ZXJuLmM= 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -732,7 +732,7 @@ 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 @@ 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 @@ NEXT; if (NXT(1) != ':') { xsltGenericError(xsltGenericErrorContext, - "xsltCompilePattern : sequence '::' expected\n"); + "xsltCompileStepPattern : sequence '::' expected\n"); ctxt->error = 1; goto error; } @@ -766,7 +772,7 @@ name = xsltScanName(ctxt); if (name == NULL) { xsltGenericError(xsltGenericErrorContext, - "xsltCompilePattern : QName expected\n"); + "xsltCompileStepPattern : QName expected\n"); ctxt->error = 1; goto error; } @@ -776,10 +782,10 @@ 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, @@ -780,10 +786,10 @@ 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 @@ /* TODO: handle namespace */ PUSH(XSLT_OP_ELEM, token, NULL); } +parse_predicate: SKIP_BLANKS; while (CUR == '[') { const xmlChar *q; @@ -807,7 +814,7 @@ NEXT; if (!IS_CHAR(CUR)) { xsltGenericError(xsltGenericErrorContext, - "xsltCompilePattern : ']' expected\n"); + "xsltCompileStepPattern : ']' expected\n"); ctxt->error = 1; goto error; } @@ -899,6 +906,8 @@ 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 @@ */ int xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur) { - xsltCompMatchPtr pat, list; + xsltCompMatchPtr pat, list, *top; const xmlChar *name = NULL; xmlChar *p, *pattern, tmp; @@ -1083,5 +1092,11 @@ * 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: @@ -1086,6 +1101,5 @@ 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,6 +1108,6 @@ name = pat->steps[0].value; break; case XSLT_OP_ROOT: - name = (const xmlChar *) "/"; + top = (xsltCompMatchPtr *) &(style->rootMatch); break; case XSLT_OP_ALL: @@ -1098,6 +1112,6 @@ break; case XSLT_OP_ALL: - name = (const xmlChar *) "*"; + top = (xsltCompMatchPtr *) &(style->elemMatch); break; case XSLT_OP_END: case XSLT_OP_PREDICATE: @@ -1110,6 +1124,9 @@ * 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: @@ -1114,5 +1131,5 @@ break; case XSLT_OP_COMMENT: - name = (const xmlChar *) "comment()"; + top = (xsltCompMatchPtr *) &(style->commentMatch); break; case XSLT_OP_TEXT: @@ -1117,5 +1134,5 @@ break; case XSLT_OP_TEXT: - name = (const xmlChar *) "text()"; + top = (xsltCompMatchPtr *) &(style->textMatch); break; case XSLT_OP_NODE: @@ -1120,5 +1137,9 @@ 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; } @@ -1123,15 +1144,10 @@ 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); - } + if (name != NULL) { + if (style->templatesHash == NULL) { + style->templatesHash = xmlHashCreate(0); + if (style->templatesHash == NULL) { + xsltFreeCompMatch(pat); + return(-1); + } #ifdef DEBUG_PARSING @@ -1137,4 +1153,4 @@ #ifdef DEBUG_PARSING - xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: created template hash\n"); + xsltGenericDebug(xsltGenericDebugContext, + "xsltAddTemplate: created template hash\n"); #endif @@ -1140,15 +1156,7 @@ #endif - xmlHashAddEntry(style->templatesHash, name, pat); -#ifdef DEBUG_PARSING - xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: added new hash %s\n", name); -#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 { @@ -1149,15 +1157,11 @@ 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, @@ -1162,5 +1166,5 @@ #ifdef DEBUG_PARSING xsltGenericDebug(xsltGenericDebugContext, - "xsltAddTemplate: added head hash for %s\n", name); + "xsltAddTemplate: added new hash %s\n", name); #endif } else { @@ -1165,6 +1169,22 @@ #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; } @@ -1170,5 +1190,3 @@ } - pat->next = list->next; - list->next = pat; } } @@ -1173,5 +1191,26 @@ } } + } 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,10 +1228,11 @@ */ 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 ! */ @@ -1194,9 +1234,54 @@ 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; /* @@ -1201,6 +1286,6 @@ /* - * Use a name as selector + * find alternate generic matches */ switch (node->type) { case XML_ELEMENT_NODE: @@ -1204,4 +1289,6 @@ */ switch (node->type) { case XML_ELEMENT_NODE: + list = style->elemMatch; + break; case XML_ATTRIBUTE_NODE: @@ -1207,2 +1294,4 @@ case XML_ATTRIBUTE_NODE: + list = style->attrMatch; + break; case XML_PI_NODE: @@ -1208,5 +1297,5 @@ case XML_PI_NODE: - name = node->name; + list = style->piMatch; break; case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: @@ -1210,7 +1299,7 @@ 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: @@ -1214,5 +1303,10 @@ 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: @@ -1217,6 +1311,5 @@ 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,5 +1320,5 @@ case XML_NAMESPACE_DECL: case XML_XINCLUDE_START: case XML_XINCLUDE_END: - return(NULL); + break; default: @@ -1231,4 +1324,4 @@ default: - return(NULL); + break; } @@ -1233,16 +1326,9 @@ } - if (name == NULL) - return(NULL); - - /* - * 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) && + ((ret == NULL) || (list->priority > ret->priority))) { + if (xsltTestCompMatch(list, node)) { + ret = list->template; + break; + } } @@ -1248,11 +1334,5 @@ } - while (list != NULL) { - if (xsltTestCompMatch(list, node)) - return(list->template); - list = list->next; - } - - return(NULL); + return(ret); } @@ -1267,6 +1347,20 @@ 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 fd33194f2755e710db9dc80d50d39c5871bf336a_bGlieHNsdC90ZW1wbGF0ZXMuYw==..451d45f339fe55c818e71c669a5b5bbbc1361719_bGlieHNsdC90ZW1wbGF0ZXMuYw== 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 @@ } /** + * 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 @@ } /** + * 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 @@ 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 fd33194f2755e710db9dc80d50d39c5871bf336a_bGlieHNsdC90ZW1wbGF0ZXMuaA==..451d45f339fe55c818e71c669a5b5bbbc1361719_bGlieHNsdC90ZW1wbGF0ZXMuaA== 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 fd33194f2755e710db9dc80d50d39c5871bf336a_bGlieHNsdC90cmFuc2Zvcm0uYw==..451d45f339fe55c818e71c669a5b5bbbc1361719_bGlieHNsdC90cmFuc2Zvcm0uYw== 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -129,7 +129,7 @@ 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 @@ } 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 @@ 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 @@ } /** + * 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,5 +341,5 @@ "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) { @@ -262,6 +345,5 @@ if (prop != NULL) { - /* TODO: attribute value template */ - TODO + TODO /* xsl:attribute namespace */ xmlFree(prop); return; } @@ -265,7 +347,7 @@ 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,5 +980,6 @@ ctxt->insert = insert; xsltAttribute(ctxt, node, cur); ctxt->insert = oldInsert; + /******* } else if (IS_XSLT_NAME(cur, "element")) { ctxt->insert = insert; @@ -901,6 +984,15 @@ } 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 fd33194f2755e710db9dc80d50d39c5871bf336a_bGlieHNsdC94c2x0SW50ZXJuYWxzLmg=..451d45f339fe55c818e71c669a5b5bbbc1361719_bGlieHNsdC94c2x0SW50ZXJuYWxzLmg= 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -93,6 +93,14 @@ 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. */