1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-29 11:41:22 +03:00

Big XPath cleanup continues, one URI fix:

- xpath.[ch] debugXML.c testXPath.c: fixed the XPath evaluation
  engine, should be far more stable, incorporated a new version of
  preceding/following axis, need testing
- uri.c: fixed file:///c:/a/b/c problem
- test/XPath/tests/idsimple: augmented the XPath tests
Daniel
This commit is contained in:
Daniel Veillard
2000-10-02 23:04:54 +00:00
parent 3bff2b0e5d
commit 740abf5ae7
9 changed files with 343 additions and 185 deletions

View File

@ -1,3 +1,11 @@
Mon Oct 2 23:47:32 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* xpath.[ch] debugXML.c testXPath.c: fixed the XPath evaluation
engine, should be far more stable, incorporated a new version of
preceding/following axis, need testing
* uri.c: fixed file:///c:/a/b/c problem
* test/XPath/tests/idsimple: augmented the XPath tests
Sun Oct 1 22:33:00 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org> Sun Oct 1 22:33:00 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* doc/* rebuilding docs for 2.2.4 release * doc/* rebuilding docs for 2.2.4 release

View File

@ -1649,9 +1649,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
} else { } else {
ctxt->pctxt->node = ctxt->node; ctxt->pctxt->node = ctxt->node;
#ifdef LIBXML_XPATH_ENABLED #ifdef LIBXML_XPATH_ENABLED
if (ctxt->pctxt->nodelist != NULL) ctxt->pctxt->node = ctxt->node;
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
#else #else
list = NULL; list = NULL;
@ -1688,21 +1686,14 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
} else { } else {
fprintf(stderr, "%s: no such node\n", arg); fprintf(stderr, "%s: no such node\n", arg);
} }
#ifdef LIBXML_XPATH_ENABLED ctxt->pctxt->node = NULL;
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
#endif /* LIBXML_XPATH_ENABLED */
ctxt->pctxt->nodelist = NULL;
} }
} else if (!strcmp(command, "cd")) { } else if (!strcmp(command, "cd")) {
if (arg[0] == 0) { if (arg[0] == 0) {
ctxt->node = (xmlNodePtr) ctxt->doc; ctxt->node = (xmlNodePtr) ctxt->doc;
} else { } else {
ctxt->pctxt->node = ctxt->node;
#ifdef LIBXML_XPATH_ENABLED #ifdef LIBXML_XPATH_ENABLED
if (ctxt->pctxt->nodelist != NULL) ctxt->pctxt->node = ctxt->node;
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
#else #else
list = NULL; list = NULL;
@ -1733,11 +1724,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
} else { } else {
fprintf(stderr, "%s: no such node\n", arg); fprintf(stderr, "%s: no such node\n", arg);
} }
#ifdef LIBXML_XPATH_ENABLED ctxt->pctxt->node = NULL;
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
#endif /* LIBXML_XPATH_ENABLED */
ctxt->pctxt->nodelist = NULL;
} }
} else if (!strcmp(command, "cat")) { } else if (!strcmp(command, "cat")) {
if (arg[0] == 0) { if (arg[0] == 0) {
@ -1745,9 +1732,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
} else { } else {
ctxt->pctxt->node = ctxt->node; ctxt->pctxt->node = ctxt->node;
#ifdef LIBXML_XPATH_ENABLED #ifdef LIBXML_XPATH_ENABLED
if (ctxt->pctxt->nodelist != NULL) ctxt->pctxt->node = ctxt->node;
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
ctxt->pctxt->nodelist = xmlXPathNodeSetCreate(ctxt->node);
list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt); list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
#else #else
list = NULL; list = NULL;
@ -1781,11 +1766,7 @@ xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
} else { } else {
fprintf(stderr, "%s: no such node\n", arg); fprintf(stderr, "%s: no such node\n", arg);
} }
#ifdef LIBXML_XPATH_ENABLED ctxt->pctxt->node = NULL;
if (ctxt->pctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->pctxt->nodelist);
#endif /* LIBXML_XPATH_ENABLED */
ctxt->pctxt->nodelist = NULL;
} }
} else { } else {
fprintf(stderr, "Unknown command %s\n", command); fprintf(stderr, "Unknown command %s\n", command);

View File

@ -143,7 +143,6 @@ struct _xmlXPathAxis {
struct _xmlXPathContext { struct _xmlXPathContext {
xmlDocPtr doc; /* The current document */ xmlDocPtr doc; /* The current document */
xmlNodePtr node; /* The current node */ xmlNodePtr node; /* The current node */
xmlNodeSetPtr nodelist; /* The current node list */
int nb_variables; /* number of defined variables */ int nb_variables; /* number of defined variables */
int max_variables; /* max number of variables */ int max_variables; /* max number of variables */

View File

@ -0,0 +1,24 @@
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT EXAMPLE
ATTRIBUTE id
TEXT
content=root
ATTRIBUTE prop1
TEXT
content=gnome is great
ATTRIBUTE prop2
TEXT
content=& linux too
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT chapter
ATTRIBUTE id
TEXT
content=chapter2
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT chapter
ATTRIBUTE id
TEXT
content=chapter5

View File

@ -0,0 +1,3 @@
//*[@id="root"]
//*[@id="chapter2"]
//*[@id="chapter5"]

View File

@ -40,8 +40,10 @@
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/debugXML.h> #include <libxml/debugXML.h>
#include <libxml/xmlmemory.h> #include <libxml/xmlmemory.h>
#include <libxml/parserInternals.h>
static int debug = 0; static int debug = 0;
static int valid = 0;
static int expr = 0; static int expr = 0;
static xmlDocPtr document = NULL; static xmlDocPtr document = NULL;
@ -171,6 +173,8 @@ int main(int argc, char **argv) {
for (i = 1; i < argc ; i++) { for (i = 1; i < argc ; i++) {
if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
debug++; debug++;
if ((!strcmp(argv[i], "-valid")) || (!strcmp(argv[i], "--valid")))
valid++;
if ((!strcmp(argv[i], "-expr")) || (!strcmp(argv[i], "--expr"))) if ((!strcmp(argv[i], "-expr")) || (!strcmp(argv[i], "--expr")))
expr++; expr++;
if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input"))) if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input")))
@ -178,6 +182,7 @@ int main(int argc, char **argv) {
if ((!strcmp(argv[i], "-f")) || (!strcmp(argv[i], "--file"))) if ((!strcmp(argv[i], "-f")) || (!strcmp(argv[i], "--file")))
usefile++; usefile++;
} }
if (valid != 0) xmlDoValidityCheckingDefaultValue = 1;
if (document == NULL) { if (document == NULL) {
if (filename == NULL) if (filename == NULL)
document = xmlParseDoc(buffer); document = xmlParseDoc(buffer);
@ -201,6 +206,7 @@ int main(int argc, char **argv) {
argv[0]); argv[0]);
printf("\tParse the XPath strings and output the result of the parsing\n"); printf("\tParse the XPath strings and output the result of the parsing\n");
printf("\t--debug : dump a debug version of the result\n"); printf("\t--debug : dump a debug version of the result\n");
printf("\t--valid : switch on DTD support in the parser\n");
printf("\t--expr : debug XPath expressions only\n"); printf("\t--expr : debug XPath expressions only\n");
printf("\t--input filename : or\n"); printf("\t--input filename : or\n");
printf("\t-i filename : read the document from filename\n"); printf("\t-i filename : read the document from filename\n");

26
uri.c
View File

@ -373,6 +373,17 @@ xmlSaveUri(xmlURIPtr uri) {
ret[len++] = lo + (lo > 9? 'A'-10 : '0'); ret[len++] = lo + (lo > 9? 'A'-10 : '0');
} }
} }
} else if (uri->scheme != NULL) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
if (ret == NULL) {
fprintf(stderr, "xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '/';
ret[len++] = '/';
} }
if (uri->path != NULL) { if (uri->path != NULL) {
p = uri->path; p = uri->path;
@ -766,12 +777,25 @@ xmlParseURIServer(xmlURIPtr uri, const char **str) {
} }
cur = *str; cur = *str;
} }
/*
* This can be empty in the case where there is no server
*/
host = cur;
if (*cur == '/') {
if (uri != NULL) {
if (uri->authority != NULL) xmlFree(uri->authority);
uri->authority = NULL;
if (uri->server != NULL) xmlFree(uri->server);
uri->server = NULL;
uri->port = 0;
}
return(0);
}
/* /*
* host part of hostport can derive either an IPV4 address * host part of hostport can derive either an IPV4 address
* or an unresolved name. Check the IP first, it easier to detect * or an unresolved name. Check the IP first, it easier to detect
* errors if wrong one * errors if wrong one
*/ */
host = cur;
if (IS_DIGIT(*cur)) { if (IS_DIGIT(*cur)) {
while(IS_DIGIT(*cur)) cur++; while(IS_DIGIT(*cur)) cur++;
if (*cur != '.') if (*cur != '.')

428
xpath.c
View File

@ -646,7 +646,7 @@ xmlXPathNewBoolean(int val) {
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) { if (ret == NULL) {
fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n"); fprintf(xmlXPathDebug, "xmlXPathNewBoolean: out of memory\n");
return(NULL); return(NULL);
} }
memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@ -669,7 +669,7 @@ xmlXPathNewString(const xmlChar *val) {
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) { if (ret == NULL) {
fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n"); fprintf(xmlXPathDebug, "xmlXPathNewString: out of memory\n");
return(NULL); return(NULL);
} }
memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@ -692,7 +692,7 @@ xmlXPathNewCString(const char *val) {
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) { if (ret == NULL) {
fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n"); fprintf(xmlXPathDebug, "xmlXPathNewCString: out of memory\n");
return(NULL); return(NULL);
} }
memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@ -716,7 +716,7 @@ xmlXPathNewNodeSet(xmlNodePtr val) {
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) { if (ret == NULL) {
fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n"); fprintf(xmlXPathDebug, "xmlXPathNewNodeSet: out of memory\n");
return(NULL); return(NULL);
} }
memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
@ -753,6 +753,29 @@ xmlXPathNewNodeSetList(xmlNodeSetPtr val) {
return(ret); return(ret);
} }
/**
* xmlXPathWrapNodeSet:
* @val: the NodePtr value
*
* Wrap the Nodeset @val in a new xmlXPathObjectPtr
*
* Returns the newly created object.
*/
xmlXPathObjectPtr
xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
xmlXPathObjectPtr ret;
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
if (ret == NULL) {
fprintf(xmlXPathDebug, "xmlXPathWrapNodeSet: out of memory\n");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
ret->type = XPATH_NODESET;
ret->nodesetval = val;
return(ret);
}
/** /**
* xmlXPathFreeNodeSetList: * xmlXPathFreeNodeSetList:
* @obj: an existing NodeSetList object * @obj: an existing NodeSetList object
@ -813,12 +836,7 @@ xmlXPathNewContext(xmlDocPtr doc) {
} }
memset(ret, 0 , (size_t) sizeof(xmlXPathContext)); memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
ret->doc = doc; ret->doc = doc;
/***********
ret->node = (xmlNodePtr) doc;
ret->nodelist = xmlXPathNodeSetCreate(ret->node);
***********/
ret->node = NULL; ret->node = NULL;
ret->nodelist = NULL;
ret->nb_variables = 0; ret->nb_variables = 0;
ret->max_variables = 0; ret->max_variables = 0;
@ -856,8 +874,6 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
if (ctxt->namespaces != NULL) if (ctxt->namespaces != NULL)
xmlFree(ctxt->namespaces); xmlFree(ctxt->namespaces);
if (ctxt->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->nodelist);
#ifdef DEBUG #ifdef DEBUG
memset(ctxt, 0xB , (size_t) sizeof(xmlXPathContext)); memset(ctxt, 0xB , (size_t) sizeof(xmlXPathContext));
#endif #endif
@ -870,14 +886,14 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
* * * *
************************************************************************/ ************************************************************************/
#define CHECK_CTXT \ #define CHECK_CTXT(ctxt) \
if (ctxt == NULL) { \ if (ctxt == NULL) { \
fprintf(xmlXPathDebug, "%s:%d Internal error: ctxt == NULL\n", \ fprintf(xmlXPathDebug, "%s:%d Internal error: ctxt == NULL\n", \
__FILE__, __LINE__); \ __FILE__, __LINE__); \
} \ } \
#define CHECK_CONTEXT \ #define CHECK_CONTEXT(ctxt) \
if (ctxt == NULL) { \ if (ctxt == NULL) { \
fprintf(xmlXPathDebug, "%s:%d Internal error: no context\n", \ fprintf(xmlXPathDebug, "%s:%d Internal error: no context\n", \
__FILE__, __LINE__); \ __FILE__, __LINE__); \
@ -1136,6 +1152,9 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
case XPATH_STRING: case XPATH_STRING:
ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval); ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval);
break; break;
case XPATH_USERS:
TODO
break;
} }
break; break;
case XPATH_BOOLEAN: case XPATH_BOOLEAN:
@ -1170,6 +1189,9 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
ret = 1; ret = 1;
ret = (arg1->boolval == ret); ret = (arg1->boolval == ret);
break; break;
case XPATH_USERS:
TODO
break;
} }
break; break;
case XPATH_NUMBER: case XPATH_NUMBER:
@ -1195,6 +1217,9 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
case XPATH_NUMBER: case XPATH_NUMBER:
ret = (arg1->floatval == arg2->floatval); ret = (arg1->floatval == arg2->floatval);
break; break;
case XPATH_USERS:
TODO
break;
} }
break; break;
case XPATH_STRING: case XPATH_STRING:
@ -1223,8 +1248,14 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
arg1 = valuePop(ctxt); arg1 = valuePop(ctxt);
ret = (arg1->floatval == arg2->floatval); ret = (arg1->floatval == arg2->floatval);
break; break;
case XPATH_USERS:
TODO
break;
} }
break; break;
case XPATH_USERS:
TODO
break;
} }
xmlXPathFreeObject(arg1); xmlXPathFreeObject(arg1);
xmlXPathFreeObject(arg2); xmlXPathFreeObject(arg2);
@ -1443,19 +1474,21 @@ xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
* * * *
************************************************************************/ ************************************************************************/
#define AXIS_ANCESTOR 1 typedef enum {
#define AXIS_ANCESTOR_OR_SELF 2 AXIS_ANCESTOR = 1,
#define AXIS_ATTRIBUTE 3 AXIS_ANCESTOR_OR_SELF,
#define AXIS_CHILD 4 AXIS_ATTRIBUTE,
#define AXIS_DESCENDANT 5 AXIS_CHILD,
#define AXIS_DESCENDANT_OR_SELF 6 AXIS_DESCENDANT,
#define AXIS_FOLLOWING 7 AXIS_DESCENDANT_OR_SELF,
#define AXIS_FOLLOWING_SIBLING 8 AXIS_FOLLOWING,
#define AXIS_NAMESPACE 9 AXIS_FOLLOWING_SIBLING,
#define AXIS_PARENT 10 AXIS_NAMESPACE,
#define AXIS_PRECEDING 11 AXIS_PARENT,
#define AXIS_PRECEDING_SIBLING 12 AXIS_PRECEDING,
#define AXIS_SELF 13 AXIS_PRECEDING_SIBLING,
AXIS_SELF
} xmlXPathAxisVal;
/* /*
* A traversal function enumerates nodes along an axis. * A traversal function enumerates nodes along an axis.
@ -1802,6 +1835,84 @@ xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
return(cur->prev); return(cur->prev);
} }
/**
* xmlXPathNextFollowing:
* @ctxt: the XPath Parser context
* @cur: the current node in the traversal
*
* Traversal function for the "following" direction
* The following axis contains all nodes in the same document as the context
* node that are after the context node in document order, excluding any
* descendants and excluding attribute nodes and namespace nodes; the nodes
* are ordered in document order
*
* Returns the next element following that axis
*/
xmlNodePtr
xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (cur != NULL && cur->children != NULL)
return cur->children ;
if (cur == NULL)
if ((cur = ctxt->context->node) == NULL) return(NULL) ;
do {
cur = cur->parent;
if (cur == NULL) return(NULL);
if (cur == ctxt->context->doc->children) return(NULL);
if (cur->next != NULL) {
cur = cur->next;
return(cur);
}
} while (cur != NULL);
return(cur);
}
/*
* returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
*/
static int
isAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
xmlNodePtr tmp ;
if (ancestor == NULL || node == NULL) return 0 ;
for (tmp = node ; tmp->parent != NULL ; tmp = tmp->parent) {
if (tmp->parent == ancestor)
return 1 ;
}
return 0 ;
}
/**
* xmlXPathNextPreceding:
* @ctxt: the XPath Parser context
* @cur: the current node in the traversal
*
* Traversal function for the "preceding" direction
* the preceding axis contains all nodes in the same document as the context
* node that are before the context node in document order, excluding any
* ancestors and excluding attribute nodes and namespace nodes; the nodes are
* ordered in reverse document order
*
* Returns the next element following that axis
*/
xmlNodePtr
xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if (cur == NULL)
cur = ctxt->context->node ;
do {
if (cur->prev != NULL) {
for (cur = cur->prev ; cur->last != NULL ; cur = cur->last)
;
return(cur) ;
}
cur = cur->parent;
if (cur == NULL) return(NULL);
if (cur == ctxt->context->doc->children) return(NULL);
} while (isAncestor(cur, ctxt->context->node));
return(cur);
}
#if 0
/* OLD VERSION, I was told they were broken ! */
/** /**
* xmlXPathNextFollowing: * xmlXPathNextFollowing:
* @ctxt: the XPath Parser context * @ctxt: the XPath Parser context
@ -1869,6 +1980,7 @@ xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
} while (cur != NULL); } while (cur != NULL);
return(cur); return(cur);
} }
#endif
/** /**
* xmlXPathNextNamespace: * xmlXPathNextNamespace:
@ -1921,24 +2033,32 @@ xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) {
* * * *
************************************************************************/ ************************************************************************/
#define NODE_TEST_NONE 0 typedef enum {
#define NODE_TEST_TYPE 1 NODE_TEST_NONE = 0,
#define NODE_TEST_PI 2 NODE_TEST_TYPE = 1,
#define NODE_TEST_ALL 3 NODE_TEST_PI = 2,
#define NODE_TEST_NS 4 NODE_TEST_ALL = 3,
#define NODE_TEST_NAME 5 NODE_TEST_NS = 4,
NODE_TEST_NAME = 5
} xmlXPathTestVal;
#define NODE_TYPE_COMMENT 50 typedef enum {
#define NODE_TYPE_TEXT 51 NODE_TYPE_COMMENT = 50,
#define NODE_TYPE_PI 52 NODE_TYPE_TEXT = 51,
#define NODE_TYPE_NODE 53 NODE_TYPE_PI = 52,
NODE_TYPE_NODE = 53
} xmlXPathTypeVal;
#define IS_FUNCTION 200 #define IS_FUNCTION 200
/** /**
* xmlXPathNodeCollectAndTest: * xmlXPathNodeCollectAndTest:
* @ctxt: the XPath Parser context * @ctxt: the XPath Parser context
* @cur: the current node to test * @axis: the XPath axis
* @test: the XPath test
* @type: the XPath type
* @prefix: the namesapce prefix if any
* @name: the name used in the search if any
* *
* This is the function implementing a step: based on the current list * This is the function implementing a step: based on the current list
* of nodes, it builds up a new list, looking at all nodes under that * of nodes, it builds up a new list, looking at all nodes under that
@ -1946,9 +2066,10 @@ xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) {
* *
* Returns the new NodeSet resulting from the search. * Returns the new NodeSet resulting from the search.
*/ */
xmlNodeSetPtr void
xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis, xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathAxisVal axis,
int test, int type, const xmlChar *prefix, const xmlChar *name) { xmlXPathTestVal test, xmlXPathTypeVal type,
const xmlChar *prefix, const xmlChar *name) {
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
int n = 0, t = 0; int n = 0, t = 0;
#endif #endif
@ -1956,17 +2077,12 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
xmlNodeSetPtr ret; xmlNodeSetPtr ret;
xmlXPathTraversalFunction next = NULL; xmlXPathTraversalFunction next = NULL;
xmlNodePtr cur = NULL; xmlNodePtr cur = NULL;
xmlXPathObjectPtr obj;
xmlNodeSetPtr nodelist;
CHECK_TYPE(XPATH_NODESET);
obj = valuePop(ctxt);
if (ctxt->context->nodelist == NULL) {
if (ctxt->context->node == NULL) {
fprintf(xmlXPathDebug,
"xmlXPathNodeCollectAndTest %s:%d : nodelist and node are NULL\n",
__FILE__, __LINE__);
return(NULL);
}
STRANGE
return(NULL);
}
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
fprintf(xmlXPathDebug, "new step : "); fprintf(xmlXPathDebug, "new step : ");
#endif #endif
@ -2039,11 +2155,14 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
#endif #endif
next = xmlXPathNextSelf; break; next = xmlXPathNextSelf; break;
} }
if (next == NULL) return(NULL); if (next == NULL)
return;
nodelist = obj->nodesetval;
ret = xmlXPathNodeSetCreate(NULL); ret = xmlXPathNodeSetCreate(NULL);
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
fprintf(xmlXPathDebug, " context contains %d nodes\n", fprintf(xmlXPathDebug, " context contains %d nodes\n",
ctxt->context->nodelist->nodeNr); nodelist->nodeNr);
switch (test) { switch (test) {
case NODE_TEST_NONE: case NODE_TEST_NONE:
fprintf(xmlXPathDebug, " searching for none !!!\n"); fprintf(xmlXPathDebug, " searching for none !!!\n");
@ -2070,8 +2189,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
} }
fprintf(xmlXPathDebug, "Testing : "); fprintf(xmlXPathDebug, "Testing : ");
#endif #endif
for (i = 0;i < ctxt->context->nodelist->nodeNr; i++) { for (i = 0;i < nodelist->nodeNr; i++) {
ctxt->context->node = ctxt->context->nodelist->nodeTab[i]; ctxt->context->node = nodelist->nodeTab[i];
cur = NULL; cur = NULL;
do { do {
@ -2084,7 +2203,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
switch (test) { switch (test) {
case NODE_TEST_NONE: case NODE_TEST_NONE:
STRANGE STRANGE
return(NULL); return;
case NODE_TEST_TYPE: case NODE_TEST_TYPE:
if ((cur->type == type) || if ((cur->type == type) ||
((type == XML_ELEMENT_NODE) && ((type == XML_ELEMENT_NODE) &&
@ -2129,7 +2248,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
((cur->ns != NULL) && ((cur->ns != NULL) &&
(xmlStrEqual(prefix, cur->ns->href)))))) { (xmlStrEqual(prefix, cur->ns->href)))))) {
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
n++; n++;
#endif #endif
xmlXPathNodeSetAdd(ret, cur); xmlXPathNodeSetAdd(ret, cur);
} }
@ -2138,7 +2257,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
xmlAttrPtr attr = (xmlAttrPtr) cur; xmlAttrPtr attr = (xmlAttrPtr) cur;
if (xmlStrEqual(name, attr->name)) { if (xmlStrEqual(name, attr->name)) {
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
n++; n++;
#endif #endif
xmlXPathNodeSetAdd(ret, cur); xmlXPathNodeSetAdd(ret, cur);
} }
@ -2148,7 +2267,6 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
break; break;
} }
break; break;
} }
} while (cur != NULL); } while (cur != NULL);
} }
@ -2156,7 +2274,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
fprintf(xmlXPathDebug, fprintf(xmlXPathDebug,
"\nExamined %d nodes, found %d nodes at that step\n", t, n); "\nExamined %d nodes, found %d nodes at that step\n", t, n);
#endif #endif
return(ret); xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPathWrapNodeSet(ret));
} }
@ -2174,10 +2293,15 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, int axis,
*/ */
void void
xmlXPathRoot(xmlXPathParserContextPtr ctxt) { xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
if (ctxt->context->nodelist != NULL) xmlXPathObjectPtr obj;
xmlXPathFreeNodeSet(ctxt->context->nodelist);
CHECK_TYPE(XPATH_NODESET);
obj = valuePop(ctxt);
ctxt->context->node = (xmlNodePtr) ctxt->context->doc; ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
ctxt->context->nodelist = xmlXPathNodeSetCreate(ctxt->context->node);
xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
} }
/************************************************************************ /************************************************************************
@ -2487,6 +2611,12 @@ xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
cur = valuePop(ctxt); cur = valuePop(ctxt);
if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND); if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
switch (cur->type) { switch (cur->type) {
case XPATH_UNDEFINED:
#ifdef DEBUG_EXPR
fprintf(xmlXPathDebug, "String: undefined\n");
#endif
valuePush(ctxt, xmlXPathNewCString(""));
break;
case XPATH_NODESET: case XPATH_NODESET:
if (cur->nodesetval->nodeNr == 0) { if (cur->nodesetval->nodeNr == 0) {
valuePush(ctxt, xmlXPathNewCString("")); valuePush(ctxt, xmlXPathNewCString(""));
@ -2522,6 +2652,10 @@ xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathFreeObject(cur); xmlXPathFreeObject(cur);
return; return;
} }
case XPATH_USERS:
TODO
valuePush(ctxt, xmlXPathNewCString(""));
break;
} }
STRANGE STRANGE
} }
@ -3084,6 +3218,12 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CHECK_ARITY(1); CHECK_ARITY(1);
cur = valuePop(ctxt); cur = valuePop(ctxt);
switch (cur->type) { switch (cur->type) {
case XPATH_UNDEFINED:
#ifdef DEBUG_EXPR
fprintf(xmlXPathDebug, "NUMBER: undefined\n");
#endif
valuePush(ctxt, xmlXPathNewFloat(0.0));
break;
case XPATH_NODESET: case XPATH_NODESET:
valuePush(ctxt, cur); valuePush(ctxt, cur);
xmlXPathStringFunction(ctxt, 1); xmlXPathStringFunction(ctxt, 1);
@ -3101,6 +3241,10 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
case XPATH_NUMBER: case XPATH_NUMBER:
valuePush(ctxt, cur); valuePush(ctxt, cur);
return; return;
case XPATH_USERS:
TODO
valuePush(ctxt, xmlXPathNewFloat(0.0));
break;
} }
STRANGE STRANGE
} }
@ -3800,8 +3944,6 @@ xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
void void
xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) { xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) {
xmlNodeSetPtr newset = NULL;
SKIP_BLANKS; SKIP_BLANKS;
if ((CUR == '$') || (CUR == '(') || (IS_DIGIT(CUR)) || if ((CUR == '$') || (CUR == '(') || (IS_DIGIT(CUR)) ||
(CUR == '\'') || (CUR == '"')) { (CUR == '\'') || (CUR == '"')) {
@ -3810,15 +3952,8 @@ xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) {
if ((CUR == '/') && (NXT(1) == '/')) { if ((CUR == '/') && (NXT(1) == '/')) {
SKIP(2); SKIP(2);
SKIP_BLANKS; SKIP_BLANKS;
if (ctxt->context->nodelist == NULL) { xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
STRANGE
xmlXPathRoot(ctxt);
}
newset = xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL); NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL);
if (ctxt->context->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->context->nodelist);
ctxt->context->nodelist = newset;
ctxt->context->node = NULL; ctxt->context->node = NULL;
xmlXPathEvalRelativeLocationPath(ctxt); xmlXPathEvalRelativeLocationPath(ctxt);
} else if (CUR == '/') { } else if (CUR == '/') {
@ -3836,8 +3971,11 @@ xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) {
if (name != NULL) if (name != NULL)
xmlFree(name); xmlFree(name);
if (ctxt->context->nodelist != NULL) #if 0
valuePush(ctxt, xmlXPathNewNodeSetList(ctxt->context->nodelist)); /* DV 1234 !!!!!!! */
if (ctxt->context->nodelist != NULL)
valuePush(ctxt, xmlXPathNewNodeSetList(ctxt->context->nodelist));
#endif
} }
} }
@ -3857,19 +3995,21 @@ xmlXPathEvalUnionExpr(xmlXPathParserContextPtr ctxt) {
CHECK_ERROR; CHECK_ERROR;
SKIP_BLANKS; SKIP_BLANKS;
if (CUR == '|') { if (CUR == '|') {
xmlNodeSetPtr old = ctxt->context->nodelist; xmlXPathObjectPtr obj1,obj2;
CHECK_TYPE(XPATH_NODESET);
obj1 = valuePop(ctxt);
valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
NEXT; NEXT;
SKIP_BLANKS; SKIP_BLANKS;
xmlXPathEvalPathExpr(ctxt); xmlXPathEvalPathExpr(ctxt);
if (ctxt->context->nodelist == NULL) CHECK_TYPE(XPATH_NODESET);
ctxt->context->nodelist = old; obj2 = valuePop(ctxt);
else { obj1->nodesetval = xmlXPathNodeSetMerge(obj1->nodesetval,
ctxt->context->nodelist = obj2->nodesetval);
xmlXPathNodeSetMerge(ctxt->context->nodelist, old); xmlXPathFreeObject(obj2);
xmlXPathFreeNodeSet(old);
}
} }
} }
@ -4182,6 +4322,7 @@ void
xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) { xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
const xmlChar *cur; const xmlChar *cur;
xmlXPathObjectPtr res; xmlXPathObjectPtr res;
xmlXPathObjectPtr obj, tmp;
xmlNodeSetPtr newset = NULL; xmlNodeSetPtr newset = NULL;
xmlNodeSetPtr oldset; xmlNodeSetPtr oldset;
int i; int i;
@ -4198,8 +4339,9 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
* expression for all the element in the set. use it to grow * expression for all the element in the set. use it to grow
* up a new set. * up a new set.
*/ */
oldset = ctxt->context->nodelist; CHECK_TYPE(XPATH_NODESET);
ctxt->context->nodelist = NULL; obj = valuePop(ctxt);
oldset = obj->nodesetval;
ctxt->context->node = NULL; ctxt->context->node = NULL;
if ((oldset == NULL) || (oldset->nodeNr == 0)) { if ((oldset == NULL) || (oldset->nodeNr == 0)) {
@ -4210,6 +4352,7 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
res = valuePop(ctxt); res = valuePop(ctxt);
if (res != NULL) if (res != NULL)
xmlXPathFreeObject(res); xmlXPathFreeObject(res);
valuePush(ctxt, obj);
} else { } else {
/* /*
* Save the expression pointer since we will have to evaluate * Save the expression pointer since we will have to evaluate
@ -4226,7 +4369,8 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
* in the nodeset. * in the nodeset.
*/ */
ctxt->context->node = oldset->nodeTab[i]; ctxt->context->node = oldset->nodeTab[i];
ctxt->context->nodelist = NULL; tmp = xmlXPathNewNodeSet(ctxt->context->node);
valuePush(ctxt, tmp);
ctxt->context->contextSize = oldset->nodeNr; ctxt->context->contextSize = oldset->nodeNr;
ctxt->context->proximityPosition = i + 1; ctxt->context->proximityPosition = i + 1;
@ -4241,8 +4385,16 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
if (xmlXPathEvaluatePredicateResult(ctxt, res)) { if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
} }
/*
* Cleanup
*/
if (res != NULL) if (res != NULL)
xmlXPathFreeObject(res); xmlXPathFreeObject(res);
if (ctxt->value == tmp) {
res = valuePop(ctxt);
xmlXPathFreeObject(res);
}
ctxt->context->node = NULL; ctxt->context->node = NULL;
} }
@ -4250,22 +4402,21 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
/* /*
* The result is used as the new evaluation set. * The result is used as the new evaluation set.
*/ */
ctxt->context->nodelist = newset; xmlXPathFreeObject(obj);
ctxt->context->node = NULL; ctxt->context->node = NULL;
ctxt->context->contextSize = -1; ctxt->context->contextSize = -1;
ctxt->context->proximityPosition = -1; ctxt->context->proximityPosition = -1;
valuePush(ctxt, xmlXPathWrapNodeSet(newset));
} }
if (CUR != ']') { if (CUR != ']') {
XP_ERROR(XPATH_INVALID_PREDICATE_ERROR); XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
} }
if (oldset != NULL)
xmlXPathFreeNodeSet(oldset);
NEXT; NEXT;
SKIP_BLANKS; SKIP_BLANKS;
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
fprintf(xmlXPathDebug, "After predicate : "); fprintf(xmlXPathDebug, "After predicate : ");
xmlXPathDebugNodeSet(xmlXPathDebug, ctxt->context->nodelist); xmlXPathDebugNodeSet(xmlXPathDebug, ctxt->context->value->nodesetval);
#endif #endif
} }
@ -4290,11 +4441,10 @@ void
xmlXPathEvalBasis(xmlXPathParserContextPtr ctxt) { xmlXPathEvalBasis(xmlXPathParserContextPtr ctxt) {
xmlChar *name = NULL; xmlChar *name = NULL;
xmlChar *prefix = NULL; xmlChar *prefix = NULL;
int type = 0; xmlXPathTypeVal type = 0;
int axis = AXIS_CHILD; /* the default on abbreviated syntax */ xmlXPathAxisVal axis = AXIS_CHILD; /* the default on abbreviated syntax */
int nodetest = NODE_TEST_NONE; xmlXPathTestVal nodetest = NODE_TEST_NONE;
int nodetype = 0; xmlElementType nodetype = 0;
xmlNodeSetPtr newset = NULL;
if (CUR == '@') { if (CUR == '@') {
NEXT; NEXT;
@ -4344,17 +4494,6 @@ xmlXPathEvalBasis(xmlXPathParserContextPtr ctxt) {
NEXT; NEXT;
xmlFree(name); xmlFree(name);
func(ctxt, nbargs); func(ctxt, nbargs);
if ((ctxt->value != top) &&
(ctxt->value != NULL) &&
(ctxt->value->type == XPATH_NODESET)) {
xmlXPathObjectPtr cur;
cur = valuePop(ctxt);
ctxt->context->nodelist = cur->nodesetval;
ctxt->context->node = NULL;
cur->nodesetval = NULL;
xmlXPathFreeObject(cur);
}
return; return;
} }
/* /*
@ -4522,15 +4661,11 @@ search_nodes:
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
fprintf(xmlXPathDebug, "Basis : computing new set\n"); fprintf(xmlXPathDebug, "Basis : computing new set\n");
#endif #endif
newset = xmlXPathNodeCollectAndTest(ctxt, axis, nodetest, nodetype, xmlXPathNodeCollectAndTest(ctxt, axis, nodetest, nodetype,
prefix, name); prefix, name);
if (ctxt->context->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->context->nodelist);
ctxt->context->nodelist = newset;
ctxt->context->node = NULL;
#ifdef DEBUG_STEP #ifdef DEBUG_STEP
fprintf(xmlXPathDebug, "Basis : "); fprintf(xmlXPathDebug, "Basis : ");
xmlXPathDebugNodeSet(stdout, ctxt->context->nodelist); xmlXPathDebugNodeSet(stdout, ctxt->context->value->nodesetval);
#endif #endif
if (name != NULL) xmlFree(name); if (name != NULL) xmlFree(name);
if (prefix != NULL) xmlFree(prefix); if (prefix != NULL) xmlFree(prefix);
@ -4559,22 +4694,12 @@ search_nodes:
*/ */
void void
xmlXPathEvalStep(xmlXPathParserContextPtr ctxt) { xmlXPathEvalStep(xmlXPathParserContextPtr ctxt) {
xmlNodeSetPtr newset = NULL;
SKIP_BLANKS; SKIP_BLANKS;
if ((CUR == '.') && (NXT(1) == '.')) { if ((CUR == '.') && (NXT(1) == '.')) {
SKIP(2); SKIP(2);
SKIP_BLANKS; SKIP_BLANKS;
if (ctxt->context->nodelist == NULL) { xmlXPathNodeCollectAndTest(ctxt, AXIS_PARENT,
STRANGE
xmlXPathRoot(ctxt);
}
newset = xmlXPathNodeCollectAndTest(ctxt, AXIS_PARENT,
NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL); NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL);
if (ctxt->context->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->context->nodelist);
ctxt->context->nodelist = newset;
ctxt->context->node = NULL;
} else if (CUR == '.') { } else if (CUR == '.') {
NEXT; NEXT;
SKIP_BLANKS; SKIP_BLANKS;
@ -4608,8 +4733,6 @@ xmlXPathEvalStep(xmlXPathParserContextPtr ctxt) {
*/ */
void void
xmlXPathEvalRelativeLocationPath(xmlXPathParserContextPtr ctxt) { xmlXPathEvalRelativeLocationPath(xmlXPathParserContextPtr ctxt) {
xmlNodeSetPtr newset = NULL;
SKIP_BLANKS; SKIP_BLANKS;
xmlXPathEvalStep(ctxt); xmlXPathEvalStep(ctxt);
SKIP_BLANKS; SKIP_BLANKS;
@ -4617,16 +4740,8 @@ xmlXPathEvalRelativeLocationPath(xmlXPathParserContextPtr ctxt) {
if ((CUR == '/') && (NXT(1) == '/')) { if ((CUR == '/') && (NXT(1) == '/')) {
SKIP(2); SKIP(2);
SKIP_BLANKS; SKIP_BLANKS;
if (ctxt->context->nodelist == NULL) { xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
STRANGE
xmlXPathRoot(ctxt);
}
newset = xmlXPathNodeCollectAndTest(ctxt, AXIS_DESCENDANT_OR_SELF,
NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL); NODE_TEST_TYPE, XML_ELEMENT_NODE, NULL, NULL);
if (ctxt->context->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->context->nodelist);
ctxt->context->nodelist = newset;
ctxt->context->node = NULL;
xmlXPathEvalStep(ctxt); xmlXPathEvalStep(ctxt);
} else if (CUR == '/') { } else if (CUR == '/') {
NEXT; NEXT;
@ -4658,8 +4773,6 @@ xmlXPathEvalRelativeLocationPath(xmlXPathParserContextPtr ctxt) {
*/ */
void void
xmlXPathEvalLocationPath(xmlXPathParserContextPtr ctxt) { xmlXPathEvalLocationPath(xmlXPathParserContextPtr ctxt) {
xmlNodeSetPtr newset = NULL;
SKIP_BLANKS; SKIP_BLANKS;
if (CUR != '/') { if (CUR != '/') {
xmlXPathEvalRelativeLocationPath(ctxt); xmlXPathEvalRelativeLocationPath(ctxt);
@ -4668,15 +4781,9 @@ xmlXPathEvalLocationPath(xmlXPathParserContextPtr ctxt) {
if ((CUR == '/') && (NXT(1) == '/')) { if ((CUR == '/') && (NXT(1) == '/')) {
SKIP(2); SKIP(2);
SKIP_BLANKS; SKIP_BLANKS;
if (ctxt->context->nodelist == NULL) xmlXPathNodeCollectAndTest(ctxt,
xmlXPathRoot(ctxt);
newset = xmlXPathNodeCollectAndTest(ctxt,
AXIS_DESCENDANT_OR_SELF, NODE_TEST_TYPE, AXIS_DESCENDANT_OR_SELF, NODE_TEST_TYPE,
XML_ELEMENT_NODE, NULL, NULL); XML_ELEMENT_NODE, NULL, NULL);
if (ctxt->context->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->context->nodelist);
ctxt->context->nodelist = newset;
ctxt->context->node = NULL;
xmlXPathEvalRelativeLocationPath(ctxt); xmlXPathEvalRelativeLocationPath(ctxt);
} else if (CUR == '/') { } else if (CUR == '/') {
NEXT; NEXT;
@ -4694,7 +4801,7 @@ xmlXPathEvalLocationPath(xmlXPathParserContextPtr ctxt) {
/** /**
* xmlXPathEval: * xmlXPathEval:
* @str: the XPath expression * @str: the XPath expression
* @ctxt: the XPath context * @ctx: the XPath context
* *
* Evaluate the XPath Location Path in the given context. * Evaluate the XPath Location Path in the given context.
* *
@ -4702,25 +4809,32 @@ xmlXPathEvalLocationPath(xmlXPathParserContextPtr ctxt) {
* the caller has to free the object. * the caller has to free the object.
*/ */
xmlXPathObjectPtr xmlXPathObjectPtr
xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctxt) { xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
xmlXPathParserContextPtr pctxt; xmlXPathParserContextPtr ctxt;
xmlXPathObjectPtr res = NULL, tmp; xmlXPathObjectPtr res = NULL, tmp;
int stack = 0; int stack = 0;
xmlXPathInit(); xmlXPathInit();
CHECK_CONTEXT CHECK_CONTEXT(ctx)
if (xmlXPathDebug == NULL) if (xmlXPathDebug == NULL)
xmlXPathDebug = stderr; xmlXPathDebug = stderr;
pctxt = xmlXPathNewParserContext(str, ctxt); ctxt = xmlXPathNewParserContext(str, ctx);
valuePush(ctxt, xmlXPathNewNodeSet(ctx->node));
if (str[0] == '/') if (str[0] == '/')
xmlXPathRoot(pctxt); xmlXPathRoot(ctxt);
xmlXPathEvalLocationPath(pctxt); xmlXPathEvalLocationPath(ctxt);
if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
fprintf(xmlXPathDebug,
"xmlXPathEval: evaluation failed to return a node set\n");
} else {
res = valuePop(ctxt);
}
/* TODO: cleanup nodelist, res = valuePop(pctxt); */
do { do {
tmp = valuePop(pctxt); tmp = valuePop(ctxt);
if (tmp != NULL) { if (tmp != NULL) {
xmlXPathFreeObject(tmp); xmlXPathFreeObject(tmp);
stack++; stack++;
@ -4730,12 +4844,12 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctxt) {
fprintf(xmlXPathDebug, "xmlXPathEval: %d object left on the stack\n", fprintf(xmlXPathDebug, "xmlXPathEval: %d object left on the stack\n",
stack); stack);
} }
if (pctxt->error == XPATH_EXPRESSION_OK) if (ctxt->error != XPATH_EXPRESSION_OK) {
res = xmlXPathNewNodeSetList(pctxt->context->nodelist); xmlXPathFreeObject(res);
else res = NULL;
res = NULL; }
xmlXPathFreeParserContext(pctxt); xmlXPathFreeParserContext(ctxt);
return(res); return(res);
} }
@ -4757,7 +4871,7 @@ xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
xmlXPathInit(); xmlXPathInit();
CHECK_CONTEXT CHECK_CONTEXT(ctxt)
if (xmlXPathDebug == NULL) if (xmlXPathDebug == NULL)
xmlXPathDebug = stderr; xmlXPathDebug = stderr;

View File

@ -143,7 +143,6 @@ struct _xmlXPathAxis {
struct _xmlXPathContext { struct _xmlXPathContext {
xmlDocPtr doc; /* The current document */ xmlDocPtr doc; /* The current document */
xmlNodePtr node; /* The current node */ xmlNodePtr node; /* The current node */
xmlNodeSetPtr nodelist; /* The current node list */
int nb_variables; /* number of defined variables */ int nb_variables; /* number of defined variables */
int max_variables; /* max number of variables */ int max_variables; /* max number of variables */