📄 pattern.c
字号:
return; } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : Name expected\n"); ctxt->error = 1; return; } } if (IS_BLANK_CH(CUR)) { hasBlanks = 1; SKIP_BLANKS; } if (CUR == ':') { NEXT; if (CUR != ':') { xmlChar *prefix = name; int i; if (hasBlanks || IS_BLANK_CH(CUR)) { ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); ctxt->error = 1; goto error; } /* * This is a namespace match */ token = xmlPatScanName(ctxt); if ((prefix[0] == 'x') && (prefix[1] == 'm') && (prefix[2] == 'l') && (prefix[3] == 0)) { XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE) } else { for (i = 0;i < ctxt->nb_namespaces;i++) { if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i]) break; } } if (i >= ctxt->nb_namespaces) { ERROR5(NULL, NULL, NULL, "xmlCompileStepPattern : no namespace bound to prefix %s\n", prefix); ctxt->error = 1; goto error; } } XML_PAT_FREE_STRING(ctxt, prefix); if (token == NULL) { if (CUR == '*') { NEXT; PUSH(XML_OP_NS, URL, NULL); } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : Name expected\n"); ctxt->error = 1; goto error; } } else { PUSH(XML_OP_ELEM, token, URL); } } else { NEXT; if (xmlStrEqual(name, (const xmlChar *) "child")) { XML_PAT_FREE_STRING(ctxt, name); name = xmlPatScanName(ctxt); if (name == NULL) { if (CUR == '*') { NEXT; PUSH(XML_OP_ALL, NULL, NULL); return; } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : QName expected\n"); ctxt->error = 1; goto error; } } if (CUR == ':') { xmlChar *prefix = name; int i; NEXT; if (IS_BLANK_CH(CUR)) { ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); ctxt->error = 1; goto error; } /* * This is a namespace match */ token = xmlPatScanName(ctxt); if ((prefix[0] == 'x') && (prefix[1] == 'm') && (prefix[2] == 'l') && (prefix[3] == 0)) { XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE) } else { for (i = 0;i < ctxt->nb_namespaces;i++) { if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i]) break; } } if (i >= ctxt->nb_namespaces) { ERROR5(NULL, NULL, NULL, "xmlCompileStepPattern : no namespace bound " "to prefix %s\n", prefix); ctxt->error = 1; goto error; } } XML_PAT_FREE_STRING(ctxt, prefix); if (token == NULL) { if (CUR == '*') { NEXT; PUSH(XML_OP_NS, URL, NULL); } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : Name expected\n"); ctxt->error = 1; goto error; } } else { PUSH(XML_OP_CHILD, token, URL); } } else PUSH(XML_OP_CHILD, name, NULL); return; } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) { XML_PAT_FREE_STRING(ctxt, name) name = NULL; if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) { ERROR5(NULL, NULL, NULL, "Unexpected attribute axis in '%s'.\n", ctxt->base); ctxt->error = 1; goto error; } xmlCompileAttributeTest(ctxt); if (ctxt->error != 0) goto error; return; } else { ERROR5(NULL, NULL, NULL, "The 'element' or 'attribute' axis is expected.\n", NULL); ctxt->error = 1; goto error; } } } else if (CUR == '*') { if (name != NULL) { ctxt->error = 1; goto error; } NEXT; PUSH(XML_OP_ALL, token, NULL); } else { PUSH(XML_OP_ELEM, name, NULL); } return;error: if (URL != NULL) XML_PAT_FREE_STRING(ctxt, URL) if (token != NULL) XML_PAT_FREE_STRING(ctxt, token) if (name != NULL) XML_PAT_FREE_STRING(ctxt, name)}/** * xmlCompilePathPattern: * @ctxt: the compilation context * * Compile the Path Pattern and generates a precompiled * form suitable for fast matching. * * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) */static voidxmlCompilePathPattern(xmlPatParserContextPtr ctxt) { SKIP_BLANKS; if (CUR == '/') { ctxt->comp->flags |= PAT_FROM_ROOT; } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) { ctxt->comp->flags |= PAT_FROM_CUR; } if ((CUR == '/') && (NXT(1) == '/')) { PUSH(XML_OP_ANCESTOR, NULL, NULL); NEXT; NEXT; } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) { PUSH(XML_OP_ANCESTOR, NULL, NULL); NEXT; NEXT; NEXT; /* Check for incompleteness. */ SKIP_BLANKS; if (CUR == 0) { ERROR5(NULL, NULL, NULL, "Incomplete expression '%s'.\n", ctxt->base); ctxt->error = 1; goto error; } } if (CUR == '@') { NEXT; xmlCompileAttributeTest(ctxt); SKIP_BLANKS; /* TODO: check for incompleteness */ if (CUR != 0) { xmlCompileStepPattern(ctxt); if (ctxt->error != 0) goto error; } } else { if (CUR == '/') { PUSH(XML_OP_ROOT, NULL, NULL); NEXT; /* Check for incompleteness. */ SKIP_BLANKS; if (CUR == 0) { ERROR5(NULL, NULL, NULL, "Incomplete expression '%s'.\n", ctxt->base); ctxt->error = 1; goto error; } } xmlCompileStepPattern(ctxt); if (ctxt->error != 0) goto error; SKIP_BLANKS; while (CUR == '/') { if (NXT(1) == '/') { PUSH(XML_OP_ANCESTOR, NULL, NULL); NEXT; NEXT; SKIP_BLANKS; xmlCompileStepPattern(ctxt); if (ctxt->error != 0) goto error; } else { PUSH(XML_OP_PARENT, NULL, NULL); NEXT; SKIP_BLANKS; if (CUR == 0) { ERROR5(NULL, NULL, NULL, "Incomplete expression '%s'.\n", ctxt->base); ctxt->error = 1; goto error; } xmlCompileStepPattern(ctxt); if (ctxt->error != 0) goto error; } } } if (CUR != 0) { ERROR5(NULL, NULL, NULL, "Failed to compile pattern %s\n", ctxt->base); ctxt->error = 1; }error: return;}/** * xmlCompileIDCXPathPath: * @ctxt: the compilation context * * Compile the Path Pattern and generates a precompiled * form suitable for fast matching. * * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) */static voidxmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) { SKIP_BLANKS; if (CUR == '/') { ERROR5(NULL, NULL, NULL, "Unexpected selection of the document root in '%s'.\n", ctxt->base); goto error; } ctxt->comp->flags |= PAT_FROM_CUR; if (CUR == '.') { /* "." - "self::node()" */ NEXT; SKIP_BLANKS; if (CUR == 0) { /* * Selection of the context node. */ PUSH(XML_OP_ELEM, NULL, NULL); return; } if (CUR != '/') { /* TODO: A more meaningful error message. */ ERROR5(NULL, NULL, NULL, "Unexpected token after '.' in '%s'.\n", ctxt->base); goto error; } /* "./" - "self::node()/" */ NEXT; SKIP_BLANKS; if (CUR == '/') { if (IS_BLANK_CH(PEEKPREV(1))) { /* * Disallow "./ /" */ ERROR5(NULL, NULL, NULL, "Unexpected '/' token in '%s'.\n", ctxt->base); goto error; } /* ".//" - "self:node()/descendant-or-self::node()/" */ PUSH(XML_OP_ANCESTOR, NULL, NULL); NEXT; SKIP_BLANKS; } if (CUR == 0) goto error_unfinished; } /* * Process steps. */ do { xmlCompileStepPattern(ctxt); if (ctxt->error != 0) goto error; SKIP_BLANKS; if (CUR != '/') break; PUSH(XML_OP_PARENT, NULL, NULL); NEXT; SKIP_BLANKS; if (CUR == '/') { /* * Disallow subsequent '//'. */ ERROR5(NULL, NULL, NULL, "Unexpected subsequent '//' in '%s'.\n", ctxt->base); goto error; } if (CUR == 0) goto error_unfinished; } while (CUR != 0); if (CUR != 0) { ERROR5(NULL, NULL, NULL, "Failed to compile expression '%s'.\n", ctxt->base); ctxt->error = 1; } return;error: ctxt->error = 1; return;error_unfinished: ctxt->error = 1; ERROR5(NULL, NULL, NULL, "Unfinished expression '%s'.\n", ctxt->base); return;}/************************************************************************ * * * The streaming code * * * ************************************************************************/#ifdef DEBUG_STREAMINGstatic voidxmlDebugStreamComp(xmlStreamCompPtr stream) { int i; if (stream == NULL) { printf("Stream: NULL\n"); return; } printf("Stream: %d steps\n", stream->nbStep); for (i = 0;i < stream->nbStep;i++) { if (stream->steps[i].ns != NULL) { printf("{%s}", stream->steps[i].ns); } if (stream->steps[i].name == NULL) { printf("* "); } else { printf("%s ", stream->steps[i].name); } if (stream->steps[i].flags & XML_STREAM_STEP_ROOT) printf("root "); if (stream->steps[i].flags & XML_STREAM_STEP_DESC) printf("// "); if (stream->steps[i].flags & XML_STREAM_STEP_FINAL) printf("final "); printf("\n"); }}static voidxmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) { int i; if (ctxt == NULL) { printf("Stream: NULL\n"); return; } printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState); if (match) printf("matches\n"); else printf("\n"); for (i = 0;i < ctxt->nbState;i++) { if (ctxt->states[2 * i] < 0) printf(" %d: free\n", i); else { printf(" %d: step %d, level %d", i, ctxt->states[2 * i], ctxt->states[(2 * i) + 1]); if (ctxt->comp->steps[ctxt->states[2 * i]].flags & XML_STREAM_STEP_DESC) printf(" //\n"); else printf("\n"); } }}#endif/** * xmlNewStreamComp: * @size: the number of expected steps * * build a new compiled pattern for streaming * * Returns the new structure or NULL in case of error. */static xmlStreamCompPtrxmlNewStreamComp(int size) { xmlStreamCompPtr cur; if (size < 4) size = 4; cur = (xmlStreamCompPtr) xmlMalloc(sizeof(xmlStreamComp)); if (cur == NULL) { ERROR(NULL, NULL, NULL, "xmlNewStreamComp: malloc failed\n"); return(NULL); } memset(cur, 0, sizeof(xmlStreamComp)); cur->steps = (xmlStreamStepPtr) xmlMalloc(size * sizeof(xmlStreamStep)); if (cur->steps == NULL) { xmlFree(cur); ERROR(NULL, NULL, NULL, "xmlNewStreamComp: malloc failed\n"); return(NULL); } cur->nbStep = 0; cur->maxStep = size; return(cur);}/** * xmlFreeStreamComp: * @comp: the compiled pattern for streaming * * Free the compiled pattern for streaming */static voidxmlFreeStreamComp(xmlStreamCompPtr comp) { if (comp != NULL) { if (comp->steps != NULL) xmlFree(comp->steps); if (comp->dict != NULL) xmlDictFree(comp->dict); xmlFree(comp); }}/** * xmlStreamCompAddStep: * @comp: the compiled pattern for streaming * @name: the first string, the name, or NULL for * * @ns: the second step, the namespace name * @flags: the flags for that step * * Add a new step to the compiled pattern * * Returns -1 in case of error or the step index if successful */static intxmlStreamCompAddStep(xmlStreamCompPtr comp, const xmlChar *name, const xmlChar *ns, int nodeType, int flags) { xmlStreamStepPtr cur; if (comp->nbStep >= comp->maxStep) { cur = (xmlStreamStepPtr) xmlRealloc(comp->steps, comp->maxStep * 2 * sizeof(xmlStreamStep)); if (cur == NULL) { ERROR(NULL, NULL, NULL, "xmlNewStreamComp: malloc failed\n"); return(-1); } comp->steps = cur; comp->maxStep *= 2; } cur = &comp->steps[comp->nbStep++]; cur->flags = flags; cur->name = name; cur->ns = ns; cur->nodeType = nodeType; return(comp->nbStep - 1);}/** * xmlStreamCompile: * @comp: the precompiled pattern * * Tries to stream compile a pattern
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -