📄 xpointer.c.svn-base
字号:
NEXT; } *cur = 0; if ((level != 0) && (CUR == 0)) { xmlFree(buffer); XP_ERROR(XPTR_SYNTAX_ERROR); } if (xmlStrEqual(name, (xmlChar *) "xpointer")) { const xmlChar *left = CUR_PTR; CUR_PTR = buffer; /* * To evaluate an xpointer scheme element (4.3) we need: * context initialized to the root * context position initalized to 1 * context size initialized to 1 */ ctxt->context->node = (xmlNodePtr)ctxt->context->doc; ctxt->context->proximityPosition = 1; ctxt->context->contextSize = 1; xmlXPathEvalExpr(ctxt); CUR_PTR=left; } else if (xmlStrEqual(name, (xmlChar *) "element")) { const xmlChar *left = CUR_PTR; xmlChar *name2; CUR_PTR = buffer; if (buffer[0] == '/') { xmlXPathRoot(ctxt); xmlXPtrEvalChildSeq(ctxt, NULL); } else { name2 = xmlXPathParseName(ctxt); if (name2 == NULL) { CUR_PTR = left; xmlFree(buffer); XP_ERROR(XPATH_EXPR_ERROR); } xmlXPtrEvalChildSeq(ctxt, name2); } CUR_PTR = left;#ifdef XPTR_XMLNS_SCHEME } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) { const xmlChar *left = CUR_PTR; xmlChar *prefix; xmlChar *URI; xmlURIPtr value; CUR_PTR = buffer; prefix = xmlXPathParseNCName(ctxt); if (prefix == NULL) { xmlFree(buffer); xmlFree(name); XP_ERROR(XPTR_SYNTAX_ERROR); } SKIP_BLANKS; if (CUR != '=') { xmlFree(prefix); xmlFree(buffer); xmlFree(name); XP_ERROR(XPTR_SYNTAX_ERROR); } NEXT; SKIP_BLANKS; /* @@ check escaping in the XPointer WD */ value = xmlParseURI((const char *)ctxt->cur); if (value == NULL) { xmlFree(prefix); xmlFree(buffer); xmlFree(name); XP_ERROR(XPTR_SYNTAX_ERROR); } URI = xmlSaveUri(value); xmlFreeURI(value); if (URI == NULL) { xmlFree(prefix); xmlFree(buffer); xmlFree(name); XP_ERROR(XPATH_MEMORY_ERROR); } xmlXPathRegisterNs(ctxt->context, prefix, URI); CUR_PTR = left; xmlFree(URI); xmlFree(prefix);#endif /* XPTR_XMLNS_SCHEME */ } else { xmlXPtrErr(ctxt, XML_XPTR_UNKNOWN_SCHEME, "unsupported scheme '%s'\n", name); } xmlFree(buffer); xmlFree(name);}/** * xmlXPtrEvalFullXPtr: * @ctxt: the XPointer Parser context * @name: the preparsed Scheme for the first XPtrPart * * FullXPtr ::= XPtrPart (S? XPtrPart)* * * As the specs says: * ----------- * When multiple XPtrParts are provided, they must be evaluated in * left-to-right order. If evaluation of one part fails, the nexti * is evaluated. The following conditions cause XPointer part failure: * * - An unknown scheme * - A scheme that does not locate any sub-resource present in the resource * - A scheme that is not applicable to the media type of the resource * * The XPointer application must consume a failed XPointer part and * attempt to evaluate the next one, if any. The result of the first * XPointer part whose evaluation succeeds is taken to be the fragment * located by the XPointer as a whole. If all the parts fail, the result * for the XPointer as a whole is a sub-resource error. * ----------- * * Parse and evaluate a Full XPtr i.e. possibly a cascade of XPath based * expressions or other schemes. */static voidxmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) { if (name == NULL) name = xmlXPathParseName(ctxt); if (name == NULL) XP_ERROR(XPATH_EXPR_ERROR); while (name != NULL) { xmlXPtrEvalXPtrPart(ctxt, name); /* in case of syntax error, break here */ if (ctxt->error != XPATH_EXPRESSION_OK) return; /* * If the returned value is a non-empty nodeset * or location set, return here. */ if (ctxt->value != NULL) { xmlXPathObjectPtr obj = ctxt->value; switch (obj->type) { case XPATH_LOCATIONSET: { xmlLocationSetPtr loc = ctxt->value->user; if ((loc != NULL) && (loc->locNr > 0)) return; break; } case XPATH_NODESET: { xmlNodeSetPtr loc = ctxt->value->nodesetval; if ((loc != NULL) && (loc->nodeNr > 0)) return; break; } default: break; } /* * Evaluating to improper values is equivalent to * a sub-resource error, clean-up the stack */ do { obj = valuePop(ctxt); if (obj != NULL) { xmlXPathFreeObject(obj); } } while (obj != NULL); } /* * Is there another XPointer part. */ SKIP_BLANKS; name = xmlXPathParseName(ctxt); }}/** * xmlXPtrEvalChildSeq: * @ctxt: the XPointer Parser context * @name: a possible ID name of the child sequence * * ChildSeq ::= '/1' ('/' [0-9]*)* * | Name ('/' [0-9]*)+ * * Parse and evaluate a Child Sequence. This routine also handle the * case of a Bare Name used to get a document ID. */static voidxmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) { /* * XPointer don't allow by syntax to address in mutirooted trees * this might prove useful in some cases, warn about it. */ if ((name == NULL) && (CUR == '/') && (NXT(1) != '1')) { xmlXPtrErr(ctxt, XML_XPTR_CHILDSEQ_START, "warning: ChildSeq not starting by /1\n", NULL); } if (name != NULL) { valuePush(ctxt, xmlXPathNewString(name)); xmlFree(name); xmlXPathIdFunction(ctxt, 1); CHECK_ERROR; } while (CUR == '/') { int child = 0; NEXT; while ((CUR >= '0') && (CUR <= '9')) { child = child * 10 + (CUR - '0'); NEXT; } xmlXPtrGetChildNo(ctxt, child); }}/** * xmlXPtrEvalXPointer: * @ctxt: the XPointer Parser context * * XPointer ::= Name * | ChildSeq * | FullXPtr * * Parse and evaluate an XPointer */static voidxmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) { if (ctxt->valueTab == NULL) { /* Allocate the value stack */ ctxt->valueTab = (xmlXPathObjectPtr *) xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); if (ctxt->valueTab == NULL) { xmlXPtrErrMemory("allocating evaluation context"); return; } ctxt->valueNr = 0; ctxt->valueMax = 10; ctxt->value = NULL; } SKIP_BLANKS; if (CUR == '/') { xmlXPathRoot(ctxt); xmlXPtrEvalChildSeq(ctxt, NULL); } else { xmlChar *name; name = xmlXPathParseName(ctxt); if (name == NULL) XP_ERROR(XPATH_EXPR_ERROR); if (CUR == '(') { xmlXPtrEvalFullXPtr(ctxt, name); /* Short evaluation */ return; } else { /* this handle both Bare Names and Child Sequences */ xmlXPtrEvalChildSeq(ctxt, name); } } SKIP_BLANKS; if (CUR != 0) XP_ERROR(XPATH_EXPR_ERROR);}/************************************************************************ * * * General routines * * * ************************************************************************/void xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);void xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs);void xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs);void xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs);void xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs);void xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs);void xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);/** * xmlXPtrNewContext: * @doc: the XML document * @here: the node that directly contains the XPointer being evaluated or NULL * @origin: the element from which a user or program initiated traversal of * the link, or NULL. * * Create a new XPointer context * * Returns the xmlXPathContext just allocated. */xmlXPathContextPtrxmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) { xmlXPathContextPtr ret; ret = xmlXPathNewContext(doc); if (ret == NULL) return(ret); ret->xptr = 1; ret->here = here; ret->origin = origin; xmlXPathRegisterFunc(ret, (xmlChar *)"range-to", xmlXPtrRangeToFunction); xmlXPathRegisterFunc(ret, (xmlChar *)"range", xmlXPtrRangeFunction); xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside", xmlXPtrRangeInsideFunction); xmlXPathRegisterFunc(ret, (xmlChar *)"string-range", xmlXPtrStringRangeFunction); xmlXPathRegisterFunc(ret, (xmlChar *)"start-point", xmlXPtrStartPointFunction); xmlXPathRegisterFunc(ret, (xmlChar *)"end-point", xmlXPtrEndPointFunction); xmlXPathRegisterFunc(ret, (xmlChar *)"here", xmlXPtrHereFunction); xmlXPathRegisterFunc(ret, (xmlChar *)" origin", xmlXPtrOriginFunction); return(ret);}/** * xmlXPtrEval: * @str: the XPointer expression * @ctx: the XPointer context * * Evaluate the XPath Location Path in the given context. * * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. * the caller has to free the object. */xmlXPathObjectPtrxmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) { xmlXPathParserContextPtr ctxt; xmlXPathObjectPtr res = NULL, tmp; xmlXPathObjectPtr init = NULL; int stack = 0; xmlXPathInit(); if ((ctx == NULL) || (str == NULL)) return(NULL); ctxt = xmlXPathNewParserContext(str, ctx); ctxt->xptr = 1; xmlXPtrEvalXPointer(ctxt); if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NODESET) && (ctxt->value->type != XPATH_LOCATIONSET)) { xmlXPtrErr(ctxt, XML_XPTR_EVAL_FAILED, "xmlXPtrEval: evaluation failed to return a node set\n", NULL); } else { res = valuePop(ctxt); } do { tmp = valuePop(ctxt); if (tmp != NULL) { if (tmp != init) { if (tmp->type == XPATH_NODESET) { /* * Evaluation may push a root nodeset which is unused */ xmlNodeSetPtr set; set = tmp->nodesetval; if ((set->nodeNr != 1) || (set->nodeTab[0] != (xmlNodePtr) ctx->doc)) stack++; } else stack++; } xmlXPathFreeObject(tmp); } } while (tmp != NULL); if (stack != 0) { xmlXPtrErr(ctxt, XML_XPTR_EXTRA_OBJECTS, "xmlXPtrEval: object(s) left on the eval stack\n", NULL); } if (ctxt->error != XPATH_EXPRESSION_OK) { xmlXPathFreeObject(res); res = NULL; } xmlXPathFreeParserContext(ctxt); return(res);}/** * xmlXPtrBuildRangeNodeList: * @range: a range object * * Build a node list tree copy of the range * * Returns an xmlNodePtr list or NULL. * the caller has to free the node tree. */static xmlNodePtrxmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) { /* pointers to generated nodes */ xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp; /* pointers to traversal nodes */ xmlNodePtr start, cur, end; int index1, index2; if (range == NULL) return(NULL); if (range->type != XPATH_RANGE) return(NULL); start = (xmlNodePtr) range->user; if (start == NULL) return(NULL); end = range->user2; if (end == NULL) return(xmlCopyNode(start, 1)); cur = start; index1 = range->index; index2 = range->index2; while (cur != NULL) { if (cur == end) { if (cur->type == XML_TEXT_NODE) { const xmlChar *content = cur->content; int len; if (content == NULL) { tmp = xmlNewTextLen(NULL, 0); } else { len = index2; if ((cur == start) && (index1 > 1)) { content += (index1 - 1); len -= (index1 - 1); index1 = 0; } else { len = index2; } tmp = xmlNewTextLen(content, len); } /* single sub text node selection */ if (list == NULL) return(tmp); /* prune and return full set */ if (last != NULL) xmlAddNextSibling(last, tmp); else xmlAddChild(parent, tmp); return(list); } else { tmp = xmlCopyNode(cur, 0); if (list == NULL) list = tmp; else { if (last != NULL) xmlAddNextSibling(last, tmp); else xmlAddChild(parent, tmp); } last = NULL; parent = tmp; if (index2 > 1) { end = xmlXPtrGetNthChild(cur, index2 - 1); index2 = 0; } if ((cur == start) && (index1 > 1)) { cur = xmlXPtrGetNthChild(cur, index1 - 1); index1 = 0; } else { cur = cur->children; } /* * Now gather the remaining nodes from cur to end */ continue; /* while */ } } else if ((cur == start) && (list == NULL) /* looks superfluous but ... */ ) { if ((cur->type == XML_TEXT_NODE) || (cur->type == XML_CDATA_SECTION_NODE)) { const xmlChar *content = cur->content; if (content == NULL) { tmp = xmlNewTextLen(NULL, 0); } else { if (index1 > 1) { content += (index1 - 1); } tmp = xmlNewText(content); } last = list = tmp; } else { if ((cur == start) && (index1 > 1)) { tmp = xmlCopyNode(cur, 0); list = tmp; parent = tmp; last = NULL; cur = xmlXPtrGetNthChild(cur, index1 - 1); index1 = 0; /* * Now gather the remaining nodes from cur to end */ continue; /* while */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -