📄 xpointer.c.svn-base
字号:
oldset = (xmlLocationSetPtr) set->user; /* * The loop is to compute the covering range for each item and add it */ newset = xmlXPtrLocationSetCreate(NULL); for (i = 0;i < oldset->locNr;i++) { xmlXPtrLocationSetAdd(newset, xmlXPtrCoveringRange(ctxt, oldset->locTab[i])); } /* * Save the new value and cleanup */ valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); xmlXPathFreeObject(set);}/** * xmlXPtrInsideRange: * @ctxt: the XPointer Parser context * @loc: the location for which the inside range must be computed * * A inside range is a range described in the range-inside() description * * Returns a new location or NULL in case of error */static xmlXPathObjectPtrxmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) { if (loc == NULL) return(NULL); if ((ctxt == NULL) || (ctxt->context == NULL) || (ctxt->context->doc == NULL)) return(NULL); switch (loc->type) { case XPATH_POINT: { xmlNodePtr node = (xmlNodePtr) loc->user; switch (node->type) { case XML_PI_NODE: case XML_COMMENT_NODE: case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: { if (node->content == NULL) { return(xmlXPtrNewRange(node, 0, node, 0)); } else { return(xmlXPtrNewRange(node, 0, node, xmlStrlen(node->content))); } } case XML_ATTRIBUTE_NODE: case XML_ELEMENT_NODE: case XML_ENTITY_REF_NODE: case XML_DOCUMENT_NODE: case XML_NOTATION_NODE: case XML_HTML_DOCUMENT_NODE: { return(xmlXPtrNewRange(node, 0, node, xmlXPtrGetArity(node))); } default: break; } return(NULL); } case XPATH_RANGE: { xmlNodePtr node = (xmlNodePtr) loc->user; if (loc->user2 != NULL) { return(xmlXPtrNewRange(node, loc->index, loc->user2, loc->index2)); } else { switch (node->type) { case XML_PI_NODE: case XML_COMMENT_NODE: case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: { if (node->content == NULL) { return(xmlXPtrNewRange(node, 0, node, 0)); } else { return(xmlXPtrNewRange(node, 0, node, xmlStrlen(node->content))); } } case XML_ATTRIBUTE_NODE: case XML_ELEMENT_NODE: case XML_ENTITY_REF_NODE: case XML_DOCUMENT_NODE: case XML_NOTATION_NODE: case XML_HTML_DOCUMENT_NODE: { return(xmlXPtrNewRange(node, 0, node, xmlXPtrGetArity(node))); } default: break; } return(NULL); } } default: TODO /* missed one case ??? */ } return(NULL);}/** * xmlXPtrRangeInsideFunction: * @ctxt: the XPointer Parser context * @nargs: the number of args * * Function implementing the range-inside() function 5.4.3 * location-set range-inside(location-set ) * * The range-inside function returns ranges covering the contents of * the locations in the argument location-set. For each location x in * the argument location-set, a range location is added to the result * location-set. If x is a range location, then x is added to the * result location-set. If x is not a range location, then x is used * as the container location of the start and end points of the range * location to be added; the index of the start point of the range is * zero; if the end point is a character point then its index is the * length of the string-value of x, and otherwise is the number of * location children of x. * */voidxmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) { int i; xmlXPathObjectPtr set; xmlLocationSetPtr oldset; xmlLocationSetPtr newset; CHECK_ARITY(1); if ((ctxt->value == NULL) || ((ctxt->value->type != XPATH_LOCATIONSET) && (ctxt->value->type != XPATH_NODESET))) XP_ERROR(XPATH_INVALID_TYPE) set = valuePop(ctxt); if (set->type == XPATH_NODESET) { xmlXPathObjectPtr tmp; /* * First convert to a location set */ tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval); xmlXPathFreeObject(set); set = tmp; } oldset = (xmlLocationSetPtr) set->user; /* * The loop is to compute the covering range for each item and add it */ newset = xmlXPtrLocationSetCreate(NULL); for (i = 0;i < oldset->locNr;i++) { xmlXPtrLocationSetAdd(newset, xmlXPtrInsideRange(ctxt, oldset->locTab[i])); } /* * Save the new value and cleanup */ valuePush(ctxt, xmlXPtrWrapLocationSet(newset)); xmlXPathFreeObject(set);}/** * xmlXPtrRangeToFunction: * @ctxt: the XPointer Parser context * @nargs: the number of args * * Implement the range-to() XPointer function */voidxmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr range; const xmlChar *cur; xmlXPathObjectPtr res, obj; xmlXPathObjectPtr tmp; xmlLocationSetPtr newset = NULL; xmlNodeSetPtr oldset; int i; CHECK_ARITY(1); /* * Save the expression pointer since we will have to evaluate * it multiple times. Initialize the new set. */ CHECK_TYPE(XPATH_NODESET); obj = valuePop(ctxt); oldset = obj->nodesetval; ctxt->context->node = NULL; cur = ctxt->cur; newset = xmlXPtrLocationSetCreate(NULL); for (i = 0; i < oldset->nodeNr; i++) { ctxt->cur = cur; /* * 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); xmlXPathEvalExpr(ctxt); CHECK_ERROR; /* * 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(newset, range); } /* * Cleanup */ if (res != NULL) xmlXPathFreeObject(res); if (ctxt->value == tmp) { res = valuePop(ctxt); xmlXPathFreeObject(res); } ctxt->context->node = NULL; } /* * The result is used as the new evaluation set. */ xmlXPathFreeObject(obj); ctxt->context->node = NULL; ctxt->context->contextSize = -1; ctxt->context->proximityPosition = -1; valuePush(ctxt, xmlXPtrWrapLocationSet(newset));}/** * xmlXPtrAdvanceNode: * @cur: the node * @level: incremented/decremented to show level in tree * * Advance to the next element or text node in document order * TODO: add a stack for entering/exiting entities * * Returns -1 in case of failure, 0 otherwise */xmlNodePtrxmlXPtrAdvanceNode(xmlNodePtr cur, int *level) {next: if (cur == NULL) return(NULL); if (cur->children != NULL) { cur = cur->children ; if (level != NULL) (*level)++; goto found; }skip: /* This label should only be needed if something is wrong! */ if (cur->next != NULL) { cur = cur->next; goto found; } do { cur = cur->parent; if (level != NULL) (*level)--; if (cur == NULL) return(NULL); if (cur->next != NULL) { cur = cur->next; goto found; } } while (cur != NULL);found: if ((cur->type != XML_ELEMENT_NODE) && (cur->type != XML_TEXT_NODE) && (cur->type != XML_DOCUMENT_NODE) && (cur->type != XML_HTML_DOCUMENT_NODE) && (cur->type != XML_CDATA_SECTION_NODE)) { if (cur->type == XML_ENTITY_REF_NODE) { /* Shouldn't happen */ TODO goto skip; } goto next; } return(cur);}/** * xmlXPtrAdvanceChar: * @node: the node * @indx: the indx * @bytes: the number of bytes * * Advance a point of the associated number of bytes (not UTF8 chars) * * Returns -1 in case of failure, 0 otherwise */static intxmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) { xmlNodePtr cur; int pos; int len; if ((node == NULL) || (indx == NULL)) return(-1); cur = *node; if (cur == NULL) return(-1); pos = *indx; while (bytes >= 0) { /* * First position to the beginning of the first text node * corresponding to this point */ while ((cur != NULL) && ((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE))) { if (pos > 0) { cur = xmlXPtrGetNthChild(cur, pos); pos = 0; } else { cur = xmlXPtrAdvanceNode(cur, NULL); pos = 0; } } if (cur == NULL) { *node = NULL; *indx = 0; return(-1); } /* * if there is no move needed return the current value. */ if (pos == 0) pos = 1; if (bytes == 0) { *node = cur; *indx = pos; return(0); } /* * We should have a text (or cdata) node ... */ len = 0; if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { len = xmlStrlen(cur->content); } if (pos > len) { /* Strange, the indx in the text node is greater than it's len */ STRANGE pos = len; } if (pos + bytes >= len) { bytes -= (len - pos); cur = xmlXPtrAdvanceNode(cur, NULL); cur = 0; } else if (pos + bytes < len) { pos += bytes; *node = cur; *indx = pos; return(0); } } return(-1);}/** * xmlXPtrMatchString: * @string: the string to search * @start: the start textnode * @startindex: the start index * @end: the end textnode IN/OUT * @endindex: the end index IN/OUT * * Check whether the document contains @string at the position * (@start, @startindex) and limited by the (@end, @endindex) point * * Returns -1 in case of failure, 0 if not found, 1 if found in which case * (@start, @startindex) will indicate the position of the beginning * of the range and (@end, @endindex) will indicate the end * of the range */static intxmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex, xmlNodePtr *end, int *endindex) { xmlNodePtr cur; int pos; /* 0 based */ int len; /* in bytes */ int stringlen; /* in bytes */ int match; if (string == NULL) return(-1); if (start == NULL) return(-1); if ((end == NULL) || (endindex == NULL)) return(-1); cur = start; if (cur == NULL) return(-1); pos = startindex - 1; stringlen = xmlStrlen(string); while (stringlen > 0) { if ((cur == *end) && (pos + stringlen > *endindex)) return(0); if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { len = xmlStrlen(cur->content); if (len >= pos + stringlen) { match = (!xmlStrncmp(&cur->content[pos], string, stringlen)); if (match) {#ifdef DEBUG_RANGES xmlGenericError(xmlGenericErrorContext, "found range %d bytes at index %d of ->", stringlen, pos + 1); xmlDebugDumpString(stdout, cur->content); xmlGenericError(xmlGenericErrorContext, "\n");#endif *end = cur; *endindex = pos + stringlen; return(1); } else { return(0); } } else { int sub = len - pos; match = (!xmlStrncmp(&cur->content[pos], string, sub)); if (match) {#ifdef DEBUG_RANGES xmlGenericError(xmlGenericErrorContext, "found subrange %d bytes at index %d of ->", sub, pos + 1); xmlDebugDumpString(stdout, cur->content); xmlGenericError(xmlGenericErrorContext, "\n");#endif string = &string[sub]; stringlen -= sub; } else { return(0); } } } cur = xmlXPtrAdvanceNode(cur, NULL); if (cur == NULL) return(0); pos = 0; } return(1);}/** * xmlXPtrSearchString: * @string: the string to search * @start: the start textnode IN/OUT * @startindex: the start index IN/OUT * @end: the end textnode * @endindex: the end index * * Search the next occurrence of @string within the document content * until the (@end, @endindex) point is reached * * Returns -1 in case of failure, 0 if not found, 1 if found in which case * (@start, @startindex) will indicate the position of the beginning * of the range and (@end, @endindex) will indicate the end * of the range */static intxmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex, xmlNodePtr *end, int *endindex) { xmlNodePtr cur; const xmlChar *str; int pos; /* 0 based */ int len; /* in bytes */ xmlChar first; if (string == NULL) return(-1); if ((start == NULL) || (startindex == NULL)) return(-1); if ((end == NULL) || (endindex == NULL)) return(-1); cur = *start; if (cur == NULL) return(-1); pos = *startindex - 1; first = string[0]; while (cur != NULL) { if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { len = xmlStrlen(cur->content); while (pos <= len) { if (first != 0) { str = xmlStrchr(&cur->content[pos], first); if (str != NULL) { pos = (str - (xmlChar *)(cur->content));#ifdef DEBUG_RANGES xmlGenericError(xmlGenericErrorContext, "found '%c' at
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -