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

edited a couple of comments in accordance with posting on the mailing list

* xmlschemas.c: edited a couple of comments in accordance with
  posting on the mailing list (no logic change)
* xpointer.c: working on Bug 129967, added check for NULL
  nodeset to prevent crash.  Further work required.
* xpath.c: working on Bug 129967, added code to handle
  XPATH_LOCATIONSET in RANGETO code, also added code to
  handle it in xmlXPathEvaluatePredicateResult.  Further
  work required.
This commit is contained in:
William M. Brack
2003-12-29 02:52:11 +00:00
parent b15351e54d
commit 081719182d
4 changed files with 179 additions and 82 deletions

View File

@ -1,3 +1,14 @@
Mon Dec 28 10:47:32 HKT 2003 William Brack <wbrack@mmm.com.hk>
* xmlschemas.c: edited a couple of comments in accordance with
posting on the mailing list (no logic change)
* xpointer.c: working on Bug 129967, added check for NULL
nodeset to prevent crash. Further work required.
* xpath.c: working on Bug 129967, added code to handle
XPATH_LOCATIONSET in RANGETO code, also added code to
handle it in xmlXPathEvaluatePredicateResult. Further
work required.
Sat Dec 27 12:32:58 HKT 2003 William Brack <wbrack@mmm.com.hk> Sat Dec 27 12:32:58 HKT 2003 William Brack <wbrack@mmm.com.hk>
* xmlschemas.c: added tests for xs:all to assure minOccurs * xmlschemas.c: added tests for xs:all to assure minOccurs

View File

