📄 xpath.c
字号:
valuePush(ctxt, arg); \ xmlXPathNumberFunction(ctxt, 1); \ arg = valuePop(ctxt); \ }/** * 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. */intxmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar *str) { int i; xmlNodeSetPtr ns; xmlChar *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))) { xmlFree(str2); return(1); } xmlFree(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. */intxmlXPathEqualNodeSetFloat(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, BAD_CAST 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. */intxmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) { int i; xmlNodeSetPtr ns; xmlChar *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))) { xmlFree(str); return(1); } xmlFree(str); } return(0);}/** * xmlXPathEqualValues: * @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. */intxmlXPathEqualValues(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); } switch (arg1->type) { case XPATH_UNDEFINED:#ifdef DEBUG_EXPR fprintf(xmlXPathDebug, "Equal: undefined\n");#endif break; case XPATH_NODESET: 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);#endif 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: undefined\n");#endif 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; } 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 * * Implement the compare operation on XPath objects: * @arg1 < @arg2 (1, 1, ... * @arg1 <= @arg2 (1, 0, ... * @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. */intxmlXPathCompareValues(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);}/** * xmlXPathValueFlipSign: * @ctxt: the XPath Parser context * * Implement the unary - operation on an XPath object * The numeric operators convert their operands to numbers as if * by calling the number function. */voidxmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) { xmlXPathObjectPtr arg; POP_FLOAT arg->floatval = -arg->floatval; valuePush(ctxt, arg);}/** * xmlXPathAddValues: * @ctxt: the XPath Parser context * * Implement the add operation on XPath objects: * The numeric operators convert their operands to numbers as if * by calling the number function. */voidxmlXPathAddValues(xmlXPathParserContextPtr ctxt) { xmlXPathObjectPtr arg; double val; POP_FLOAT val = arg->floatval; xmlXPathFreeObject(arg); POP_FLOAT arg->floatval += val; valuePush(ctxt, arg);}/** * xmlXPathSubValues: * @ctxt: the XPath Parser context * * Implement the substraction operation on XPath objects: * The numeric operators convert their operands to numbers as if * by calling the number function. */voidxmlXPathSubValues(xmlXPathParserContextPtr ctxt) { xmlXPathObjectPtr arg; double val; POP_FLOAT val = arg->floatval; xmlXPathFreeObject(arg); POP_FLOAT arg->floatval -= val; valuePush(ctxt, arg);}/** * xmlXPathMultValues: * @ctxt: the XPath Parser context * * Implement the multiply operation on XPath objects: * The numeric operators convert their operands to numbers as if * by calling the number function. */voidxmlXPathMultValues(xmlXPathParserContextPtr ctxt) { xmlXPathObjectPtr arg; double val; POP_FLOAT val = arg->floatval; xmlXPathFreeObject(arg); POP_FLOAT arg->floatval *= val; valuePush(ctxt, arg);}/** * xmlXPathDivValues: * @ctxt: the XPath Parser context * * Implement the div operation on XPath objects: * The numeric operators convert their operands to numbers as if * by calling the number function. */voidxmlXPathDivValues(xmlXPathParserContextPtr ctxt) { xmlXPathObjectPtr arg; double val; POP_FLOAT val = arg->floatval; xmlXPathFreeObject(arg); POP_FLOAT arg->floatval /= val; valuePush(ctxt, arg);}/** * xmlXPathModValues: * @ctxt: the XPath Parser context * * Implement the div operation on XPath objects: @arg1 / @arg2 * The numeric operators convert their operands to numbers as if * by calling the number function. */voidxmlXPathModValues(xmlXPathParserContextPtr ctxt) { xmlXPathObjectPtr arg; double val; POP_FLOAT val = arg->floatval; xmlXPathFreeObject(arg); POP_FLOAT arg->floatval /= val; valuePush(ctxt, arg);}/************************************************************************ * * * The traversal functions * * * ************************************************************************/#define AXIS_ANCESTOR 1#define AXIS_ANCESTOR_OR_SELF 2#define AXIS_ATTRIBUTE 3#define AXIS_CHILD 4#define AXIS_DESCENDANT 5#define AXIS_DESCENDANT_OR_SELF 6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -