mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-29 11:41:22 +03:00
More cleanups, XSLT induced, start looking okay:
- xpath.[ch]: still a lot of cleanup based on XSLT, added xmlXPathConvert{String,Number,Boolean} to be able to make type casts without a context stack, fixed some implementation problems related to the absence of context at parse-time, added xmlXPathEvalPredicate() and xmlXPathFreeCompExpr() in the public API too - xpointer.c xpathInternals.h: we need to know at parse time whether we are compiling an XPointer Daniel
This commit is contained in:
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
Mon Mar 19 16:50:52 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* xpath.[ch]: still a lot of cleanup based on XSLT, added
|
||||||
|
xmlXPathConvert{String,Number,Boolean} to be able to make
|
||||||
|
type casts without a context stack, fixed some implementation
|
||||||
|
problems related to the absence of context at parse-time,
|
||||||
|
added xmlXPathEvalPredicate() and xmlXPathFreeCompExpr()
|
||||||
|
in the public API too
|
||||||
|
* xpointer.c xpathInternals.h: we need to know at parse time
|
||||||
|
whether we are compiling an XPointer
|
||||||
|
|
||||||
Mon Mar 19 11:54:31 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Mon Mar 19 11:54:31 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* xpath.[ch] xpointer.c: restaured the Binary and API compatibility
|
* xpath.[ch] xpointer.c: restaured the Binary and API compatibility
|
||||||
|
@ -244,7 +244,7 @@ struct _xmlXPathParserContext {
|
|||||||
xmlXPathObjectPtr *valueTab; /* stack of values */
|
xmlXPathObjectPtr *valueTab; /* stack of values */
|
||||||
|
|
||||||
xmlXPathCompExprPtr comp; /* the precompiled expression */
|
xmlXPathCompExprPtr comp; /* the precompiled expression */
|
||||||
|
int xptr; /* it this an XPointer expression */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -271,6 +271,12 @@ void xmlXPathFreeNodeSet (xmlNodeSetPtr obj);
|
|||||||
xmlXPathObjectPtr xmlXPathObjectCopy (xmlXPathObjectPtr val);
|
xmlXPathObjectPtr xmlXPathObjectCopy (xmlXPathObjectPtr val);
|
||||||
int xmlXPathCmpNodes (xmlNodePtr node1,
|
int xmlXPathCmpNodes (xmlNodePtr node1,
|
||||||
xmlNodePtr node2);
|
xmlNodePtr node2);
|
||||||
|
/**
|
||||||
|
* Conversion functions to basic types
|
||||||
|
*/
|
||||||
|
xmlXPathObjectPtr xmlXPathConvertBoolean (xmlXPathObjectPtr val);
|
||||||
|
xmlXPathObjectPtr xmlXPathConvertNumber (xmlXPathObjectPtr val);
|
||||||
|
xmlXPathObjectPtr xmlXPathConvertString (xmlXPathObjectPtr val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context handling
|
* Context handling
|
||||||
@ -288,13 +294,15 @@ xmlXPathObjectPtr xmlXPathEvalXPtrExpr (const xmlChar *str,
|
|||||||
xmlXPathContextPtr ctxt);
|
xmlXPathContextPtr ctxt);
|
||||||
xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
|
xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
|
||||||
xmlXPathContextPtr ctxt);
|
xmlXPathContextPtr ctxt);
|
||||||
|
int xmlXPathEvalPredicate (xmlXPathContextPtr ctxt,
|
||||||
|
xmlXPathObjectPtr res);
|
||||||
/**
|
/**
|
||||||
* Separate compilation/evaluation entry points
|
* Separate compilation/evaluation entry points
|
||||||
*/
|
*/
|
||||||
xmlXPathCompExprPtr xmlXPathCompile (const xmlChar *str);
|
xmlXPathCompExprPtr xmlXPathCompile (const xmlChar *str);
|
||||||
xmlXPathObjectPtr xmlXPathCompiledEval (xmlXPathCompExprPtr comp,
|
xmlXPathObjectPtr xmlXPathCompiledEval (xmlXPathCompExprPtr comp,
|
||||||
xmlXPathContextPtr ctx);
|
xmlXPathContextPtr ctx);
|
||||||
|
void xmlXPathFreeCompExpr (xmlXPathCompExprPtr comp);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
379
xpath.c
379
xpath.c
@ -2351,6 +2351,7 @@ xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
|
|||||||
ret->valueMax = 10;
|
ret->valueMax = 10;
|
||||||
ret->value = NULL;
|
ret->value = NULL;
|
||||||
|
|
||||||
|
ret->context = ctxt;
|
||||||
ret->comp = comp;
|
ret->comp = comp;
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
@ -4444,6 +4445,71 @@ xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
xmlXPathFreeObject(cur);
|
xmlXPathFreeObject(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPathConvertString:
|
||||||
|
* @val: an XPath object
|
||||||
|
*
|
||||||
|
* Converts an existing object to its string() equivalent
|
||||||
|
*
|
||||||
|
* Returns the new object, the old one is freed (or the operation
|
||||||
|
* is done directly on @val)
|
||||||
|
*/
|
||||||
|
xmlXPathObjectPtr
|
||||||
|
xmlXPathConvertString(xmlXPathObjectPtr val) {
|
||||||
|
xmlXPathObjectPtr ret;
|
||||||
|
|
||||||
|
if (val == NULL)
|
||||||
|
return(xmlXPathNewCString(""));
|
||||||
|
switch (val->type) {
|
||||||
|
case XPATH_UNDEFINED:
|
||||||
|
#ifdef DEBUG_EXPR
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
|
||||||
|
#endif
|
||||||
|
ret = xmlXPathNewCString("");
|
||||||
|
break;
|
||||||
|
case XPATH_XSLT_TREE:
|
||||||
|
case XPATH_NODESET:
|
||||||
|
if (val->nodesetval == NULL)
|
||||||
|
ret = xmlXPathNewCString("");
|
||||||
|
else if (val->nodesetval->nodeNr == 0) {
|
||||||
|
ret = xmlXPathNewCString("");
|
||||||
|
} else {
|
||||||
|
xmlChar *res;
|
||||||
|
|
||||||
|
xmlXPathNodeSetSort(val->nodesetval);
|
||||||
|
res = xmlNodeGetContent(val->nodesetval->nodeTab[0]);
|
||||||
|
/* TODO: avoid allocating res to free it */
|
||||||
|
ret = xmlXPathNewString(res);
|
||||||
|
if (res != NULL)
|
||||||
|
xmlFree(res);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XPATH_STRING:
|
||||||
|
return(val);
|
||||||
|
case XPATH_BOOLEAN:
|
||||||
|
if (val->boolval) ret = xmlXPathNewCString("true");
|
||||||
|
else ret = xmlXPathNewCString("false");
|
||||||
|
break;
|
||||||
|
case XPATH_NUMBER: {
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
xmlXPathFormatNumber(val->floatval, buf, sizeof(buf));
|
||||||
|
ret = xmlXPathNewCString(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XPATH_USERS:
|
||||||
|
case XPATH_POINT:
|
||||||
|
case XPATH_RANGE:
|
||||||
|
case XPATH_LOCATIONSET:
|
||||||
|
TODO
|
||||||
|
ret = xmlXPathNewCString("");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(val);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPathStringFunction:
|
* xmlXPathStringFunction:
|
||||||
* @ctxt: the XPath Parser context
|
* @ctxt: the XPath Parser context
|
||||||
@ -4492,54 +4558,8 @@ xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
CHECK_ARITY(1);
|
CHECK_ARITY(1);
|
||||||
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) {
|
cur = xmlXPathConvertString(cur);
|
||||||
case XPATH_UNDEFINED:
|
valuePush(ctxt, cur);
|
||||||
#ifdef DEBUG_EXPR
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
|
|
||||||
#endif
|
|
||||||
valuePush(ctxt, xmlXPathNewCString(""));
|
|
||||||
break;
|
|
||||||
case XPATH_XSLT_TREE:
|
|
||||||
case XPATH_NODESET:
|
|
||||||
if (cur->nodesetval == NULL)
|
|
||||||
valuePush(ctxt, xmlXPathNewCString(""));
|
|
||||||
else if (cur->nodesetval->nodeNr == 0) {
|
|
||||||
valuePush(ctxt, xmlXPathNewCString(""));
|
|
||||||
} else {
|
|
||||||
xmlChar *res;
|
|
||||||
int i = 0; /* Should be first in document order !!!!! */
|
|
||||||
res = xmlNodeGetContent(cur->nodesetval->nodeTab[i]);
|
|
||||||
valuePush(ctxt, xmlXPathNewString(res));
|
|
||||||
if (res != NULL)
|
|
||||||
xmlFree(res);
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
return;
|
|
||||||
case XPATH_STRING:
|
|
||||||
valuePush(ctxt, cur);
|
|
||||||
return;
|
|
||||||
case XPATH_BOOLEAN:
|
|
||||||
if (cur->boolval) valuePush(ctxt, xmlXPathNewCString("true"));
|
|
||||||
else valuePush(ctxt, xmlXPathNewCString("false"));
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
return;
|
|
||||||
case XPATH_NUMBER: {
|
|
||||||
char buf[100];
|
|
||||||
|
|
||||||
xmlXPathFormatNumber(cur->floatval, buf, sizeof(buf));
|
|
||||||
valuePush(ctxt, xmlXPathNewCString(buf));
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case XPATH_USERS:
|
|
||||||
case XPATH_POINT:
|
|
||||||
case XPATH_RANGE:
|
|
||||||
case XPATH_LOCATIONSET:
|
|
||||||
TODO
|
|
||||||
valuePush(ctxt, xmlXPathNewCString(""));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
STRANGE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4995,6 +5015,47 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
xmlXPathFreeObject(to);
|
xmlXPathFreeObject(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPathConvertBoolean:
|
||||||
|
* @val: an XPath object
|
||||||
|
*
|
||||||
|
* Converts an existing object to its boolean() equivalent
|
||||||
|
*
|
||||||
|
* Returns the new object, the old one is freed (or the operation
|
||||||
|
* is done directly on @val)
|
||||||
|
*/
|
||||||
|
xmlXPathObjectPtr
|
||||||
|
xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (val == NULL)
|
||||||
|
return(NULL);
|
||||||
|
switch (val->type) {
|
||||||
|
case XPATH_NODESET:
|
||||||
|
case XPATH_XSLT_TREE:
|
||||||
|
if ((val->nodesetval == NULL) ||
|
||||||
|
(val->nodesetval->nodeNr == 0)) res = 0;
|
||||||
|
else
|
||||||
|
res = 1;
|
||||||
|
break;
|
||||||
|
case XPATH_STRING:
|
||||||
|
if ((val->stringval == NULL) ||
|
||||||
|
(val->stringval[0] == 0)) res = 0;
|
||||||
|
else
|
||||||
|
res = 1;
|
||||||
|
break;
|
||||||
|
case XPATH_BOOLEAN:
|
||||||
|
return(val);
|
||||||
|
case XPATH_NUMBER:
|
||||||
|
if (val->floatval) res = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
STRANGE
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(val);
|
||||||
|
return(xmlXPathNewBoolean(res));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPathBooleanFunction:
|
* xmlXPathBooleanFunction:
|
||||||
* @ctxt: the XPath Parser context
|
* @ctxt: the XPath Parser context
|
||||||
@ -5011,36 +5072,12 @@ xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
void
|
void
|
||||||
xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
||||||
xmlXPathObjectPtr cur;
|
xmlXPathObjectPtr cur;
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
CHECK_ARITY(1);
|
CHECK_ARITY(1);
|
||||||
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) {
|
cur = xmlXPathConvertBoolean(cur);
|
||||||
case XPATH_NODESET:
|
valuePush(ctxt, cur);
|
||||||
case XPATH_XSLT_TREE:
|
|
||||||
if ((cur->nodesetval == NULL) ||
|
|
||||||
(cur->nodesetval->nodeNr == 0)) res = 0;
|
|
||||||
else
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
case XPATH_STRING:
|
|
||||||
if ((cur->stringval == NULL) ||
|
|
||||||
(cur->stringval[0] == 0)) res = 0;
|
|
||||||
else
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
case XPATH_BOOLEAN:
|
|
||||||
valuePush(ctxt, cur);
|
|
||||||
return;
|
|
||||||
case XPATH_NUMBER:
|
|
||||||
if (cur->floatval) res = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
STRANGE
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
valuePush(ctxt, xmlXPathNewBoolean(res));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5135,6 +5172,55 @@ not_equal:
|
|||||||
valuePush(ctxt, xmlXPathNewBoolean(ret));
|
valuePush(ctxt, xmlXPathNewBoolean(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPathConvertNumber:
|
||||||
|
* @val: an XPath object
|
||||||
|
*
|
||||||
|
* Converts an existing object to its number() equivalent
|
||||||
|
*
|
||||||
|
* Returns the new object, the old one is freed (or the operation
|
||||||
|
* is done directly on @val)
|
||||||
|
*/
|
||||||
|
xmlXPathObjectPtr
|
||||||
|
xmlXPathConvertNumber(xmlXPathObjectPtr val) {
|
||||||
|
xmlXPathObjectPtr ret;
|
||||||
|
double res;
|
||||||
|
|
||||||
|
if (val == NULL)
|
||||||
|
return(xmlXPathNewFloat(0.0));
|
||||||
|
switch (val->type) {
|
||||||
|
case XPATH_UNDEFINED:
|
||||||
|
#ifdef DEBUG_EXPR
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
|
||||||
|
#endif
|
||||||
|
ret = xmlXPathNewFloat(0.0);
|
||||||
|
break;
|
||||||
|
case XPATH_XSLT_TREE:
|
||||||
|
case XPATH_NODESET:
|
||||||
|
val = xmlXPathConvertString(val);
|
||||||
|
/* no break on purpose */
|
||||||
|
case XPATH_STRING:
|
||||||
|
res = xmlXPathStringEvalNumber(val->stringval);
|
||||||
|
ret = xmlXPathNewFloat(res);
|
||||||
|
break;
|
||||||
|
case XPATH_BOOLEAN:
|
||||||
|
if (val->boolval) ret = xmlXPathNewFloat(1.0);
|
||||||
|
else ret = xmlXPathNewFloat(0.0);
|
||||||
|
break;
|
||||||
|
case XPATH_NUMBER:
|
||||||
|
return(val);
|
||||||
|
case XPATH_USERS:
|
||||||
|
case XPATH_POINT:
|
||||||
|
case XPATH_RANGE:
|
||||||
|
case XPATH_LOCATIONSET:
|
||||||
|
TODO
|
||||||
|
ret = xmlXPathNewFloat(0.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(val);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPathNumberFunction:
|
* xmlXPathNumberFunction:
|
||||||
* @ctxt: the XPath Parser context
|
* @ctxt: the XPath Parser context
|
||||||
@ -5163,40 +5249,8 @@ xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
|
|||||||
|
|
||||||
CHECK_ARITY(1);
|
CHECK_ARITY(1);
|
||||||
cur = valuePop(ctxt);
|
cur = valuePop(ctxt);
|
||||||
switch (cur->type) {
|
cur = xmlXPathConvertNumber(cur);
|
||||||
case XPATH_UNDEFINED:
|
valuePush(ctxt, cur);
|
||||||
#ifdef DEBUG_EXPR
|
|
||||||
xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
|
|
||||||
#endif
|
|
||||||
valuePush(ctxt, xmlXPathNewFloat(0.0));
|
|
||||||
break;
|
|
||||||
case XPATH_XSLT_TREE:
|
|
||||||
case XPATH_NODESET:
|
|
||||||
valuePush(ctxt, cur);
|
|
||||||
xmlXPathStringFunction(ctxt, 1);
|
|
||||||
cur = valuePop(ctxt);
|
|
||||||
case XPATH_STRING:
|
|
||||||
res = xmlXPathStringEvalNumber(cur->stringval);
|
|
||||||
valuePush(ctxt, xmlXPathNewFloat(res));
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
return;
|
|
||||||
case XPATH_BOOLEAN:
|
|
||||||
if (cur->boolval) valuePush(ctxt, xmlXPathNewFloat(1.0));
|
|
||||||
else valuePush(ctxt, xmlXPathNewFloat(0.0));
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
return;
|
|
||||||
case XPATH_NUMBER:
|
|
||||||
valuePush(ctxt, cur);
|
|
||||||
return;
|
|
||||||
case XPATH_USERS:
|
|
||||||
case XPATH_POINT:
|
|
||||||
case XPATH_RANGE:
|
|
||||||
case XPATH_LOCATIONSET:
|
|
||||||
TODO
|
|
||||||
valuePush(ctxt, xmlXPathNewFloat(0.0));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
STRANGE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5535,6 +5589,50 @@ xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) {
|
|||||||
xmlXPathNewFloat(ret), NULL);
|
xmlXPathNewFloat(ret), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPathParseLiteral:
|
||||||
|
* @ctxt: the XPath Parser context
|
||||||
|
*
|
||||||
|
* Parse a Literal
|
||||||
|
*
|
||||||
|
* [29] Literal ::= '"' [^"]* '"'
|
||||||
|
* | "'" [^']* "'"
|
||||||
|
*
|
||||||
|
* Returns the value found or NULL in case of error
|
||||||
|
*/
|
||||||
|
static xmlChar *
|
||||||
|
xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
|
||||||
|
const xmlChar *q;
|
||||||
|
xmlChar *ret = NULL;
|
||||||
|
|
||||||
|
if (CUR == '"') {
|
||||||
|
NEXT;
|
||||||
|
q = CUR_PTR;
|
||||||
|
while ((IS_CHAR(CUR)) && (CUR != '"'))
|
||||||
|
NEXT;
|
||||||
|
if (!IS_CHAR(CUR)) {
|
||||||
|
XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
|
||||||
|
} else {
|
||||||
|
ret = xmlStrndup(q, CUR_PTR - q);
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
} else if (CUR == '\'') {
|
||||||
|
NEXT;
|
||||||
|
q = CUR_PTR;
|
||||||
|
while ((IS_CHAR(CUR)) && (CUR != '\''))
|
||||||
|
NEXT;
|
||||||
|
if (!IS_CHAR(CUR)) {
|
||||||
|
XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
|
||||||
|
} else {
|
||||||
|
ret = xmlStrndup(q, CUR_PTR - q);
|
||||||
|
NEXT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XP_ERROR0(XPATH_START_LITERAL_ERROR);
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPathCompLiteral:
|
* xmlXPathCompLiteral:
|
||||||
* @ctxt: the XPath Parser context
|
* @ctxt: the XPath Parser context
|
||||||
@ -5613,6 +5711,7 @@ xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
|
|||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
|
XP_ERROR(XPATH_VARIABLE_REF_ERROR);
|
||||||
}
|
}
|
||||||
|
ctxt->comp->last = -1;
|
||||||
PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
|
PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
|
||||||
name, prefix);
|
name, prefix);
|
||||||
SKIP_BLANKS;
|
SKIP_BLANKS;
|
||||||
@ -6369,13 +6468,8 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
|
|||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
xmlFree(name);
|
xmlFree(name);
|
||||||
|
|
||||||
xmlXPathCompLiteral(ctxt);
|
name = xmlXPathParseLiteral(ctxt);
|
||||||
CHECK_ERROR 0;
|
CHECK_ERROR 0;
|
||||||
xmlXPathStringFunction(ctxt, 1);
|
|
||||||
CHECK_ERROR0;
|
|
||||||
cur = valuePop(ctxt);
|
|
||||||
name = xmlStrdup(cur->stringval);
|
|
||||||
xmlXPathFreeObject(cur);
|
|
||||||
SKIP_BLANKS;
|
SKIP_BLANKS;
|
||||||
}
|
}
|
||||||
if (CUR != ')') {
|
if (CUR != ')') {
|
||||||
@ -6391,14 +6485,22 @@ xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
|
|||||||
NEXT;
|
NEXT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get the namespace name for this prefix
|
* Since currently the parser context don't have a
|
||||||
|
* namespace list associated:
|
||||||
|
* The namespace name for this prefix can be computed
|
||||||
|
* only at evaluation time. The compilation is done
|
||||||
|
* outside of any context.
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
*prefix = xmlXPathNsLookup(ctxt->context, name);
|
*prefix = xmlXPathNsLookup(ctxt->context, name);
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
xmlFree(name);
|
xmlFree(name);
|
||||||
if (*prefix == NULL) {
|
if (*prefix == NULL) {
|
||||||
XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
|
XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
*prefix = name;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (CUR == '*') {
|
if (CUR == '*') {
|
||||||
/*
|
/*
|
||||||
@ -6574,7 +6676,7 @@ xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
|
|||||||
* The modification needed for XPointer change to the production
|
* The modification needed for XPointer change to the production
|
||||||
*/
|
*/
|
||||||
#ifdef LIBXML_XPTR_ENABLED
|
#ifdef LIBXML_XPTR_ENABLED
|
||||||
if (ctxt->context->xptr) {
|
if (ctxt->xptr) {
|
||||||
name = xmlXPathParseNCName(ctxt);
|
name = xmlXPathParseNCName(ctxt);
|
||||||
if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
|
if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
|
||||||
int op1 = ctxt->comp->last;
|
int op1 = ctxt->comp->last;
|
||||||
@ -6758,7 +6860,7 @@ xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
|
|||||||
*
|
*
|
||||||
* Evaluate the Precompiled XPath operation
|
* Evaluate the Precompiled XPath operation
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) {
|
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) {
|
||||||
int equal, ret;
|
int equal, ret;
|
||||||
xmlXPathCompExprPtr comp;
|
xmlXPathCompExprPtr comp;
|
||||||
@ -7188,7 +7290,7 @@ xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op) {
|
|||||||
*
|
*
|
||||||
* Evaluate the Precompiled XPath expression in the given context.
|
* Evaluate the Precompiled XPath expression in the given context.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
xmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
|
xmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
|
||||||
xmlXPathCompExprPtr comp;
|
xmlXPathCompExprPtr comp;
|
||||||
|
|
||||||
@ -7219,6 +7321,42 @@ xmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
|
|||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlXPathEvalPredicate:
|
||||||
|
* @ctxt: the XPath context
|
||||||
|
* @res: the Predicate Expression evaluation result
|
||||||
|
*
|
||||||
|
* Evaluate a predicate result for the current node.
|
||||||
|
* A PredicateExpr is evaluated by evaluating the Expr and converting
|
||||||
|
* the result to a boolean. If the result is a number, the result will
|
||||||
|
* be converted to true if the number is equal to the position of the
|
||||||
|
* context node in the context node list (as returned by the position
|
||||||
|
* function) and will be converted to false otherwise; if the result
|
||||||
|
* is not a number, then the result will be converted as if by a call
|
||||||
|
* to the boolean function.
|
||||||
|
*
|
||||||
|
* Return 1 if predicate is true, 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
|
||||||
|
if (res == NULL) return(0);
|
||||||
|
switch (res->type) {
|
||||||
|
case XPATH_BOOLEAN:
|
||||||
|
return(res->boolval);
|
||||||
|
case XPATH_NUMBER:
|
||||||
|
return(res->floatval == ctxt->proximityPosition);
|
||||||
|
case XPATH_NODESET:
|
||||||
|
case XPATH_XSLT_TREE:
|
||||||
|
return(res->nodesetval->nodeNr != 0);
|
||||||
|
case XPATH_STRING:
|
||||||
|
return((res->stringval != NULL) &&
|
||||||
|
(xmlStrlen(res->stringval) != 0));
|
||||||
|
default:
|
||||||
|
STRANGE
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlXPathEvaluatePredicateResult:
|
* xmlXPathEvaluatePredicateResult:
|
||||||
* @ctxt: the XPath Parser context
|
* @ctxt: the XPath Parser context
|
||||||
@ -7310,9 +7448,6 @@ xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) {
|
|||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlXPathEval: evaluation failed\n");
|
"xmlXPathEval: evaluation failed\n");
|
||||||
res = NULL;
|
res = NULL;
|
||||||
} else if (*ctxt->cur != 0) {
|
|
||||||
xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
|
|
||||||
res = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
res = valuePop(ctxt);
|
res = valuePop(ctxt);
|
||||||
}
|
}
|
||||||
@ -7329,13 +7464,13 @@ xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) {
|
|||||||
xmlGenericError(xmlGenericErrorContext,
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
"xmlXPathEval: %d object left on the stack\n",
|
"xmlXPathEval: %d object left on the stack\n",
|
||||||
stack);
|
stack);
|
||||||
|
xmlXPathDebugDumpCompExpr(stdout, ctxt->comp, 0);
|
||||||
}
|
}
|
||||||
if (ctxt->error != XPATH_EXPRESSION_OK) {
|
if (ctxt->error != XPATH_EXPRESSION_OK) {
|
||||||
xmlXPathFreeObject(res);
|
xmlXPathFreeObject(res);
|
||||||
res = NULL;
|
res = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlXPathDebugDumpCompExpr(stdout, ctxt->comp, 0);
|
|
||||||
|
|
||||||
ctxt->comp = NULL;
|
ctxt->comp = NULL;
|
||||||
xmlXPathFreeParserContext(ctxt);
|
xmlXPathFreeParserContext(ctxt);
|
||||||
|
12
xpath.h
12
xpath.h
@ -244,7 +244,7 @@ struct _xmlXPathParserContext {
|
|||||||
xmlXPathObjectPtr *valueTab; /* stack of values */
|
xmlXPathObjectPtr *valueTab; /* stack of values */
|
||||||
|
|
||||||
xmlXPathCompExprPtr comp; /* the precompiled expression */
|
xmlXPathCompExprPtr comp; /* the precompiled expression */
|
||||||
|
int xptr; /* it this an XPointer expression */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -271,6 +271,12 @@ void xmlXPathFreeNodeSet (xmlNodeSetPtr obj);
|
|||||||
xmlXPathObjectPtr xmlXPathObjectCopy (xmlXPathObjectPtr val);
|
xmlXPathObjectPtr xmlXPathObjectCopy (xmlXPathObjectPtr val);
|
||||||
int xmlXPathCmpNodes (xmlNodePtr node1,
|
int xmlXPathCmpNodes (xmlNodePtr node1,
|
||||||
xmlNodePtr node2);
|
xmlNodePtr node2);
|
||||||
|
/**
|
||||||
|
* Conversion functions to basic types
|
||||||
|
*/
|
||||||
|
xmlXPathObjectPtr xmlXPathConvertBoolean (xmlXPathObjectPtr val);
|
||||||
|
xmlXPathObjectPtr xmlXPathConvertNumber (xmlXPathObjectPtr val);
|
||||||
|
xmlXPathObjectPtr xmlXPathConvertString (xmlXPathObjectPtr val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context handling
|
* Context handling
|
||||||
@ -288,13 +294,15 @@ xmlXPathObjectPtr xmlXPathEvalXPtrExpr (const xmlChar *str,
|
|||||||
xmlXPathContextPtr ctxt);
|
xmlXPathContextPtr ctxt);
|
||||||
xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
|
xmlXPathObjectPtr xmlXPathEvalExpression (const xmlChar *str,
|
||||||
xmlXPathContextPtr ctxt);
|
xmlXPathContextPtr ctxt);
|
||||||
|
int xmlXPathEvalPredicate (xmlXPathContextPtr ctxt,
|
||||||
|
xmlXPathObjectPtr res);
|
||||||
/**
|
/**
|
||||||
* Separate compilation/evaluation entry points
|
* Separate compilation/evaluation entry points
|
||||||
*/
|
*/
|
||||||
xmlXPathCompExprPtr xmlXPathCompile (const xmlChar *str);
|
xmlXPathCompExprPtr xmlXPathCompile (const xmlChar *str);
|
||||||
xmlXPathObjectPtr xmlXPathCompiledEval (xmlXPathCompExprPtr comp,
|
xmlXPathObjectPtr xmlXPathCompiledEval (xmlXPathCompExprPtr comp,
|
||||||
xmlXPathContextPtr ctx);
|
xmlXPathContextPtr ctx);
|
||||||
|
void xmlXPathFreeCompExpr (xmlXPathCompExprPtr comp);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1292,6 +1292,7 @@ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
|
|
||||||
ctxt = xmlXPathNewParserContext(str, ctx);
|
ctxt = xmlXPathNewParserContext(str, ctx);
|
||||||
|
ctxt->xptr = 1;
|
||||||
xmlXPtrEvalXPointer(ctxt);
|
xmlXPtrEvalXPointer(ctxt);
|
||||||
|
|
||||||
if ((ctxt->value != NULL) &&
|
if ((ctxt->value != NULL) &&
|
||||||
|
Reference in New Issue
Block a user