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:
11
ChangeLog
11
ChangeLog
@ -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>
|
||||
|
||||
* xmlschemas.c: added tests for xs:all to assure minOccurs
|
||||
|
@ -356,7 +356,7 @@ xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
|
||||
|
||||
/**
|
||||
* xmlSchemaNewSchema:
|
||||
* @ctxt: a schema validation context (optional)
|
||||
* @ctxt: a schema validation context
|
||||
*
|
||||
* Allocate a new Schema structure.
|
||||
*
|
||||
@ -402,7 +402,7 @@ xmlSchemaNewFacet(void)
|
||||
|
||||
/**
|
||||
* xmlSchemaNewAnnot:
|
||||
* @ctxt: a schema validation context (optional)
|
||||
* @ctxt: a schema validation context
|
||||
* @node: a node
|
||||
*
|
||||
* Allocate a new annotation structure.
|
||||
|
240
xpath.c
240
xpath.c
@ -175,7 +175,9 @@ static int xmlXPathDisableOptimizer = 0;
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
|
||||
*/
|
||||
static const char *xmlXPathErrorMessages[] = {
|
||||
"Ok\n",
|
||||
"Number encoding\n",
|
||||
@ -400,9 +402,9 @@ typedef enum {
|
||||
typedef struct _xmlXPathStepOp xmlXPathStepOp;
|
||||
typedef xmlXPathStepOp *xmlXPathStepOpPtr;
|
||||
struct _xmlXPathStepOp {
|
||||
xmlXPathOp op;
|
||||
int ch1;
|
||||
int ch2;
|
||||
xmlXPathOp op; /* The identifier of the operation */
|
||||
int ch1; /* First child */
|
||||
int ch2; /* Second child */
|
||||
int value;
|
||||
int value2;
|
||||
int value3;
|
||||
@ -413,11 +415,11 @@ struct _xmlXPathStepOp {
|
||||
};
|
||||
|
||||
struct _xmlXPathCompExpr {
|
||||
int nbStep;
|
||||
int maxStep;
|
||||
xmlXPathStepOp *steps; /* ops for computation */
|
||||
int last;
|
||||
xmlChar *expr;
|
||||
int nbStep; /* Number of steps in this expression */
|
||||
int maxStep; /* Maximum number of steps allocated */
|
||||
xmlXPathStepOp *steps; /* ops for computation of this expression */
|
||||
int last; /* index of last step in expression */
|
||||
xmlChar *expr; /* the expression being computed */
|
||||
#ifdef DEBUG_EVAL_COUNTS
|
||||
int nb;
|
||||
xmlChar *string;
|
||||
@ -516,7 +518,7 @@ xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
|
||||
* @value4: the first 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
|
||||
*/
|
||||
@ -564,7 +566,7 @@ xmlXPathCompSwap(xmlXPathStepOpPtr op) {
|
||||
#ifndef LIBXML_THREAD_ENABLED
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
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)
|
||||
|
||||
#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);
|
||||
return(0);
|
||||
}
|
||||
ret = xmlXPathCastToBoolean(obj);
|
||||
if (obj->type != XPATH_BOOLEAN)
|
||||
ret = xmlXPathCastToBoolean(obj);
|
||||
else
|
||||
ret = obj->boolval;
|
||||
xmlXPathFreeObject(obj);
|
||||
return(ret);
|
||||
}
|
||||
@ -1141,7 +1147,10 @@ xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(0);
|
||||
}
|
||||
ret = xmlXPathCastToNumber(obj);
|
||||
if (obj->type != XPATH_NUMBER)
|
||||
ret = xmlXPathCastToNumber(obj);
|
||||
else
|
||||
ret = obj->floatval;
|
||||
xmlXPathFreeObject(obj);
|
||||
return(ret);
|
||||
}
|
||||
@ -1165,7 +1174,7 @@ xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(NULL);
|
||||
}
|
||||
ret = xmlXPathCastToString(obj);
|
||||
ret = xmlXPathCastToString(obj); /* this does required strdup */
|
||||
/* TODO: needs refactoring somewhere else */
|
||||
if (obj->stringval == ret)
|
||||
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.
|
||||
* This stamps all the element nodes with the document order
|
||||
* Like for line information, the order is kept in the element->content
|
||||
* field, the value stored is actually - the node number (startting at -1)
|
||||
* to be able to differenciate from line numbers.
|
||||
* field, the value stored is actually - the node number (starting at -1)
|
||||
* 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.
|
||||
*/
|
||||
long
|
||||
@ -1469,7 +1478,7 @@ xmlXPathOrderDocElems(xmlDocPtr doc) {
|
||||
* Compare two nodes w.r.t document order
|
||||
*
|
||||
* 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
|
||||
xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
|
||||
@ -1662,9 +1671,9 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
|
||||
* xmlXPathNodeSetFreeNs:
|
||||
* @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
|
||||
* 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
|
||||
xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
|
||||
@ -1772,9 +1781,9 @@ xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
|
||||
(node->type != XML_ELEMENT_NODE))
|
||||
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++) {
|
||||
if ((cur->nodeTab[i] != NULL) &&
|
||||
@ -1830,9 +1839,9 @@ xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
return; /* an XSLT fake node */
|
||||
#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++)
|
||||
if (cur->nodeTab[i] == val) return;
|
||||
@ -1888,7 +1897,7 @@ xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
return; /* an XSLT fake node */
|
||||
#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
|
||||
*/
|
||||
@ -1942,12 +1951,12 @@ xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
|
||||
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;
|
||||
|
||||
for (i = 0;i < val2->nodeNr;i++) {
|
||||
/*
|
||||
* check against doublons
|
||||
* check against duplicates
|
||||
*/
|
||||
skip = 0;
|
||||
for (j = 0; j < initNr; j++) {
|
||||
@ -2025,7 +2034,7 @@ xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
|
||||
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++) {
|
||||
/*
|
||||
@ -2080,12 +2089,12 @@ xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
if (val == NULL) return;
|
||||
|
||||
/*
|
||||
* check against doublons
|
||||
* find node in nodeTab
|
||||
*/
|
||||
for (i = 0;i < cur->nodeNr;i++)
|
||||
if (cur->nodeTab[i] == val) break;
|
||||
|
||||
if (i >= cur->nodeNr) {
|
||||
if (i >= cur->nodeNr) { /* not found */
|
||||
#ifdef DEBUG
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
|
||||
@ -2134,7 +2143,7 @@ xmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
|
||||
if (obj->nodeTab != NULL) {
|
||||
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++)
|
||||
if ((obj->nodeTab[i] != NULL) &&
|
||||
(obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
|
||||
@ -2176,7 +2185,7 @@ xmlXPathFreeValueTree(xmlNodeSetPtr obj) {
|
||||
/**
|
||||
* xmlGenericErrorContextNodeSet:
|
||||
* @output: a FILE * for the output
|
||||
* @obj: the xmlNodeSetPtr to free
|
||||
* @obj: the xmlNodeSetPtr to display
|
||||
*
|
||||
* Quick display of a NodeSet
|
||||
*/
|
||||
@ -2235,7 +2244,7 @@ xmlXPathNewNodeSet(xmlNodePtr val) {
|
||||
ret->type = XPATH_NODESET;
|
||||
ret->boolval = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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:
|
||||
@ -4031,8 +4040,6 @@ xmlXPathNodeValHash(xmlNodePtr node) {
|
||||
break;
|
||||
}
|
||||
if ((string != NULL) && (string[0] != 0)) {
|
||||
if (string[0] == 0)
|
||||
return(0);
|
||||
if (len == 1) {
|
||||
return(ret + (((unsigned int) string[0]) << 8));
|
||||
}
|
||||
@ -4659,7 +4666,8 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
|
||||
/* no break on purpose */
|
||||
case XPATH_NUMBER:
|
||||
/* Hand check NaN and Infinity equalities */
|
||||
if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
|
||||
if (xmlXPathIsNaN(arg1->floatval) ||
|
||||
xmlXPathIsNaN(arg2->floatval)) {
|
||||
ret = 0;
|
||||
} else if (xmlXPathIsInf(arg1->floatval) == 1) {
|
||||
if (xmlXPathIsInf(arg2->floatval) == 1)
|
||||
@ -4719,7 +4727,8 @@ xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
|
||||
xmlXPathNumberFunction(ctxt, 1);
|
||||
arg1 = valuePop(ctxt);
|
||||
/* Hand check NaN and Infinity equalities */
|
||||
if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
|
||||
if (xmlXPathIsNaN(arg1->floatval) ||
|
||||
xmlXPathIsNaN(arg2->floatval)) {
|
||||
ret = 0;
|
||||
} else if (xmlXPathIsInf(arg1->floatval) == 1) {
|
||||
if (xmlXPathIsInf(arg2->floatval) == 1)
|
||||
@ -5539,7 +5548,7 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
|
||||
if ((ns->next != NULL) &&
|
||||
(ns->next->type != XML_NAMESPACE_DECL))
|
||||
return((xmlNodePtr) ns->next);
|
||||
/* Bad, how did that namespace ended-up there ? */
|
||||
/* Bad, how did that namespace end up here ? */
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
@ -5583,7 +5592,7 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
|
||||
if ((ns->next != NULL) &&
|
||||
(ns->next->type != XML_NAMESPACE_DECL))
|
||||
return((xmlNodePtr) ns->next);
|
||||
/* Bad, how did that namespace ended-up there ? */
|
||||
/* Bad, how did that namespace end up here ? */
|
||||
return(NULL);
|
||||
}
|
||||
case XML_DOCUMENT_NODE:
|
||||
@ -6295,7 +6304,7 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
|
||||
*
|
||||
* Implement the string() XPath function
|
||||
* 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
|
||||
* the node in the node-set that is first in document order.
|
||||
* 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
|
||||
* 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
|
||||
* negative zero nor NaN
|
||||
* - 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);
|
||||
cur = valuePop(ctxt);
|
||||
|
||||
if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
|
||||
valuePush(ctxt, xmlXPathNewFloat(0.0));
|
||||
} else {
|
||||
if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
|
||||
for (i = 0; i < cur->nodesetval->nodeNr; i++) {
|
||||
res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
|
||||
}
|
||||
valuePush(ctxt, xmlXPathNewFloat(res));
|
||||
}
|
||||
valuePush(ctxt, xmlXPathNewFloat(res));
|
||||
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.
|
||||
*/
|
||||
static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
|
||||
@ -7226,8 +7233,8 @@ xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
|
||||
}
|
||||
encoding_error:
|
||||
/*
|
||||
* If we detect an UTF8 error that probably mean that the
|
||||
* input encoding didn't get properly advertized in the
|
||||
* If we detect an UTF8 error that probably means that the
|
||||
* input encoding didn't get properly advertised in the
|
||||
* declaration header. Report the error and switch the encoding
|
||||
* to ISO-Latin-1 (if you don't like this policy, just declare the
|
||||
* encoding !)
|
||||
@ -7713,7 +7720,7 @@ xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
|
||||
* Parse a VariableReference, evaluate it and push it on the stack.
|
||||
*
|
||||
* 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,
|
||||
* and may also be of additional types not specified here.
|
||||
*
|
||||
@ -7994,7 +8001,7 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
|
||||
* - a element name
|
||||
* We do an a priori analysis here rather than having to
|
||||
* 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.
|
||||
*/
|
||||
SKIP_BLANKS;
|
||||
@ -8073,7 +8080,7 @@ xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
|
||||
}
|
||||
xmlFree(name);
|
||||
} else {
|
||||
/* make sure all cases are covered explicitely */
|
||||
/* make sure all cases are covered explicitly */
|
||||
XP_ERROR(XPATH_EXPR_ERROR);
|
||||
}
|
||||
}
|
||||
@ -8435,7 +8442,7 @@ xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
|
||||
* | 'processing-instruction'
|
||||
* | '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 *
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* Returns the number of node traversed
|
||||
* Returns the number of nodes traversed
|
||||
*/
|
||||
static int
|
||||
xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
|
||||
@ -9313,7 +9320,7 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* Returns the number of node traversed
|
||||
@ -9830,7 +9837,7 @@ xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
|
||||
* Evaluate the Precompiled XPath operation searching only the last
|
||||
* element in document order
|
||||
*
|
||||
* Returns the number of node traversed
|
||||
* Returns the number of nodes traversed
|
||||
*/
|
||||
static int
|
||||
xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
|
||||
@ -9965,7 +9972,7 @@ xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
|
||||
* @op: an XPath compiled operation
|
||||
*
|
||||
* Evaluate the Precompiled XPath operation
|
||||
* Returns the number of node traversed
|
||||
* Returns the number of nodes traversed
|
||||
*/
|
||||
static int
|
||||
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
||||
@ -10537,8 +10544,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
||||
CHECK_ERROR0;
|
||||
|
||||
/*
|
||||
* The result of the evaluation need to be tested to
|
||||
* decided whether the filter succeeded or not
|
||||
* The result of the evaluation needs to be tested to
|
||||
* decide whether the filter succeeded or not
|
||||
*/
|
||||
res = valuePop(ctxt);
|
||||
if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
|
||||
@ -10584,7 +10591,8 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
||||
xmlXPathObjectPtr range;
|
||||
xmlXPathObjectPtr res, obj;
|
||||
xmlXPathObjectPtr tmp;
|
||||
xmlLocationSetPtr newset = NULL;
|
||||
xmlLocationSetPtr newlocset = NULL;
|
||||
xmlLocationSetPtr oldlocset;
|
||||
xmlNodeSetPtr oldset;
|
||||
int i;
|
||||
|
||||
@ -10594,22 +10602,40 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
||||
if (op->ch2 == -1)
|
||||
return (total);
|
||||
|
||||
CHECK_TYPE0(XPATH_NODESET);
|
||||
obj = valuePop(ctxt);
|
||||
oldset = obj->nodesetval;
|
||||
ctxt->context->node = NULL;
|
||||
if (ctxt->value->type == XPATH_LOCATIONSET) {
|
||||
/*
|
||||
* Extract the old locset, and then evaluate the result of the
|
||||
* 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 < oldset->nodeNr; i++) {
|
||||
for (i = 0; i < oldlocset->locNr; i++) {
|
||||
/*
|
||||
* Run the evaluation with a node list made of a single item
|
||||
* in the nodeset.
|
||||
* Run the evaluation with a node list made of a
|
||||
* single item in the nodelocset.
|
||||
*/
|
||||
ctxt->context->node = oldset->nodeTab[i];
|
||||
ctxt->context->node = oldlocset->locTab[i]->user;
|
||||
tmp = xmlXPathNewNodeSet(ctxt->context->node);
|
||||
valuePush(ctxt, tmp);
|
||||
ctxt->context->contextSize = oldlocset->locNr;
|
||||
ctxt->context->proximityPosition = i + 1;
|
||||
|
||||
if (op->ch2 != -1)
|
||||
total +=
|
||||
@ -10622,11 +10648,10 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
||||
* decided whether the filter succeeded or not
|
||||
*/
|
||||
res = valuePop(ctxt);
|
||||
range =
|
||||
xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
|
||||
res);
|
||||
if (range != NULL) {
|
||||
xmlXPtrLocationSetAdd(newset, range);
|
||||
if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
|
||||
xmlXPtrLocationSetAdd(newlocset,
|
||||
xmlXPathObjectCopy
|
||||
(oldlocset->locTab[i]));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -10641,6 +10666,55 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
|
||||
|
||||
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->contextSize = -1;
|
||||
ctxt->context->proximityPosition = -1;
|
||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
|
||||
return (total);
|
||||
}
|
||||
#endif /* LIBXML_XPTR_ENABLED */
|
||||
@ -10771,6 +10845,14 @@ xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
|
||||
case XPATH_STRING:
|
||||
return((res->stringval != NULL) &&
|
||||
(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:
|
||||
STRANGE
|
||||
}
|
||||
|
@ -2771,6 +2771,10 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
XP_ERROR(XPATH_INVALID_TYPE)
|
||||
|
||||
set = valuePop(ctxt);
|
||||
newset = xmlXPtrLocationSetCreate(NULL);
|
||||
if (set->nodesetval == NULL) {
|
||||
goto error;
|
||||
}
|
||||
if (set->type == XPATH_NODESET) {
|
||||
xmlXPathObjectPtr tmp;
|
||||
|
||||
@ -2787,7 +2791,6 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
* The loop is to search for each element in the location set
|
||||
* the list of location set corresponding to that search
|
||||
*/
|
||||
newset = xmlXPtrLocationSetCreate(NULL);
|
||||
for (i = 0;i < oldset->locNr;i++) {
|
||||
#ifdef DEBUG_RANGES
|
||||
xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0);
|
||||
@ -2851,6 +2854,7 @@ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||
/*
|
||||
* Save the new value and cleanup
|
||||
*/
|
||||
error:
|
||||
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
|
||||
xmlXPathFreeObject(set);
|
||||
xmlXPathFreeObject(string);
|
||||
|
Reference in New Issue
Block a user