From: Daniel Veillard Date: Thu, 8 Feb 2001 11:16:41 +0000 (+0000) Subject: Added more support for keys, nearly complete: X-Git-Tag: v1.1.28~1477 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=443496a5d7ad1504ad5554f3a80d9539140fcb5c;p=platform%2Fupstream%2Flibxslt.git Added more support for keys, nearly complete: - FEATURES libxslt/xsltInternals.h libxslt/pattern.c libxslt/keys.c: added support for keys in patterns - tests/REC/test-12.2-2.*: added a specific testcase Daniel --- diff --git a/ChangeLog b/ChangeLog index 683dcb4..f61b089 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Feb 8 12:09:58 CET 2001 Daniel Veillard + + * FEATURES libxslt/xsltInternals.h libxslt/pattern.c libxslt/keys.c: + added support for keys in patterns + * tests/REC/test-12.2-2.*: added a specific testcase + Wed Feb 7 21:16:47 CET 2001 Daniel Veillard * libxslt/functions.c FEATURES: started adding support for key() diff --git a/FEATURES b/FEATURES index c7556d0..d094e8e 100644 --- a/FEATURES +++ b/FEATURES @@ -194,7 +194,7 @@ YES match="*|/" YES match="text()|@*" YES match="processing-instruction()|comment()" YES Namespace -NO Mode +YES Mode NO Extension Elements @@ -238,6 +238,6 @@ YES item[position() mod 2 = 1] YES div[@class="appendix"]//p YES @class YES @* -NO key('a','b') +YES except ns for key key('a','b') Daniel.Veillard@imag.fr diff --git a/libxslt/keys.c b/libxslt/keys.c index a25cceb..056204f 100644 --- a/libxslt/keys.c +++ b/libxslt/keys.c @@ -272,6 +272,7 @@ xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value); return(ret); } + table = table->next; } return(NULL); } @@ -370,6 +371,7 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltKeyDefPtr keyd) { } else { xmlXPathNodeSetAdd(keylist, nodelist->nodeTab[i]); } + nodelist->nodeTab[i]->_private = keyd; xmlFree(str); #ifdef DEBUG_KEYS } else { @@ -431,3 +433,24 @@ xsltFreeCtxtKeys(xsltTransformContextPtr ctxt) { xsltFreeKeyTableList((xsltKeyTablePtr) ctxt->keys); } +/* + * xsltIsKey: + * @ctxt: an XSLT transformation context + * @node: a node + * + * Returns 1 if the node is a Key, 0 otherwise + */ +int +xsltIsKey(xsltTransformContextPtr ctxt, xmlNodePtr node) { + if (node == NULL) + return(0); + + /* + * TODO: + * Something a bit more complex may be needed if we want + * to be able to do similar things with IDs + */ + if (node->_private != NULL) + return(1); + return(0); +} diff --git a/libxslt/pattern.c b/libxslt/pattern.c index 0bf79be..51e4c11 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -24,6 +24,7 @@ #include "xsltutils.h" #include "imports.h" #include "templates.h" +#include "keys.h" #include "pattern.h" /* #define DEBUG_PARSING */ @@ -58,6 +59,7 @@ struct _xsltStepOp { xsltOp op; xmlChar *value; xmlChar *value2; + xmlChar *value3; }; typedef struct _xsltCompMatch xsltCompMatch; @@ -139,6 +141,8 @@ xsltFreeCompMatch(xsltCompMatchPtr comp) { xmlFree(op->value); if (op->value2 != NULL) xmlFree(op->value2); + if (op->value3 != NULL) + xmlFree(op->value3); } memset(comp, -1, sizeof(xsltCompMatch)); xmlFree(comp); @@ -442,9 +446,21 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, return(0); break; } - case XSLT_OP_KEY: - TODO /* Handle Keys, might be done differently */ + case XSLT_OP_KEY: { + xmlNodeSetPtr list; + int i; + + list = xsltGetKey(ctxt, step->value, + step->value3, step->value2); + if (list == NULL) + return(0); + for (i = 0;i < list->nodeNr;i++) + if (list->nodeTab[i] == node) + break; + if (i >= list->nodeNr) + return(0); break; + } case XSLT_OP_NS: /* Namespace test */ if (node->ns == NULL) { @@ -761,6 +777,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid) { return; } NEXT; + /* TODO: support namespace in keys */ PUSH(XSLT_OP_KEY, lit, lit2); } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) { NEXT; @@ -1250,9 +1267,11 @@ next_pattern: case XSLT_OP_ROOT: top = (xsltCompMatchPtr *) &(style->rootMatch); break; - case XSLT_OP_ID: case XSLT_OP_KEY: - /* TODO optimize ID/KEY !!! */ + top = (xsltCompMatchPtr *) &(style->keyMatch); + break; + case XSLT_OP_ID: + /* TODO optimize ID !!! */ case XSLT_OP_ALL: top = (xsltCompMatchPtr *) &(style->elemMatch); break; @@ -1487,6 +1506,19 @@ xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node) { } list = list->next; } + if (node->_private != NULL) { + list = style->keyMatch; + while ((list != NULL) && + ((ret == NULL) || (list->priority > ret->priority))) { + if (xsltTestCompMatch(ctxt, list, node, + ctxt->mode, ctxt->modeURI)) { + ret = list->template; + break; + } + list = list->next; + } + } + if (ret != NULL) return(ret); @@ -1512,6 +1544,8 @@ xsltFreeTemplateHashes(xsltStylesheetPtr style) { (xmlHashDeallocator) xsltFreeCompMatchList); if (style->rootMatch != NULL) xsltFreeCompMatchList(style->rootMatch); + if (style->keyMatch != NULL) + xsltFreeCompMatchList(style->keyMatch); if (style->elemMatch != NULL) xsltFreeCompMatchList(style->elemMatch); if (style->attrMatch != NULL) diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 360d9c3..0989f4c 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -116,6 +116,7 @@ struct _xsltStylesheet { void *templatesHash; /* hash table or wherever compiled templates informations are stored */ void *rootMatch; /* template based on / */ + void *keyMatch; /* template based on key() */ void *elemMatch; /* template based on * */ void *attrMatch; /* template based on @* */ void *parentMatch; /* template based on .. */ diff --git a/tests/REC/test-12.2-2.out b/tests/REC/test-12.2-2.out new file mode 100644 index 0000000..62ec6a4 --- /dev/null +++ b/tests/REC/test-12.2-2.out @@ -0,0 +1,7 @@ + + + +Success + + + diff --git a/tests/REC/test-12.2-2.xml b/tests/REC/test-12.2-2.xml new file mode 100644 index 0000000..b833b61 --- /dev/null +++ b/tests/REC/test-12.2-2.xml @@ -0,0 +1,4 @@ + +
+
+ diff --git a/tests/REC/test-12.2-2.xsl b/tests/REC/test-12.2-2.xsl new file mode 100644 index 0000000..68d1299 --- /dev/null +++ b/tests/REC/test-12.2-2.xsl @@ -0,0 +1,11 @@ + + + + + +Success + + +