📄 pattern.c
字号:
if (step.flags & XML_STREAM_STEP_ROOT) goto stream_next; desc = step.flags & XML_STREAM_STEP_DESC; if (stream->flags & XML_PATTERN_NOTPATTERN) { /* * Re/enter the expression if it is a "descendant" one, * or if we are at the 1st level of evaluation. */ if (stream->level == 1) { if (XML_STREAM_XS_IDC(stream)) { /* * XS-IDC: The missing "self::node()" will always * match the first given node. */ goto stream_next; } else goto compare; } /* * A "//" is always reentrant. */ if (desc) goto compare; /* * XS-IDC: Process the 2nd level, since the missing * "self::node()" is responsible for the 2nd level being * the real start level. */ if ((stream->level == 2) && XML_STREAM_XS_IDC(stream)) goto compare; goto stream_next; } compare: /* * Check expected node-type. */ if (step.nodeType != nodeType) { if (nodeType == XML_ATTRIBUTE_NODE) goto stream_next; else if (step.nodeType != XML_STREAM_ANY_NODE) goto stream_next; } /* * Compare local/namespace-name. */ match = 0; if (step.nodeType == XML_STREAM_ANY_NODE) { match = 1; } else if (step.name == NULL) { if (step.ns == NULL) { /* * This lets through all elements/attributes. */ match = 1; } else if (ns != NULL) match = xmlStrEqual(step.ns, ns); } else if (((step.ns != NULL) == (ns != NULL)) && (name != NULL) && (step.name[0] == name[0]) && xmlStrEqual(step.name, name) && ((step.ns == ns) || xmlStrEqual(step.ns, ns))) { match = 1; } final = step.flags & XML_STREAM_STEP_FINAL; if (match) { if (final) ret = 1; else xmlStreamCtxtAddState(stream, 1, stream->level); if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { /* * Check if we have a special case like "foo//.", where * "foo" is selected as well. */ ret = 1; } } if (((comp->flags & XML_STREAM_DESC) == 0) && ((! match) || final)) { /* * Mark this expression as blocked for any evaluation at * deeper levels. */ stream->blockLevel = stream->level; }stream_next: stream = stream->next; } /* while stream != NULL */ if (err > 0) ret = -1;#ifdef DEBUG_STREAMING xmlDebugStreamCtxt(orig, ret);#endif return(ret);}/** * xmlStreamPush: * @stream: the stream context * @name: the current name * @ns: the namespace name * * Push new data onto the stream. NOTE: if the call xmlPatterncompile() * indicated a dictionary, then strings for name and ns will be expected * to come from the dictionary. * Both @name and @ns being NULL means the / i.e. the root of the document. * This can also act as a reset. * Otherwise the function will act as if it has been given an element-node. * * Returns: -1 in case of error, 1 if the current state in the stream is a * match and 0 otherwise. */intxmlStreamPush(xmlStreamCtxtPtr stream, const xmlChar *name, const xmlChar *ns) { return (xmlStreamPushInternal(stream, name, ns, (int) XML_ELEMENT_NODE));}/** * xmlStreamPushNode: * @stream: the stream context * @name: the current name * @ns: the namespace name * @nodeType: the type of the node being pushed * * Push new data onto the stream. NOTE: if the call xmlPatterncompile() * indicated a dictionary, then strings for name and ns will be expected * to come from the dictionary. * Both @name and @ns being NULL means the / i.e. the root of the document. * This can also act as a reset. * Different from xmlStreamPush() this function can be fed with nodes of type: * element-, attribute-, text-, cdata-section-, comment- and * processing-instruction-node. * * Returns: -1 in case of error, 1 if the current state in the stream is a * match and 0 otherwise. */intxmlStreamPushNode(xmlStreamCtxtPtr stream, const xmlChar *name, const xmlChar *ns, int nodeType){ return (xmlStreamPushInternal(stream, name, ns, nodeType));}/*** xmlStreamPushAttr:* @stream: the stream context* @name: the current name* @ns: the namespace name** Push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()* indicated a dictionary, then strings for name and ns will be expected* to come from the dictionary.* Both @name and @ns being NULL means the / i.e. the root of the document.* This can also act as a reset.* Otherwise the function will act as if it has been given an attribute-node.** Returns: -1 in case of error, 1 if the current state in the stream is a* match and 0 otherwise.*/intxmlStreamPushAttr(xmlStreamCtxtPtr stream, const xmlChar *name, const xmlChar *ns) { return (xmlStreamPushInternal(stream, name, ns, (int) XML_ATTRIBUTE_NODE));}/** * xmlStreamPop: * @stream: the stream context * * push one level from the stream. * * Returns: -1 in case of error, 0 otherwise. */intxmlStreamPop(xmlStreamCtxtPtr stream) { int i, lev; if (stream == NULL) return(-1); while (stream != NULL) { /* * Reset block-level. */ if (stream->blockLevel == stream->level) stream->blockLevel = -1; stream->level--; if (stream->level < 0) return(-1); /* * Check evolution of existing states */ for (i = stream->nbState -1; i >= 0; i--) { /* discard obsoleted states */ lev = stream->states[(2 * i) + 1]; if (lev > stream->level) stream->nbState--; if (lev <= stream->level) break; } stream = stream->next; } return(0);}/** * xmlStreamWantsAnyNode: * @streamCtxt: the stream context * * Query if the streaming pattern additionally needs to be fed with * text-, cdata-section-, comment- and processing-instruction-nodes. * If the result is 0 then only element-nodes and attribute-nodes * need to be pushed. * * Returns: 1 in case of need of nodes of the above described types, * 0 otherwise. -1 on API errors. */intxmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt){ if (streamCtxt == NULL) return(-1); while (streamCtxt != NULL) { if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) return(1); streamCtxt = streamCtxt->next; } return(0);}/************************************************************************ * * * The public interfaces * * * ************************************************************************//** * xmlPatterncompile: * @pattern: the pattern to compile * @dict: an optional dictionary for interned strings * @flags: compilation flags, see xmlPatternFlags * @namespaces: the prefix definitions, array of [URI, prefix] or NULL * * Compile a pattern. * * Returns the compiled form of the pattern or NULL in case of error */xmlPatternPtrxmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags, const xmlChar **namespaces) { xmlPatternPtr ret = NULL, cur; xmlPatParserContextPtr ctxt = NULL; const xmlChar *or, *start; xmlChar *tmp = NULL; int type = 0; int streamable = 1; if (pattern == NULL) return(NULL); start = pattern; or = start; while (*or != 0) { tmp = NULL; while ((*or != 0) && (*or != '|')) or++; if (*or == 0) ctxt = xmlNewPatParserContext(start, dict, namespaces); else { tmp = xmlStrndup(start, or - start); if (tmp != NULL) { ctxt = xmlNewPatParserContext(tmp, dict, namespaces); } or++; } if (ctxt == NULL) goto error; cur = xmlNewPattern(); if (cur == NULL) goto error; /* * Assign string dict. */ if (dict) { cur->dict = dict; xmlDictReference(dict); } if (ret == NULL) ret = cur; else { cur->next = ret->next; ret->next = cur; } cur->flags = flags; ctxt->comp = cur; if (XML_STREAM_XS_IDC(cur)) xmlCompileIDCXPathPath(ctxt); else xmlCompilePathPattern(ctxt); if (ctxt->error != 0) goto error; xmlFreePatParserContext(ctxt); ctxt = NULL; if (streamable) { if (type == 0) { type = cur->flags & (PAT_FROM_ROOT | PAT_FROM_CUR); } else if (type == PAT_FROM_ROOT) { if (cur->flags & PAT_FROM_CUR) streamable = 0; } else if (type == PAT_FROM_CUR) { if (cur->flags & PAT_FROM_ROOT) streamable = 0; } } if (streamable) xmlStreamCompile(cur); if (xmlReversePattern(cur) < 0) goto error; if (tmp != NULL) { xmlFree(tmp); tmp = NULL; } start = or; } if (streamable == 0) { cur = ret; while (cur != NULL) { if (cur->stream != NULL) { xmlFreeStreamComp(cur->stream); cur->stream = NULL; } cur = cur->next; } } return(ret);error: if (ctxt != NULL) xmlFreePatParserContext(ctxt); if (ret != NULL) xmlFreePattern(ret); if (tmp != NULL) xmlFree(tmp); return(NULL);}/** * xmlPatternMatch: * @comp: the precompiled pattern * @node: a node * * Test whether the node matches the pattern * * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure */intxmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node){ int ret = 0; if ((comp == NULL) || (node == NULL)) return(-1); while (comp != NULL) { ret = xmlPatMatch(comp, node); if (ret != 0) return(ret); comp = comp->next; } return(ret);}/** * xmlPatternGetStreamCtxt: * @comp: the precompiled pattern * * Get a streaming context for that pattern * Use xmlFreeStreamCtxt to free the context. * * Returns a pointer to the context or NULL in case of failure */xmlStreamCtxtPtrxmlPatternGetStreamCtxt(xmlPatternPtr comp){ xmlStreamCtxtPtr ret = NULL, cur; if ((comp == NULL) || (comp->stream == NULL)) return(NULL); while (comp != NULL) { if (comp->stream == NULL) goto failed; cur = xmlNewStreamCtxt(comp->stream); if (cur == NULL) goto failed; if (ret == NULL) ret = cur; else { cur->next = ret->next; ret->next = cur; } cur->flags = comp->flags; comp = comp->next; } return(ret);failed: xmlFreeStreamCtxt(ret); return(NULL);}/** * xmlPatternStreamable: * @comp: the precompiled pattern * * Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt() * should work. * * Returns 1 if streamable, 0 if not and -1 in case of error. */intxmlPatternStreamable(xmlPatternPtr comp) { if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(0); comp = comp->next; } return(1);}/** * xmlPatternMaxDepth: * @comp: the precompiled pattern * * Check the maximum depth reachable by a pattern * * Returns -2 if no limit (using //), otherwise the depth, * and -1 in case of error */intxmlPatternMaxDepth(xmlPatternPtr comp) { int ret = 0, i; if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(-1); for (i = 0;i < comp->stream->nbStep;i++) if (comp->stream->steps[i].flags & XML_STREAM_STEP_DESC) return(-2); if (comp->stream->nbStep > ret) ret = comp->stream->nbStep; comp = comp->next; } return(ret);}/** * xmlPatternMinDepth: * @comp: the precompiled pattern * * Check the minimum depth reachable by a pattern, 0 mean the / or . are * part of the set. * * Returns -1 in case of error otherwise the depth, * */intxmlPatternMinDepth(xmlPatternPtr comp) { int ret = 12345678; if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(-1); if (comp->stream->nbStep < ret) ret = comp->stream->nbStep; if (ret == 0) return(0); comp = comp->next; } return(ret);}/** * xmlPatternFromRoot: * @comp: the precompiled pattern * * Check if the pattern must be looked at from the root. * * Returns 1 if true, 0 if false and -1 in case of error */intxmlPatternFromRoot(xmlPatternPtr comp) { if (comp == NULL) return(-1); while (comp != NULL) { if (comp->stream == NULL) return(-1); if (comp->flags & PAT_FROM_ROOT) return(1); comp = comp->next; } return(0);}#define bottom_pattern#include "elfgcchack.h"#endif /* LIBXML_PATTERN_ENABLED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -