diff options
author | Daniel Veillard <veillard@src.gnome.org> | 1999-08-15 23:32:28 +0000 |
---|---|---|
committer | Daniel Veillard <veillard@src.gnome.org> | 1999-08-15 23:32:28 +0000 |
commit | 991e63d9cb0e9a4f65950ec67f56091a14289404 (patch) | |
tree | fc5b5698c2b2c2149294d599cfb1b1ef53e0b1d5 | |
parent | b556eb58649b0f59d55acd6a99e56ed1bf4c97e5 (diff) | |
download | libxml2-991e63d9cb0e9a4f65950ec67f56091a14289404.tar.gz |
More validity stuff (ID) and corrct version of equal and compare for XPath, Daniel
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | include/libxml/tree.h | 12 | ||||
-rw-r--r-- | include/libxml/valid.h | 20 | ||||
-rw-r--r-- | tree.h | 12 | ||||
-rw-r--r-- | valid.c | 194 | ||||
-rw-r--r-- | valid.h | 20 | ||||
-rw-r--r-- | xpath.c | 364 |
7 files changed, 581 insertions, 47 deletions
@@ -1,3 +1,9 @@ +Mon Aug 16 03:27:38 CEST 1999 + + * tree.h, valid.c, valid.h: more work on validity, IDs + * xpath.c: added/fixed comparidon and equlity, added a new isinf + definition for AIX + Sun Aug 15 21:15:17 CEST 1999 Daniel Veillard <Daniel.Veillard@w3.org> * Makefile.am libxml.spec.in: corrected missing xmlConf.sh in diff --git a/include/libxml/tree.h b/include/libxml/tree.h index a627d921..fa70ba37 100644 --- a/include/libxml/tree.h +++ b/include/libxml/tree.h @@ -197,6 +197,17 @@ typedef struct xmlAttr { typedef xmlAttr *xmlAttrPtr; /* + * An XML ID instance. + */ + +typedef struct xmlID { + struct xmlID *next; /* next ID */ + const CHAR *value; /* The ID name */ + xmlAttrPtr attr; /* The attribut holding it */ +} xmlID; +typedef xmlID *xmlIDPtr; + +/* * A node in an XML tree. */ typedef struct xmlNode { @@ -238,6 +249,7 @@ typedef struct xmlDoc { struct xmlDtd *extSubset; /* the document external subset */ struct xmlNs *oldNs; /* Global namespace, the old way */ struct xmlNode *root; /* the document tree */ + void *ids; /* Hash table for ID attributes if any */ } _xmlDoc; typedef _xmlDoc xmlDoc; typedef xmlDoc *xmlDocPtr; diff --git a/include/libxml/valid.h b/include/libxml/valid.h index 7d58459e..9afb2a0e 100644 --- a/include/libxml/valid.h +++ b/include/libxml/valid.h @@ -69,6 +69,20 @@ typedef struct xmlAttributeTable { } xmlAttributeTable; typedef xmlAttributeTable *xmlAttributeTablePtr; +/* + * ALl IDs attributes are stored in a table + * there is one table per document + */ + +#define XML_MIN_ID_TABLE 32 + +typedef struct xmlIDTable { + int nb_ids; /* number of ids stored */ + int max_ids; /* maximum number of ids */ + xmlIDPtr *table; /* the table of ids */ +} xmlIDTable; +typedef xmlIDTable *xmlIDTablePtr; + /* Notation */ xmlNotationPtr xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID, const CHAR *SystemID); @@ -101,6 +115,12 @@ xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table); void xmlFreeAttributeTable(xmlAttributeTablePtr table); void xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table); +/* IDs */ +xmlIDPtr xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + const CHAR *value, xmlAttrPtr attr); +xmlIDTablePtr xmlCopyIDTable(xmlIDTablePtr table); +void xmlFreeIDTable(xmlIDTablePtr table); + /** * The public function calls related to validity checking */ @@ -197,6 +197,17 @@ typedef struct xmlAttr { typedef xmlAttr *xmlAttrPtr; /* + * An XML ID instance. + */ + +typedef struct xmlID { + struct xmlID *next; /* next ID */ + const CHAR *value; /* The ID name */ + xmlAttrPtr attr; /* The attribut holding it */ +} xmlID; +typedef xmlID *xmlIDPtr; + +/* * A node in an XML tree. */ typedef struct xmlNode { @@ -238,6 +249,7 @@ typedef struct xmlDoc { struct xmlDtd *extSubset; /* the document external subset */ struct xmlNs *oldNs; /* Global namespace, the old way */ struct xmlNode *root; /* the document tree */ + void *ids; /* Hash table for ID attributes if any */ } _xmlDoc; typedef _xmlDoc xmlDoc; typedef xmlDoc *xmlDocPtr; @@ -1306,6 +1306,200 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { /************************************************************************ * * + * NOTATIONs * + * * + ************************************************************************/ +/** + * xmlCreateIDTable: + * + * create and initialize an empty id hash table. + * + * Returns the xmlIDTablePtr just created or NULL in case + * of error. + */ +xmlIDTablePtr +xmlCreateIDTable(void) { + xmlIDTablePtr ret; + + ret = (xmlIDTablePtr) + malloc(sizeof(xmlIDTable)); + if (ret == NULL) { + fprintf(stderr, "xmlCreateIDTable : malloc(%ld) failed\n", + (long)sizeof(xmlIDTable)); + return(NULL); + } + ret->max_ids = XML_MIN_NOTATION_TABLE; + ret->nb_ids = 0; + ret->table = (xmlIDPtr *) + malloc(ret->max_ids * sizeof(xmlIDPtr)); + if (ret == NULL) { + fprintf(stderr, "xmlCreateIDTable : malloc(%ld) failed\n", + ret->max_ids * (long)sizeof(xmlID)); + free(ret); + return(NULL); + } + return(ret); +} + + +/** + * xmlAddID: + * @ctxt: the validation context + * @doc: pointer to the document + * @value: the value name + * @attr: the attribute holding the ID + * + * Register a new id declaration + * + * Returns NULL if not, othervise the new xmlIDPtr + */ +xmlIDPtr +xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const CHAR *value, + xmlAttrPtr attr) { + xmlIDPtr ret, cur; + xmlIDTablePtr table; + int i; + + if (doc == NULL) { + fprintf(stderr, "xmlAddIDDecl: doc == NULL\n"); + return(NULL); + } + if (value == NULL) { + fprintf(stderr, "xmlAddIDDecl: value == NULL\n"); + return(NULL); + } + if (attr == NULL) { + fprintf(stderr, "xmlAddIDDecl: attr == NULL\n"); + return(NULL); + } + + /* + * Create the ID table if needed. + */ + table = doc->ids; + if (table == NULL) + table = doc->ids = xmlCreateIDTable(); + if (table == NULL) { + fprintf(stderr, "xmlAddID: Table creation failed!\n"); + return(NULL); + } + + /* + * Validity Check: + * Search the DTD for previous declarations of the ATTLIST + */ + for (i = 0;i < table->nb_ids;i++) { + cur = table->table[i]; + if (!xmlStrcmp(cur->value, value)) { + /* + * The id is already defined in this Dtd. + */ + VERROR(ctxt->userData, "ID %s already defined\n", value); + return(NULL); + } + } + + /* + * Grow the table, if needed. + */ + if (table->nb_ids >= table->max_ids) { + /* + * need more ids. + */ + table->max_ids *= 2; + table->table = (xmlIDPtr *) + realloc(table->table, table->max_ids * + sizeof(xmlIDPtr)); + if (table->table == NULL) { + fprintf(stderr, "xmlAddID: out of memory\n"); + return(NULL); + } + } + ret = (xmlIDPtr) malloc(sizeof(xmlID)); + if (ret == NULL) { + fprintf(stderr, "xmlAddID: out of memory\n"); + return(NULL); + } + table->table[table->nb_ids] = ret; + + /* + * fill the structure. + */ + ret->value = xmlStrdup(value); + ret->attr = attr; + table->nb_ids++; + + return(ret); +} + +/** + * xmlFreeID: + * @not: A id + * + * Deallocate the memory used by an id definition + */ +void +xmlFreeID(xmlIDPtr id) { + if (id == NULL) return; + if (id->value != NULL) + free((CHAR *) id->value); + memset(id, -1, sizeof(xmlID)); + free(id); +} + +/** + * xmlFreeIDTable: + * @table: An id table + * + * Deallocate the memory used by an ID hash table. + */ +void +xmlFreeIDTable(xmlIDTablePtr table) { + int i; + + if (table == NULL) return; + + for (i = 0;i < table->nb_ids;i++) { + xmlFreeID(table->table[i]); + } + free(table->table); + free(table); +} + +/** + * xmlIsID + * @doc: the document + * @elem: the element carrying the attribute + * @attr: the attribute + * + * Determine whether an attribute is of type ID. In case we have Dtd(s) + * then this is simple, otherwise we use an heuristic: name ID (upper + * or lowercase). + * + * Returns 0 or 1 depending on the lookup result + */ +int +xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr) { + if ((doc->intSubset == NULL) && (doc->extSubset == NULL)) { + if (((attr->name[0] == 'I') || (attr->name[0] == 'i')) && + ((attr->name[1] == 'D') || (attr->name[1] == 'd')) && + (attr->name[2] == 0)) return(1); + } else { + xmlAttributePtr attrDecl; + + attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name); + if ((attrDecl == NULL) && (doc->extSubset != NULL)) + attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, + attr->name); + + if ((attrDecl == NULL) || (attrDecl->type == XML_ATTRIBUTE_ID)) + return(1); + } + return(0); +} + +/************************************************************************ + * * * Routines for validity checking * * * ************************************************************************/ @@ -69,6 +69,20 @@ typedef struct xmlAttributeTable { } xmlAttributeTable; typedef xmlAttributeTable *xmlAttributeTablePtr; +/* + * ALl IDs attributes are stored in a table + * there is one table per document + */ + +#define XML_MIN_ID_TABLE 32 + +typedef struct xmlIDTable { + int nb_ids; /* number of ids stored */ + int max_ids; /* maximum number of ids */ + xmlIDPtr *table; /* the table of ids */ +} xmlIDTable; +typedef xmlIDTable *xmlIDTablePtr; + /* Notation */ xmlNotationPtr xmlAddNotationDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID, const CHAR *SystemID); @@ -101,6 +115,12 @@ xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table); void xmlFreeAttributeTable(xmlAttributeTablePtr table); void xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table); +/* IDs */ +xmlIDPtr xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + const CHAR *value, xmlAttrPtr attr); +xmlIDTablePtr xmlCopyIDTable(xmlIDTablePtr table); +void xmlFreeIDTable(xmlIDTablePtr table); + /** * The public function calls related to validity checking */ @@ -34,6 +34,7 @@ /* * Setup stuff for floating point + * The lack of portability of this section of the libc is annoying ! */ double xmlXPathNAN = 0; double xmlXPathPINF = 1; @@ -88,7 +89,16 @@ int isinf(double d) { } #elif defined(finite) || defined(HAVE_FINITE) int isinf(double x) { return !finite(x) && x==x; } -#endif /* ! HAVE_FPCLASS */ +#elif defined(HUGE_VAL) +static int isinf(double x) +{ + if (x == HUGE_VAL) + return(1); + if (x == -HUGE_VAL) + return(-1); + return(0); +} +#endif #endif /* ! HAVE_ISINF */ #endif /* ! defined(isinf) */ @@ -310,6 +320,10 @@ xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file, { xmlXPatherror(ctxt, __FILE__, __LINE__, X); \ ctxt->error = (X); return; } +#define ERROR0(X) \ + { xmlXPatherror(ctxt, __FILE__, __LINE__, X); \ + ctxt->error = (X); return(0); } + #define CHECK_TYPE(typeval) \ if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ ERROR(XPATH_INVALID_TYPE) \ @@ -875,69 +889,272 @@ void xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs); } /** + * xmlXPathEqualNodeSetString + * @arg: the nodeset object argument + * @str: the string to compare to. + * + * Implement the equal operation on XPath objects content: @arg1 == @arg2 + * If one object to be compared is a node-set and the other is a string, + * then the comparison will be true if and only if there is a node in + * the node-set such that the result of performing the comparison on the + * string-value of the node and the other string is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const CHAR *str) { + int i; + xmlNodeSetPtr ns; + CHAR *str2; + + if ((str == NULL) || (arg == NULL) || (arg->type != XPATH_NODESET)) + return(0); + ns = arg->nodesetval; + for (i = 0;i < ns->nodeNr;i++) { + str2 = xmlNodeGetContent(ns->nodeTab[i]); + if ((str2 != NULL) && (!xmlStrcmp(str, str2))) { + free(str2); + return(1); + } + free(str2); + } + return(0); +} + +/** + * xmlXPathEqualNodeSetFloat + * @arg: the nodeset object argument + * @f: the float to compare to + * + * Implement the equal operation on XPath objects content: @arg1 == @arg2 + * If one object to be compared is a node-set and the other is a number, + * then the comparison will be true if and only if there is a node in + * the node-set such that the result of performing the comparison on the + * number to be compared and on the result of converting the string-value + * of that node to a number using the number function is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathEqualNodeSetFloat(xmlXPathObjectPtr arg, float f) { + CHAR buf[100] = ""; + + if ((arg == NULL) || (arg->type != XPATH_NODESET)) + return(0); + + if (isnan(f)) + sprintf(buf, "NaN"); + else if (isinf(f) > 0) + sprintf(buf, "+Infinity"); + else if (isinf(f) < 0) + sprintf(buf, "-Infinity"); + else + sprintf(buf, "%0g", f); + + return(xmlXPathEqualNodeSetString(arg, buf)); +} + + +/** + * xmlXPathEqualNodeSets + * @arg1: first nodeset object argument + * @arg2: second nodeset object argument + * + * Implement the equal operation on XPath nodesets: @arg1 == @arg2 + * If both objects to be compared are node-sets, then the comparison + * will be true if and only if there is a node in the first node-set and + * a node in the second node-set such that the result of performing the + * comparison on the string-values of the two nodes is true. + * + * (needless to say, this is a costly operation) + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { + int i; + xmlNodeSetPtr ns; + CHAR *str; + + if ((arg1 == NULL) || (arg1->type != XPATH_NODESET)) + return(0); + if ((arg2 == NULL) || (arg2->type != XPATH_NODESET)) + return(0); + + ns = arg1->nodesetval; + for (i = 0;i < ns->nodeNr;i++) { + str = xmlNodeGetContent(ns->nodeTab[i]); + if ((str != NULL) && (xmlXPathEqualNodeSetString(arg2, str))) { + free(str); + return(1); + } + free(str); + } + return(0); +} + +/** * xmlXPathEqualValues: - * @arg1: first XPath object argument - * @arg2: second XPath object argument + * @ctxt: the XPath Parser context * * Implement the equal operation on XPath objects content: @arg1 == @arg2 * * Returns 0 or 1 depending on the results of the test. - * TODO: rewrite using the stack for evaluation */ int -xmlXPathEqualValues(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { +xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { + xmlXPathObjectPtr arg1, arg2; + int ret = 0; + + arg1 = valuePop(ctxt); + if (arg1 == NULL) + ERROR0(XPATH_INVALID_OPERAND); + + arg2 = valuePop(ctxt); + if (arg2 == NULL) { + xmlXPathFreeObject(arg1); + ERROR0(XPATH_INVALID_OPERAND); + } + if (arg1 == arg2) { #ifdef DEBUG_EXPR fprintf(xmlXPathDebug, "Equal: by pointer\n"); #endif return(1); } - if ((arg1 == NULL) || (arg2 == NULL)) { -#ifdef DEBUG_EXPR - fprintf(xmlXPathDebug, "Equal: arg NULL\n"); -#endif - return(0); - } - if (arg1->type != arg2->type) { - /* TODO : see 4.3 Boolean section !!!!!!!!!!! */ -#ifdef DEBUG_EXPR - fprintf(xmlXPathDebug, "Equal: distinct types\n"); -#endif - return(0); - } + switch (arg1->type) { case XPATH_UNDEFINED: #ifdef DEBUG_EXPR fprintf(xmlXPathDebug, "Equal: undefined\n"); #endif - return(0); + break; case XPATH_NODESET: - TODO /* compare nodesets */ + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + fprintf(xmlXPathDebug, "Equal: undefined\n"); +#endif + break; + case XPATH_NODESET: + ret = xmlXPathEqualNodeSets(arg1, arg2); + break; + case XPATH_BOOLEAN: + if ((arg1->nodesetval == NULL) || + (arg1->nodesetval->nodeNr == 0)) ret = 0; + else + ret = 1; + ret = (ret == arg2->boolval); + break; + case XPATH_NUMBER: + ret = xmlXPathEqualNodeSetFloat(arg1, arg2->floatval); + break; + case XPATH_STRING: + ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval); + break; + } break; case XPATH_BOOLEAN: + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + fprintf(xmlXPathDebug, "Equal: undefined\n"); +#endif + break; + case XPATH_NODESET: + if ((arg2->nodesetval == NULL) || + (arg2->nodesetval->nodeNr == 0)) ret = 0; + else + ret = 1; + break; + case XPATH_BOOLEAN: #ifdef DEBUG_EXPR - fprintf(xmlXPathDebug, "Equal: %d boolean %d \n", - arg1->boolval, arg2->boolval); + fprintf(xmlXPathDebug, "Equal: %d boolean %d \n", + arg1->boolval, arg2->boolval); #endif - return(arg1->boolval == arg2->boolval); + ret = (arg1->boolval == arg2->boolval); + break; + case XPATH_NUMBER: + if (arg2->floatval) ret = 1; + else ret = 0; + ret = (arg1->boolval == ret); + break; + case XPATH_STRING: + if ((arg2->stringval == NULL) || + (arg2->stringval[0] == 0)) ret = 0; + else + ret = 1; + ret = (arg1->boolval == ret); + break; + } + break; case XPATH_NUMBER: + switch (arg2->type) { + case XPATH_UNDEFINED: #ifdef DEBUG_EXPR - fprintf(xmlXPathDebug, "Equal: %f number %f \n", - arg1->floatval, arg2->floatval); + fprintf(xmlXPathDebug, "Equal: undefined\n"); #endif - return(arg1->floatval == arg2->floatval); + break; + case XPATH_NODESET: + ret = xmlXPathEqualNodeSetFloat(arg2, arg1->floatval); + break; + case XPATH_BOOLEAN: + if (arg1->floatval) ret = 1; + else ret = 0; + ret = (arg2->boolval == ret); + break; + case XPATH_STRING: + valuePush(ctxt, arg2); + xmlXPathNumberFunction(ctxt, 1); + arg2 = valuePop(ctxt); + /* no break on purpose */ + case XPATH_NUMBER: + ret = (arg1->floatval == arg2->floatval); + break; + } + break; case XPATH_STRING: + switch (arg2->type) { + case XPATH_UNDEFINED: +#ifdef DEBUG_EXPR + fprintf(xmlXPathDebug, "Equal: undefined\n"); +#endif + break; + case XPATH_NODESET: + ret = xmlXPathEqualNodeSetString(arg2, arg1->stringval); + break; + case XPATH_BOOLEAN: + if ((arg1->stringval == NULL) || + (arg1->stringval[0] == 0)) ret = 0; + else + ret = 1; + ret = (arg2->boolval == ret); + break; + case XPATH_STRING: + ret = !xmlStrcmp(arg1->stringval, arg2->stringval); + break; + case XPATH_NUMBER: + valuePush(ctxt, arg1); + xmlXPathNumberFunction(ctxt, 1); + arg1 = valuePop(ctxt); + ret = (arg1->floatval == arg2->floatval); + break; + } + break; #ifdef DEBUG_EXPR fprintf(xmlXPathDebug, "Equal: %s string %s \n", arg1->stringval, arg2->stringval); #endif - return(!xmlStrcmp(arg1->stringval, arg2->stringval)); + ret = !xmlStrcmp(arg1->stringval, arg2->stringval); } - return(1); + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(ret); } /** * xmlXPathCompareValues: + * @ctxt: the XPath Parser context * @inf: less than (1) or greater than (2) * @strict: is the comparison strict * @@ -947,11 +1164,71 @@ xmlXPathEqualValues(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { * @arg1 > @arg2 (0, 1, ... * @arg1 >= @arg2 (0, 0, ... * + * When neither object to be compared is a node-set and the operator is + * <=, <, >=, >, then the objects are compared by converted both objects + * to numbers and comparing the numbers according to IEEE 754. The < + * comparison will be true if and only if the first number is less than the + * second number. The <= comparison will be true if and only if the first + * number is less than or equal to the second number. The > comparison + * will be true if and only if the first number is greater than the second + * number. The >= comparison will be true if and only if the first number + * is greater than or equal to the second number. */ int -xmlXPathCompareValues(int inf, int strict) { - TODO /* compare */ - return(0); +xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { + int ret = 0; + xmlXPathObjectPtr arg1, arg2; + + arg2 = valuePop(ctxt); + if ((arg2 == NULL) || (arg2->type == XPATH_NODESET)) { + if (arg2 != NULL) + xmlXPathFreeObject(arg2); + ERROR0(XPATH_INVALID_OPERAND); + } + + arg1 = valuePop(ctxt); + if ((arg1 == NULL) || (arg1->type == XPATH_NODESET)) { + if (arg1 != NULL) + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + ERROR0(XPATH_INVALID_OPERAND); + } + + if (arg1->type != XPATH_NUMBER) { + valuePush(ctxt, arg1); + xmlXPathNumberFunction(ctxt, 1); + arg1 = valuePop(ctxt); + } + if (arg1->type != XPATH_NUMBER) { + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + ERROR0(XPATH_INVALID_OPERAND); + } + if (arg2->type != XPATH_NUMBER) { + valuePush(ctxt, arg2); + xmlXPathNumberFunction(ctxt, 1); + arg2 = valuePop(ctxt); + } + if (arg2->type != XPATH_NUMBER) { + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + ERROR0(XPATH_INVALID_OPERAND); + } + /* + * Add tests for infinity and nan + * => feedback on 3.4 for Inf and NaN + */ + if (inf && strict) + ret = (arg1->floatval < arg2->floatval); + else if (inf && !strict) + ret = (arg1->floatval <= arg2->floatval); + else if (!inf && strict) + ret = (arg1->floatval > arg2->floatval); + else if (!inf && !strict) + ret = (arg1->floatval >= arg2->floatval); + xmlXPathFreeObject(arg1); + xmlXPathFreeObject(arg2); + return(ret); } /** @@ -1416,8 +1693,11 @@ xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) { */ xmlAttrPtr xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlAttrPtr cur) { - if (cur == NULL) + if (cur == NULL) { + if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) + return(NULL); return(ctxt->context->node->properties); + } return(cur->next); } @@ -3005,13 +3285,6 @@ xmlXPathEvalFilterExpr(xmlXPathParserContextPtr ctxt) { CHECK_TYPE(XPATH_NODESET); - /****** - TODO: transition from PathExpr to Expr using paths ... - arg = valuePop(ctxt); - oldset = ctxt->context->nodeset; - ctxt->context->nodeset = arg->nodesetval; - ******/ - while (CUR == '[') { xmlXPathEvalPredicate(ctxt); } @@ -3230,7 +3503,7 @@ xmlXPathEvalRelationalExpr(xmlXPathParserContextPtr ctxt) { (CUR == '>') || ((CUR == '<') && (NXT(1) == '=')) || ((CUR == '>') && (NXT(1) == '='))) { - int inf, strict; + int inf, strict, ret; if (CUR == '<') inf = 1; else inf = 0; @@ -3240,7 +3513,8 @@ xmlXPathEvalRelationalExpr(xmlXPathParserContextPtr ctxt) { if (!strict) NEXT; xmlXPathEvalAdditiveExpr(ctxt); CHECK_ERROR; - xmlXPathCompareValues(inf, strict); + ret = xmlXPathCompareValues(ctxt, inf, strict); + valuePush(ctxt, xmlXPathNewBoolean(ret)); } } @@ -3265,7 +3539,7 @@ xmlXPathEvalEqualityExpr(xmlXPathParserContextPtr ctxt) { xmlXPathEvalRelationalExpr(ctxt); CHECK_ERROR; while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) { - xmlXPathObjectPtr arg1, arg2, res; + xmlXPathObjectPtr res; int eq, equal; if (CUR == '=') eq = 1; @@ -3274,14 +3548,10 @@ xmlXPathEvalEqualityExpr(xmlXPathParserContextPtr ctxt) { if (!eq) NEXT; xmlXPathEvalRelationalExpr(ctxt); CHECK_ERROR; - arg2 = valuePop(ctxt); - arg1 = valuePop(ctxt); - equal = xmlXPathEqualValues(arg1, arg2); + equal = xmlXPathEqualValues(ctxt); if (eq) res = xmlXPathNewBoolean(equal); else res = xmlXPathNewBoolean(!equal); valuePush(ctxt, res); - xmlXPathFreeObject(arg1); - xmlXPathFreeObject(arg2); } } |