summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2001-02-08 11:16:41 +0000
committerDaniel Veillard <veillard@src.gnome.org>2001-02-08 11:16:41 +0000
commit443496a5d7ad1504ad5554f3a80d9539140fcb5c (patch)
tree1cd9a356c5592831467425f491fd15cb0ae58f8b
parent8b47e572e390ca59d2b010adb833a237bc4e9db3 (diff)
downloadlibxslt-443496a5d7ad1504ad5554f3a80d9539140fcb5c.tar.gz
libxslt-443496a5d7ad1504ad5554f3a80d9539140fcb5c.tar.bz2
libxslt-443496a5d7ad1504ad5554f3a80d9539140fcb5c.zip
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
-rw-r--r--ChangeLog6
-rw-r--r--FEATURES4
-rw-r--r--libxslt/keys.c23
-rw-r--r--libxslt/pattern.c42
-rw-r--r--libxslt/xsltInternals.h1
-rw-r--r--tests/REC/test-12.2-2.out7
-rw-r--r--tests/REC/test-12.2-2.xml4
-rw-r--r--tests/REC/test-12.2-2.xsl11
8 files changed, 92 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 683dcb41..f61b0894 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+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()
diff --git a/FEATURES b/FEATURES
index c7556d03..d094e8ec 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 a25cceb3..056204fc 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 0bf79be9..51e4c11b 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 360d9c38..0989f4cb 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 00000000..62ec6a48
--- /dev/null
+++ b/tests/REC/test-12.2-2.out
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+
+
+Success
+
+
+
diff --git a/tests/REC/test-12.2-2.xml b/tests/REC/test-12.2-2.xml
new file mode 100644
index 00000000..b833b617
--- /dev/null
+++ b/tests/REC/test-12.2-2.xml
@@ -0,0 +1,4 @@
+<doc>
+ <div id="lookup"/>
+ <div id="unwanted"/>
+</doc>
diff --git a/tests/REC/test-12.2-2.xsl b/tests/REC/test-12.2-2.xsl
new file mode 100644
index 00000000..68d1299c
--- /dev/null
+++ b/tests/REC/test-12.2-2.xsl
@@ -0,0 +1,11 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+<xsl:key name="idkey" match="div" use="@id"/>
+
+<xsl:template match="key('idkey','lookup')">
+Success
+</xsl:template>
+
+</xsl:stylesheet>