@ -356,7 +356,7 @@ xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
/** /**
* xmlSchemaNewSchema: * xmlSchemaNewSchema:
* @ctxt: a schema validation context (optional) * @ctxt: a schema validation context
* *
* Allocate a new Schema structure. * Allocate a new Schema structure.
* *
@ -402,7 +402,7 @@ xmlSchemaNewFacet(void)
/** /**
* xmlSchemaNewAnnot: * xmlSchemaNewAnnot:
* @ctxt: a schema validation context (optional) * @ctxt: a schema validation context
* @node: a node * @node: a node
* *
* Allocate a new annotation structure. * Allocate a new annotation structure.

240
xpath.c
View File

@ -175,7 +175,9 @@ static int xmlXPathDisableOptimizer = 0;
* * * *
************************************************************************/ ************************************************************************/
/*
* The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
*/
static const char *xmlXPathErrorMessages[] = { static const char *xmlXPathErrorMessages[] = {
"Ok\n", "Ok\n",
"Number encoding\n", "Number encoding\n",
@ -400,9 +402,9 @@ typedef enum {
typedef struct _xmlXPathStepOp xmlXPathStepOp; typedef struct _xmlXPathStepOp xmlXPathStepOp;
typedef xmlXPathStepOp *xmlXPathStepOpPtr; typedef xmlXPathStepOp *xmlXPathStepOpPtr;
struct _xmlXPathStepOp { struct _xmlXPathStepOp {
xmlXPathOp op; xmlXPathOp op; /* The identifier of the operation */
int ch1; int ch1; /* First child */
int ch2; int ch2; /* Second child */
int value; int value;
int value2; int value2;
int value3; int value3;
@ -413,11 +415,11 @@ struct _xmlXPathStepOp {
}; };
struct _xmlXPathCompExpr { struct _xmlXPathCompExpr {
int nbStep; int nbStep; /* Number of steps in this expression */
int maxStep; int maxStep; /* Maximum number of steps allocated */
xmlXPathStepOp *steps; /* ops for computation */ xmlXPathStepOp *steps; /* ops for computation of this expression */
int last; int last; /* index of last step in expression */
xmlChar *expr; xmlChar *expr; /* the expression being computed */
#ifdef DEBUG_EVAL_COUNTS #ifdef DEBUG_EVAL_COUNTS
int nb; int nb;
xmlChar *string; xmlChar *string;
@ -516,7 +518,7 @@ xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
* @value4: the first string value * @value4: the first string value
* @value5: the second string value * @value5: the second string value
* *
* Add an step to an XPath Compiled Expression * Add a step to an XPath Compiled Expression
* *
* Returns -1 in case of failure, the index otherwise * Returns -1 in case of failure, the index otherwise
*/ */
@ -564,7 +566,7 @@ xmlXPathCompSwap(xmlXPathStepOpPtr op) {
#ifndef LIBXML_THREAD_ENABLED #ifndef LIBXML_THREAD_ENABLED
/* /*
* Since this manipulates possibly shared variables, this is * Since this manipulates possibly shared variables, this is
* disable if one detects that the library is used in a multithreaded * disabled if one detects that the library is used in a multithreaded
* application * application
*/ */
if (xmlXPathDisableOptimizer) if (xmlXPathDisableOptimizer)
@ -590,7 +592,8 @@ xmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
xmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL) xmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
#define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) \ #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) \
xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), (val), (val2), 0 ,NULL ,NULL) xmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), \
(val), (val2), 0 ,NULL ,NULL)
/************************************************************************ /************************************************************************
* * * *
@ -1117,7 +1120,10 @@ xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
return(0); return(0);
} }
ret = xmlXPathCastToBoolean(obj); if (obj->type != XPATH_BOOLEAN)
ret = xmlXPathCastToBoolean(obj);
else
ret = obj->boolval;
xmlXPathFreeObject(obj); xmlXPathFreeObject(obj);
return(ret); return(ret);
} }
@ -1141,7 +1147,10 @@ xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
return(0); return(0);
} }
ret = xmlXPathCastToNumber(obj); if (obj->type != XPATH_NUMBER)
ret = xmlXPathCastToNumber(obj);
else
ret = obj->floatval;
xmlXPathFreeObject(obj); xmlXPathFreeObject(obj);
return(ret); return(ret);
} }
@ -1165,7 +1174,7 @@ xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND); xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
return(NULL); return(NULL);
} }
ret = xmlXPathCastToString(obj); ret = xmlXPathCastToString(obj); /* this does required strdup */
/* TODO: needs refactoring somewhere else */ /* TODO: needs refactoring somewhere else */
if (obj->stringval == ret) if (obj->stringval == ret)
obj->stringval = NULL; obj->stringval = NULL;
@ -1418,10 +1427,10 @@ xmlXPathFormatNumber(double number, char buffer[], int buffersize)
* Call this routine to speed up XPath computation on static documents. * Call this routine to speed up XPath computation on static documents.
* This stamps all the element nodes with the document order * This stamps all the element nodes with the document order
* Like for line information, the order is kept in the element->content * Like for line information, the order is kept in the element->content
* field, the value stored is actually - the node number (startting at -1) * field, the value stored is actually - the node number (starting at -1)
* to be able to differenciate from line numbers. * to be able to differentiate from line numbers.
* *
* Returns the number of element found in the document or -1 in case * Returns the number of elements found in the document or -1 in case
* of error. * of error.
*/ */
long long
@ -1469,7 +1478,7 @@ xmlXPathOrderDocElems(xmlDocPtr doc) {
* Compare two nodes w.r.t document order * Compare two nodes w.r.t document order
* *
* Returns -2 in case of error 1 if first point < second point, 0 if * Returns -2 in case of error 1 if first point < second point, 0 if
* that's the same node, -1 otherwise * it's the same node, -1 otherwise
*/ */
int int
xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) { xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
@ -1662,9 +1671,9 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
* xmlXPathNodeSetFreeNs: * xmlXPathNodeSetFreeNs:
* @ns: the XPath namespace node found in a nodeset. * @ns: the XPath namespace node found in a nodeset.
* *
* Namespace node in libxml don't match the XPath semantic. In a node set * Namespace nodes in libxml don't match the XPath semantic. In a node set
* the namespace nodes are duplicated and the next pointer is set to the * the namespace nodes are duplicated and the next pointer is set to the
* parent node in the XPath semantic. Check if such a node need to be freed * parent node in the XPath semantic. Check if such a node needs to be freed
*/ */
void void
xmlXPathNodeSetFreeNs(xmlNsPtr ns) { xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
@ -1772,9 +1781,9 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
(node->type != XML_ELEMENT_NODE)) (node->type != XML_ELEMENT_NODE))
return; return;
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
/* /*
* check against doublons * prevent duplicates
*/ */
for (i = 0;i < cur->nodeNr;i++) { for (i = 0;i < cur->nodeNr;i++) {
if ((cur->nodeTab[i] != NULL) && if ((cur->nodeTab[i] != NULL) &&
@ -1830,9 +1839,9 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
return; /* an XSLT fake node */ return; /* an XSLT fake node */
#endif #endif
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
/* /*
* check against doublons * prevent duplcates
*/ */
for (i = 0;i < cur->nodeNr;i++) for (i = 0;i < cur->nodeNr;i++)
if (cur->nodeTab[i] == val) return; if (cur->nodeTab[i] == val) return;
@ -1888,7 +1897,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
return; /* an XSLT fake node */ return; /* an XSLT fake node */
#endif #endif
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
/* /*
* grow the nodeTab if needed * grow the nodeTab if needed
*/ */
@ -1942,12 +1951,12 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
val1 = xmlXPathNodeSetCreate(NULL); val1 = xmlXPathNodeSetCreate(NULL);
} }
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
initNr = val1->nodeNr; initNr = val1->nodeNr;
for (i = 0;i < val2->nodeNr;i++) { for (i = 0;i < val2->nodeNr;i++) {
/* /*
* check against doublons * check against duplicates
*/ */
skip = 0; skip = 0;
for (j = 0; j < initNr; j++) { for (j = 0; j < initNr; j++) {
@ -2025,7 +2034,7 @@ xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
val1 = xmlXPathNodeSetCreate(NULL); val1 = xmlXPathNodeSetCreate(NULL);
} }
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
for (i = 0;i < val2->nodeNr;i++) { for (i = 0;i < val2->nodeNr;i++) {
/* /*
@ -2080,12 +2089,12 @@ xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
if (val == NULL) return; if (val == NULL) return;
/* /*
* check against doublons * find node in nodeTab
*/ */
for (i = 0;i < cur->nodeNr;i++) for (i = 0;i < cur->nodeNr;i++)
if (cur->nodeTab[i] == val) break; if (cur->nodeTab[i] == val) break;
if (i >= cur->nodeNr) { if (i >= cur->nodeNr) { /* not found */
#ifdef DEBUG #ifdef DEBUG
xmlGenericError(xmlGenericErrorContext, xmlGenericError(xmlGenericErrorContext,
"xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n", "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
@ -2134,7 +2143,7 @@ xmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
if (obj->nodeTab != NULL) { if (obj->nodeTab != NULL) {
int i; int i;
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
for (i = 0;i < obj->nodeNr;i++) for (i = 0;i < obj->nodeNr;i++)
if ((obj->nodeTab[i] != NULL) && if ((obj->nodeTab[i] != NULL) &&
(obj->nodeTab[i]->type == XML_NAMESPACE_DECL)) (obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
@ -2176,7 +2185,7 @@ xmlXPathFreeValueTree(xmlNodeSetPtr obj) {
/** /**
* xmlGenericErrorContextNodeSet: * xmlGenericErrorContextNodeSet:
* @output: a FILE * for the output * @output: a FILE * for the output
* @obj: the xmlNodeSetPtr to free * @obj: the xmlNodeSetPtr to display
* *
* Quick display of a NodeSet * Quick display of a NodeSet
*/ */
@ -2235,7 +2244,7 @@ xmlXPathNewNodeSet(xmlNodePtr val) {
ret->type = XPATH_NODESET; ret->type = XPATH_NODESET;
ret->boolval = 0; ret->boolval = 0;
ret->nodesetval = xmlXPathNodeSetCreate(val); ret->nodesetval = xmlXPathNodeSetCreate(val);
/* @@ with_ns to check wether namespace nodes should be looked at @@ */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */
return(ret); return(ret);
} }
@ -2834,7 +2843,7 @@ xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
/************************************************************************ /************************************************************************
* * * *
* Routines to handle Variable * * Routines to handle Variables *
* * * *
************************************************************************/ ************************************************************************/
@ -3065,7 +3074,7 @@ xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
* * * *
************************************************************************/ ************************************************************************/
/* Allocations are terrible, one need to optimize all this !!! */ /* Allocations are terrible, one needs to optimize all this !!! */
/** /**
* xmlXPathNewFloat: * xmlXPathNewFloat:
@ -4031,8 +4040,6 @@ xmlXPathNodeValHash(xmlNodePtr node) {
break; break;
} }
if ((string != NULL) && (string[0] != 0)) { if ((string != NULL) && (string[0] != 0)) {
if (string[0] == 0)
return(0);
if (len == 1) { if (len == 1) {
return(ret + (((unsigned int) string[0]) << 8)); return(ret + (((unsigned int) string[0]) << 8));
} }
@ -4659,7 +4666,8 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
/* no break on purpose */ /* no break on purpose */
case XPATH_NUMBER: case XPATH_NUMBER:
/* Hand check NaN and Infinity equalities */ /* Hand check NaN and Infinity equalities */
if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) { if (xmlXPathIsNaN(arg1->floatval) ||
xmlXPathIsNaN(arg2->floatval)) {
ret = 0; ret = 0;
} else if (xmlXPathIsInf(arg1->floatval) == 1) { } else if (xmlXPathIsInf(arg1->floatval) == 1) {
if (xmlXPathIsInf(arg2->floatval) == 1) if (xmlXPathIsInf(arg2->floatval) == 1)
@ -4719,7 +4727,8 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
xmlXPathNumberFunction(ctxt, 1); xmlXPathNumberFunction(ctxt, 1);
arg1 = valuePop(ctxt); arg1 = valuePop(ctxt);
/* Hand check NaN and Infinity equalities */ /* Hand check NaN and Infinity equalities */
if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) { if (xmlXPathIsNaN(arg1->floatval) ||
xmlXPathIsNaN(arg2->floatval)) {
ret = 0; ret = 0;
} else if (xmlXPathIsInf(arg1->floatval) == 1) { } else if (xmlXPathIsInf(arg1->floatval) == 1) {
if (xmlXPathIsInf(arg2->floatval) == 1) if (xmlXPathIsInf(arg2->floatval) == 1)
@ -5539,7 +5548,7 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ns->next != NULL) && if ((ns->next != NULL) &&
(ns->next->type != XML_NAMESPACE_DECL)) (ns->next->type != XML_NAMESPACE_DECL))
return((xmlNodePtr) ns->next); return((xmlNodePtr) ns->next);
/* Bad, how did that namespace ended-up there ? */ /* Bad, how did that namespace end up here ? */
return(NULL); return(NULL);
} }
} }
@ -5583,7 +5592,7 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ns->next != NULL) && if ((ns->next != NULL) &&
(ns->next->type != XML_NAMESPACE_DECL)) (ns->next->type != XML_NAMESPACE_DECL))
return((xmlNodePtr) ns->next); return((xmlNodePtr) ns->next);
/* Bad, how did that namespace ended-up there ? */ /* Bad, how did that namespace end up here ? */
return(NULL); return(NULL);
} }
case XML_DOCUMENT_NODE: case XML_DOCUMENT_NODE:
@ -6295,7 +6304,7 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
* *
* Implement the string() XPath function * Implement the string() XPath function
* string string(object?) * string string(object?)
* he string function converts an object to a string as follows: * The string function converts an object to a string as follows:
* - A node-set is converted to a string by returning the value of * - A node-set is converted to a string by returning the value of
* the node in the node-set that is first in document order. * the node in the node-set that is first in document order.
* If the node-set is empty, an empty string is returned. * If the node-set is empty, an empty string is returned.
@ -6855,7 +6864,7 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
* *
* Implement the boolean() XPath function * Implement the boolean() XPath function
* boolean boolean(object) * boolean boolean(object)
* he boolean function converts its argument to a boolean as follows: * The boolean function converts its argument to a boolean as follows:
* - a number is true if and only if it is neither positive or * - a number is true if and only if it is neither positive or
* negative zero nor NaN * negative zero nor NaN
* - a node-set is true if and only if it is non-empty * - a node-set is true if and only if it is non-empty
@ -7019,14 +7028,12 @@ xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
XP_ERROR(XPATH_INVALID_TYPE); XP_ERROR(XPATH_INVALID_TYPE);
cur = valuePop(ctxt); cur = valuePop(ctxt);
if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) { if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
valuePush(ctxt, xmlXPathNewFloat(0.0));
} else {
for (i = 0; i < cur->nodesetval->nodeNr; i++) { for (i = 0; i < cur->nodesetval->nodeNr; i++) {
res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]); res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
} }
valuePush(ctxt, xmlXPathNewFloat(res));
} }
valuePush(ctxt, xmlXPathNewFloat(res));
xmlXPathFreeObject(cur); xmlXPathFreeObject(cur);
} }
@ -7141,7 +7148,7 @@ xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
************************************************************************/ ************************************************************************/
/* /*
* a couple of forward declarations since we use a recursive call based * a few forward declarations since we use a recursive call based
* implementation. * implementation.
*/ */
static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt); static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
@ -7226,8 +7233,8 @@ xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
} }
encoding_error: encoding_error:
/* /*
* If we detect an UTF8 error that probably mean that the * If we detect an UTF8 error that probably means that the
* input encoding didn't get properly advertized in the * input encoding didn't get properly advertised in the
* declaration header. Report the error and switch the encoding * declaration header. Report the error and switch the encoding
* to ISO-Latin-1 (if you don't like this policy, just declare the * to ISO-Latin-1 (if you don't like this policy, just declare the
* encoding !) * encoding !)
@ -7713,7 +7720,7 @@ xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
* Parse a VariableReference, evaluate it and push it on the stack. * Parse a VariableReference, evaluate it and push it on the stack.
* *
* The variable bindings consist of a mapping from variable names * The variable bindings consist of a mapping from variable names
* to variable values. The value of a variable is an object, which * to variable values. The value of a variable is an object, which can be
* of any of the types that are possible for the value of an expression, * of any of the types that are possible for the value of an expression,
* and may also be of additional types not specified here. * and may also be of additional types not specified here.
* *
@ -7994,7 +8001,7 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
* - a element name * - a element name
* We do an a priori analysis here rather than having to * We do an a priori analysis here rather than having to
* maintain parsed token content through the recursive function * maintain parsed token content through the recursive function
* calls. This looks uglier but makes the code quite easier to * calls. This looks uglier but makes the code easier to
* read/write/debug. * read/write/debug.
*/ */
SKIP_BLANKS; SKIP_BLANKS;
@ -8073,7 +8080,7 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
} }
xmlFree(name); xmlFree(name);
} else { } else {
/* make sure all cases are covered explicitely */ /* make sure all cases are covered explicitly */
XP_ERROR(XPATH_EXPR_ERROR); XP_ERROR(XPATH_EXPR_ERROR);
} }
} }
@ -8435,7 +8442,7 @@ xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
* | 'processing-instruction' * | 'processing-instruction'
* | 'node' * | 'node'
* *
* Returns the name found and update @test, @type and @prefix appropriately * Returns the name found and updates @test, @type and @prefix appropriately
*/ */
static xmlChar * static xmlChar *
xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test, xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
@ -8891,11 +8898,11 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
* *
* 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
* axis and selecting them it also do the predicate filtering * axis and selecting them. It also does the predicate filtering
* *
* Pushes the new NodeSet resulting from the search. * Pushes the new NodeSet resulting from the search.
* *
* Returns the number of node traversed * Returns the number of nodes traversed
*/ */
static int static int
xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
@ -9313,7 +9320,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
* *
* 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
* axis and selecting them it also do the predicate filtering * axis and selecting them. It also does the predicate filtering
* *
* Pushes the new NodeSet resulting from the search. * Pushes the new NodeSet resulting from the search.
* Returns the number of node traversed * Returns the number of node traversed
@ -9830,7 +9837,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
* Evaluate the Precompiled XPath operation searching only the last * Evaluate the Precompiled XPath operation searching only the last
* element in document order * element in document order
* *
* Returns the number of node traversed * Returns the number of nodes traversed
*/ */
static int static int
xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
@ -9965,7 +9972,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
* @op: an XPath compiled operation * @op: an XPath compiled operation
* *
* Evaluate the Precompiled XPath operation * Evaluate the Precompiled XPath operation
* Returns the number of node traversed * Returns the number of nodes traversed
*/ */
static int static int
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
@ -10537,8 +10544,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
CHECK_ERROR0; CHECK_ERROR0;
/* /*
* The result of the evaluation need to be tested to * The result of the evaluation needs to be tested to
* decided whether the filter succeeded or not * decide whether the filter succeeded or not
*/ */
res = valuePop(ctxt); res = valuePop(ctxt);
if (xmlXPathEvaluatePredicateResult(ctxt, res)) { if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
@ -10584,7 +10591,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
xmlXPathObjectPtr range; xmlXPathObjectPtr range;
xmlXPathObjectPtr res, obj; xmlXPathObjectPtr res, obj;
xmlXPathObjectPtr tmp; xmlXPathObjectPtr tmp;
xmlLocationSetPtr newset = NULL; xmlLocationSetPtr newlocset = NULL;
xmlLocationSetPtr oldlocset;
xmlNodeSetPtr oldset; xmlNodeSetPtr oldset;
int i; int i;
@ -10594,22 +10602,40 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
if (op->ch2 == -1) if (op->ch2 == -1)
return (total); return (total);
CHECK_TYPE0(XPATH_NODESET); if (ctxt->value->type == XPATH_LOCATIONSET) {
obj = valuePop(ctxt); /*
oldset = obj->nodesetval; * Extract the old locset, and then evaluate the result of the
ctxt->context->node = NULL; * expression for all the element in the locset. use it to grow
* up a new locset.
*/
CHECK_TYPE0(XPATH_LOCATIONSET);
obj = valuePop(ctxt);
oldlocset = obj->user;
ctxt->context->node = NULL;
newset = xmlXPtrLocationSetCreate(NULL); if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
ctxt->context->contextSize = 0;
ctxt->context->proximityPosition = 0;
total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]);
res = valuePop(ctxt);
if (res != NULL)
xmlXPathFreeObject(res);
valuePush(ctxt, obj);
CHECK_ERROR0;
return (total);
}
newlocset = xmlXPtrLocationSetCreate(NULL);
if (oldset != NULL) { for (i = 0; i < oldlocset->locNr; i++) {
for (i = 0; i < oldset->nodeNr; i++) {
/* /*
* Run the evaluation with a node list made of a single item * Run the evaluation with a node list made of a
* in the nodeset. * single item in the nodelocset.
*/ */
ctxt->context->node = oldset->nodeTab[i]; ctxt->context->node = oldlocset->locTab[i]->user;
tmp = xmlXPathNewNodeSet(ctxt->context->node); tmp = xmlXPathNewNodeSet(ctxt->context->node);
valuePush(ctxt, tmp); valuePush(ctxt, tmp);
ctxt->context->contextSize = oldlocset->locNr;
ctxt->context->proximityPosition = i + 1;
if (op->ch2 != -1) if (op->ch2 != -1)
total += total +=
@ -10622,11 +10648,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
* decided whether the filter succeeded or not * decided whether the filter succeeded or not
*/ */
res = valuePop(ctxt); res = valuePop(ctxt);
range = if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
xmlXPtrNewRangeNodeObject(oldset->nodeTab[i], xmlXPtrLocationSetAdd(newlocset,
res); xmlXPathObjectCopy
if (range != NULL) { (oldlocset->locTab[i]));
xmlXPtrLocationSetAdd(newset, range);
} }
/* /*
@ -10641,6 +10666,55 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
ctxt->context->node = NULL; ctxt->context->node = NULL;
} }
} else { /* Not a location set */
CHECK_TYPE0(XPATH_NODESET);
obj = valuePop(ctxt);
oldset = obj->nodesetval;
ctxt->context->node = NULL;
newlocset = xmlXPtrLocationSetCreate(NULL);
if (oldset != NULL) {
for (i = 0; i < oldset->nodeNr; i++) {
/*
* Run the evaluation with a node list made of a single item
* in the nodeset.
*/
ctxt->context->node = oldset->nodeTab[i];
tmp = xmlXPathNewNodeSet(ctxt->context->node);
valuePush(ctxt, tmp);
if (op->ch2 != -1)
total +=
xmlXPathCompOpEval(ctxt,
&comp->steps[op->ch2]);
CHECK_ERROR0;
/*
* The result of the evaluation need to be tested to
* decided whether the filter succeeded or not
*/
res = valuePop(ctxt);
range =
xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
res);
if (range != NULL) {
xmlXPtrLocationSetAdd(newlocset, range);
}
/*
* Cleanup
*/
if (res != NULL)
xmlXPathFreeObject(res);
if (ctxt->value == tmp) {
res = valuePop(ctxt);
xmlXPathFreeObject(res);
}
ctxt->context->node = NULL;
}
}
} }
/* /*
@ -10650,7 +10724,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
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, xmlXPtrWrapLocationSet(newset)); valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
return (total); return (total);
} }
#endif /* LIBXML_XPTR_ENABLED */ #endif /* LIBXML_XPTR_ENABLED */
@ -10771,6 +10845,14 @@ xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
case XPATH_STRING: case XPATH_STRING:
return((res->stringval != NULL) && return((res->stringval != NULL) &&
(xmlStrlen(res->stringval) != 0)); (xmlStrlen(res->stringval) != 0));
#ifdef LIBXML_XPTR_ENABLED
case XPATH_LOCATIONSET:{
xmlLocationSetPtr ptr = res->user;
if (ptr == NULL)
return(0);
return (ptr->locNr != 0);
}
#endif
default: default:
STRANGE STRANGE
} }

View File

@ -2771,6 +2771,10 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
XP_ERROR(XPATH_INVALID_TYPE) XP_ERROR(XPATH_INVALID_TYPE)
set = valuePop(ctxt); set = valuePop(ctxt);
newset = xmlXPtrLocationSetCreate(NULL);
if (set->nodesetval == NULL) {
goto error;
}
if (set->type == XPATH_NODESET) { if (set->type == XPATH_NODESET) {
xmlXPathObjectPtr tmp; xmlXPathObjectPtr tmp;
@ -2787,7 +2791,6 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
* The loop is to search for each element in the location set * The loop is to search for each element in the location set
* the list of location set corresponding to that search * the list of location set corresponding to that search
*/ */
newset = xmlXPtrLocationSetCreate(NULL);
for (i = 0;i < oldset->locNr;i++) { for (i = 0;i < oldset->locNr;i++) {
#ifdef DEBUG_RANGES #ifdef DEBUG_RANGES
xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0); xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0);
@ -2851,6 +2854,7 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
/* /*
* Save the new value and cleanup * Save the new value and cleanup
*/ */
error:
valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
xmlXPathFreeObject(set); xmlXPathFreeObject(set);
xmlXPathFreeObject(string); xmlXPathFreeObject(string);