+Thu Feb 8 12:09:58 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+ * 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 <Daniel.Veillard@imag.fr>
* libxslt/functions.c FEATURES: started adding support for key()
ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
return(ret);
}
+ table = table->next;
}
return(NULL);
}
} else {
xmlXPathNodeSetAdd(keylist, nodelist->nodeTab[i]);
}
+ nodelist->nodeTab[i]->_private = keyd;
xmlFree(str);
#ifdef DEBUG_KEYS
} else {
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);
+}
#include "xsltutils.h"
#include "imports.h"
#include "templates.h"
+#include "keys.h"
#include "pattern.h"
/* #define DEBUG_PARSING */
xsltOp op;
xmlChar *value;
xmlChar *value2;
+ xmlChar *value3;
};
typedef struct _xsltCompMatch xsltCompMatch;
xmlFree(op->value);
if (op->value2 != NULL)
xmlFree(op->value2);
+ if (op->value3 != NULL)
+ xmlFree(op->value3);
}
memset(comp, -1, sizeof(xsltCompMatch));
xmlFree(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) {
return;
}
NEXT;
+ /* TODO: support namespace in keys */
PUSH(XSLT_OP_KEY, lit, lit2);
} else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
NEXT;
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;
}
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);
(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)
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 .. */