📄 xpath.c
字号:
xmlFree(list);}/************************************************************************ * * * Parser Types * * * ************************************************************************//* * Types are private: */typedef enum { XPATH_OP_END=0, XPATH_OP_AND, XPATH_OP_OR, XPATH_OP_EQUAL, XPATH_OP_CMP, XPATH_OP_PLUS, XPATH_OP_MULT, XPATH_OP_UNION, XPATH_OP_ROOT, XPATH_OP_NODE, XPATH_OP_RESET, /* 10 */ XPATH_OP_COLLECT, XPATH_OP_VALUE, /* 12 */ XPATH_OP_VARIABLE, XPATH_OP_FUNCTION, XPATH_OP_ARG, XPATH_OP_PREDICATE, XPATH_OP_FILTER, /* 17 */ XPATH_OP_SORT /* 18 */#ifdef LIBXML_XPTR_ENABLED ,XPATH_OP_RANGETO#endif} xmlXPathOp;typedef enum { AXIS_ANCESTOR = 1, AXIS_ANCESTOR_OR_SELF, AXIS_ATTRIBUTE, AXIS_CHILD, AXIS_DESCENDANT, AXIS_DESCENDANT_OR_SELF, AXIS_FOLLOWING, AXIS_FOLLOWING_SIBLING, AXIS_NAMESPACE, AXIS_PARENT, AXIS_PRECEDING, AXIS_PRECEDING_SIBLING, AXIS_SELF } xmlXPathAxisVal;typedef enum { NODE_TEST_NONE = 0, NODE_TEST_TYPE = 1, NODE_TEST_PI = 2, NODE_TEST_ALL = 3, NODE_TEST_NS = 4, NODE_TEST_NAME = 5} xmlXPathTestVal;typedef enum { NODE_TYPE_NODE = 0, NODE_TYPE_COMMENT = XML_COMMENT_NODE, NODE_TYPE_TEXT = XML_TEXT_NODE, NODE_TYPE_PI = XML_PI_NODE } xmlXPathTypeVal;#define XP_REWRITE_DOS_CHILD_ELEM 1typedef struct _xmlXPathStepOp xmlXPathStepOp;typedef xmlXPathStepOp *xmlXPathStepOpPtr;struct _xmlXPathStepOp { xmlXPathOp op; /* The identifier of the operation */ int ch1; /* First child */ int ch2; /* Second child */ int value; int value2; int value3; void *value4; void *value5; void *cache; void *cacheURI; int rewriteType;};struct _xmlXPathCompExpr { 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 */ xmlDictPtr dict; /* the dictionnary to use if any */#ifdef DEBUG_EVAL_COUNTS int nb; xmlChar *string;#endif#ifdef XPATH_STREAMING xmlPatternPtr stream;#endif};/************************************************************************ * * * Forward declarations * * * ************************************************************************/static voidxmlXPathFreeValueTree(xmlNodeSetPtr obj);static voidxmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj);static intxmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, xmlNodePtr *first);static intxmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op, int isPredicate);/************************************************************************ * * * Parser Type functions * * * ************************************************************************//** * xmlXPathNewCompExpr: * * Create a new Xpath component * * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error */static xmlXPathCompExprPtrxmlXPathNewCompExpr(void) { xmlXPathCompExprPtr cur; cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr)); if (cur == NULL) { xmlXPathErrMemory(NULL, "allocating component\n"); return(NULL); } memset(cur, 0, sizeof(xmlXPathCompExpr)); cur->maxStep = 10; cur->nbStep = 0; cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep * sizeof(xmlXPathStepOp)); if (cur->steps == NULL) { xmlXPathErrMemory(NULL, "allocating steps\n"); xmlFree(cur); return(NULL); } memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp)); cur->last = -1;#ifdef DEBUG_EVAL_COUNTS cur->nb = 0;#endif return(cur);}/** * xmlXPathFreeCompExpr: * @comp: an XPATH comp * * Free up the memory allocated by @comp */voidxmlXPathFreeCompExpr(xmlXPathCompExprPtr comp){ xmlXPathStepOpPtr op; int i; if (comp == NULL) return; if (comp->dict == NULL) { for (i = 0; i < comp->nbStep; i++) { op = &comp->steps[i]; if (op->value4 != NULL) { if (op->op == XPATH_OP_VALUE) xmlXPathFreeObject(op->value4); else xmlFree(op->value4); } if (op->value5 != NULL) xmlFree(op->value5); } } else { for (i = 0; i < comp->nbStep; i++) { op = &comp->steps[i]; if (op->value4 != NULL) { if (op->op == XPATH_OP_VALUE) xmlXPathFreeObject(op->value4); } } xmlDictFree(comp->dict); } if (comp->steps != NULL) { xmlFree(comp->steps); }#ifdef DEBUG_EVAL_COUNTS if (comp->string != NULL) { xmlFree(comp->string); }#endif#ifdef XPATH_STREAMING if (comp->stream != NULL) { xmlFreePatternList(comp->stream); }#endif if (comp->expr != NULL) { xmlFree(comp->expr); } xmlFree(comp);}/** * xmlXPathCompExprAdd: * @comp: the compiled expression * @ch1: first child index * @ch2: second child index * @op: an op * @value: the first int value * @value2: the second int value * @value3: the third int value * @value4: the first string value * @value5: the second string value * * Add a step to an XPath Compiled Expression * * Returns -1 in case of failure, the index otherwise */static intxmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2, xmlXPathOp op, int value, int value2, int value3, void *value4, void *value5) { if (comp->nbStep >= comp->maxStep) { xmlXPathStepOp *real; comp->maxStep *= 2; real = (xmlXPathStepOp *) xmlRealloc(comp->steps, comp->maxStep * sizeof(xmlXPathStepOp)); if (real == NULL) { comp->maxStep /= 2; xmlXPathErrMemory(NULL, "adding step\n"); return(-1); } comp->steps = real; } comp->last = comp->nbStep; comp->steps[comp->nbStep].rewriteType = 0; comp->steps[comp->nbStep].ch1 = ch1; comp->steps[comp->nbStep].ch2 = ch2; comp->steps[comp->nbStep].op = op; comp->steps[comp->nbStep].value = value; comp->steps[comp->nbStep].value2 = value2; comp->steps[comp->nbStep].value3 = value3; if ((comp->dict != NULL) && ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) || (op == XPATH_OP_COLLECT))) { if (value4 != NULL) { comp->steps[comp->nbStep].value4 = (xmlChar *) (void *)xmlDictLookup(comp->dict, value4, -1); xmlFree(value4); } else comp->steps[comp->nbStep].value4 = NULL; if (value5 != NULL) { comp->steps[comp->nbStep].value5 = (xmlChar *) (void *)xmlDictLookup(comp->dict, value5, -1); xmlFree(value5); } else comp->steps[comp->nbStep].value5 = NULL; } else { comp->steps[comp->nbStep].value4 = value4; comp->steps[comp->nbStep].value5 = value5; } comp->steps[comp->nbStep].cache = NULL; return(comp->nbStep++);}/** * xmlXPathCompSwap: * @comp: the compiled expression * @op: operation index * * Swaps 2 operations in the compiled expression */static voidxmlXPathCompSwap(xmlXPathStepOpPtr op) { int tmp;#ifndef LIBXML_THREAD_ENABLED /* * Since this manipulates possibly shared variables, this is * disabled if one detects that the library is used in a multithreaded * application */ if (xmlXPathDisableOptimizer) return;#endif tmp = op->ch1; op->ch1 = op->ch2; op->ch2 = tmp;}#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \ xmlXPathCompExprAdd(ctxt->comp, (op1), (op2), \ (op), (val), (val2), (val3), (val4), (val5))#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \ xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1, \ (op), (val), (val2), (val3), (val4), (val5))#define PUSH_LEAVE_EXPR(op, val, val2) \xmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)#define PUSH_UNARY_EXPR(op, ch, val, val2) \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)/************************************************************************ * * * XPath object cache structures * * * ************************************************************************//* #define XP_DEFAULT_CACHE_ON */#define XP_HAS_CACHE(c) ((c != NULL) && ((c)->cache != NULL))typedef struct _xmlXPathContextCache xmlXPathContextCache;typedef xmlXPathContextCache *xmlXPathContextCachePtr;struct _xmlXPathContextCache { xmlPointerListPtr nodesetObjs; /* contains xmlXPathObjectPtr */ xmlPointerListPtr stringObjs; /* contains xmlXPathObjectPtr */ xmlPointerListPtr booleanObjs; /* contains xmlXPathObjectPtr */ xmlPointerListPtr numberObjs; /* contains xmlXPathObjectPtr */ xmlPointerListPtr miscObjs; /* contains xmlXPathObjectPtr */ int maxNodeset; int maxString; int maxBoolean; int maxNumber; int maxMisc;#ifdef XP_DEBUG_OBJ_USAGE int dbgCachedAll; int dbgCachedNodeset; int dbgCachedString; int dbgCachedBool; int dbgCachedNumber; int dbgCachedPoint; int dbgCachedRange; int dbgCachedLocset; int dbgCachedUsers; int dbgCachedXSLTTree; int dbgCachedUndefined; int dbgReusedAll; int dbgReusedNodeset; int dbgReusedString; int dbgReusedBool; int dbgReusedNumber; int dbgReusedPoint; int dbgReusedRange; int dbgReusedLocset; int dbgReusedUsers; int dbgReusedXSLTTree; int dbgReusedUndefined;#endif};/************************************************************************ * * * Debugging related functions * * * ************************************************************************/#define STRANGE \ xmlGenericError(xmlGenericErrorContext, \ "Internal error at %s:%d\n", \ __FILE__, __LINE__);#ifdef LIBXML_DEBUG_ENABLEDstatic voidxmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) { int i; char shift[100]; for (i = 0;((i < depth) && (i < 25));i++) shift[2 * i] = shift[2 * i + 1] = ' '; shift[2 * i] = shift[2 * i + 1] = 0; if (cur == NULL) { fprintf(output, shift); fprintf(output, "Node is NULL !\n"); return; } if ((cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)) { fprintf(output, shift); fprintf(output, " /\n"); } else if (cur->type == XML_ATTRIBUTE_NODE) xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth); else xmlDebugDumpOneNode(output, cur, depth);}static voidxmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) { xmlNodePtr tmp; int i; char shift[100]; for (i = 0;((i < depth) && (i < 25));i++) shift[2 * i] = shift[2 * i + 1] = ' '; shift[2 * i] = shift[2 * i + 1] = 0; if (cur == NULL) { fprintf(output, shift); fprintf(output, "Node is NULL !\n"); return; } while (cur != NULL) { tmp = cur; cur = cur->next; xmlDebugDumpOneNode(output, tmp, depth); }}static voidxmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) { int i; char shift[100]; for (i = 0;((i < depth) && (i < 25));i++) shift[2 * i] = shift[2 * i + 1] = ' '; shift[2 * i] = shift[2 * i + 1] = 0; if (cur == NULL) { fprintf(output, shift); fprintf(output, "NodeSet is NULL !\n"); return; } if (cur != NULL) { fprintf(output, "Set contains %d nodes:\n", cur->nodeNr); for (i = 0;i < cur->nodeNr;i++) { fprintf(output, shift); fprintf(output, "%d", i + 1); xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1); } }}static voidxmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) { int i; char shift[100]; for (i = 0;((i < depth) && (i < 25));i++) shift[2 * i] = shift[2 * i + 1] = ' '; shift[2 * i] = shift[2 * i + 1] = 0; if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) { fprintf(output, shift); fprintf(output, "Value Tree is NULL !\n"); return; } fprintf(output, shift); fprintf(output, "%d", i + 1); xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);}#if defined(LIBXML_XPTR_ENABLED)static voidxmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -