📄 pattern.c.svn-base
字号:
return(0); if (!xmlStrEqual(step->value, node->ns->href)) return(0); } break; case XML_OP_ALL: if (node->type != XML_ELEMENT_NODE) return(0); break; } } return(1);}/************************************************************************ * * * Dedicated parser for templates * * * ************************************************************************/#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);#define CUR (*ctxt->cur)#define SKIP(val) ctxt->cur += (val)#define NXT(val) ctxt->cur[(val)]#define CUR_PTR ctxt->cur#define SKIP_BLANKS \ while (IS_BLANK_CH(CUR)) NEXT#define CURRENT (*ctxt->cur)#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)#define PUSH(op, val, val2) \ if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;#define XSLT_ERROR(X) \ { xsltError(ctxt, __FILE__, __LINE__, X); \ ctxt->error = (X); return; }#define XSLT_ERROR0(X) \ { xsltError(ctxt, __FILE__, __LINE__, X); \ ctxt->error = (X); return(0); }#if 0/** * xmlPatScanLiteral: * @ctxt: the XPath Parser context * * Parse an XPath Litteral: * * [29] Literal ::= '"' [^"]* '"' * | "'" [^']* "'" * * Returns the Literal parsed or NULL */static xmlChar *xmlPatScanLiteral(xmlPatParserContextPtr ctxt) { const xmlChar *q, *cur; xmlChar *ret = NULL; int val, len; SKIP_BLANKS; if (CUR == '"') { NEXT; cur = q = CUR_PTR; val = xmlStringCurrentChar(NULL, cur, &len); while ((IS_CHAR(val)) && (val != '"')) { cur += len; val = xmlStringCurrentChar(NULL, cur, &len); } if (!IS_CHAR(val)) { ctxt->error = 1; return(NULL); } else { ret = xmlStrndup(q, cur - q); } cur += len; CUR_PTR = cur; } else if (CUR == '\'') { NEXT; cur = q = CUR_PTR; val = xmlStringCurrentChar(NULL, cur, &len); while ((IS_CHAR(val)) && (val != '\'')) { cur += len; val = xmlStringCurrentChar(NULL, cur, &len); } if (!IS_CHAR(val)) { ctxt->error = 1; return(NULL); } else { ret = xmlStrndup(q, cur - q); } cur += len; CUR_PTR = cur; } else { /* XP_ERROR(XPATH_START_LITERAL_ERROR); */ ctxt->error = 1; return(NULL); } return(ret);}#endif/** * xmlPatScanName: * @ctxt: the XPath Parser context * * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | * CombiningChar | Extender * * [5] Name ::= (Letter | '_' | ':') (NameChar)* * * [6] Names ::= Name (S Name)* * * Returns the Name parsed or NULL */static xmlChar *xmlPatScanName(xmlPatParserContextPtr ctxt) { const xmlChar *q, *cur; xmlChar *ret = NULL; int val, len; SKIP_BLANKS; cur = q = CUR_PTR; val = xmlStringCurrentChar(NULL, cur, &len); if (!IS_LETTER(val) && (val != '_') && (val != ':')) return(NULL); while ((IS_LETTER(val)) || (IS_DIGIT(val)) || (val == '.') || (val == '-') || (val == '_') || (IS_COMBINING(val)) || (IS_EXTENDER(val))) { cur += len; val = xmlStringCurrentChar(NULL, cur, &len); } ret = xmlStrndup(q, cur - q); CUR_PTR = cur; return(ret);}/** * xmlPatScanNCName: * @ctxt: the XPath Parser context * * Parses a non qualified name * * Returns the Name parsed or NULL */static xmlChar *xmlPatScanNCName(xmlPatParserContextPtr ctxt) { const xmlChar *q, *cur; xmlChar *ret = NULL; int val, len; SKIP_BLANKS; cur = q = CUR_PTR; val = xmlStringCurrentChar(NULL, cur, &len); if (!IS_LETTER(val) && (val != '_')) return(NULL); while ((IS_LETTER(val)) || (IS_DIGIT(val)) || (val == '.') || (val == '-') || (val == '_') || (IS_COMBINING(val)) || (IS_EXTENDER(val))) { cur += len; val = xmlStringCurrentChar(NULL, cur, &len); } ret = xmlStrndup(q, cur - q); CUR_PTR = cur; return(ret);}#if 0/** * xmlPatScanQName: * @ctxt: the XPath Parser context * @prefix: the place to store the prefix * * Parse a qualified name * * Returns the Name parsed or NULL */static xmlChar *xmlPatScanQName(xmlPatParserContextPtr ctxt, xmlChar **prefix) { xmlChar *ret = NULL; *prefix = NULL; ret = xmlPatScanNCName(ctxt); if (CUR == ':') { *prefix = ret; NEXT; ret = xmlPatScanNCName(ctxt); } return(ret);}#endif/** * xmlCompileStepPattern: * @ctxt: the compilation context * * Compile the Step Pattern and generates a precompiled * form suitable for fast matching. * * [3] Step ::= '.' | NameTest * [4] NameTest ::= QName | '*' | NCName ':' '*' */static voidxmlCompileStepPattern(xmlPatParserContextPtr ctxt) { xmlChar *token = NULL; xmlChar *name = NULL; const xmlChar *URI = NULL; xmlChar *URL = NULL; SKIP_BLANKS; if (CUR == '.') { NEXT; PUSH(XML_OP_ELEM, NULL, NULL); return; } name = xmlPatScanNCName(ctxt); if (name == NULL) { if (CUR == '*') { NEXT; PUSH(XML_OP_ALL, NULL, NULL); return; } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : Name expected\n"); ctxt->error = 1; return; } } SKIP_BLANKS; if (CUR == ':') { NEXT; if (CUR != ':') { xmlChar *prefix = name; xmlNsPtr ns; /* * This is a namespace match */ token = xmlPatScanName(ctxt); ns = xmlSearchNs(NULL, ctxt->elem, prefix); if (ns == NULL) { ERROR5(NULL, NULL, NULL, "xmlCompileStepPattern : no namespace bound to prefix %s\n", prefix); ctxt->error = 1; goto error; } else { URL = xmlStrdup(ns->href); } xmlFree(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(token, (const xmlChar *) "child")) { xmlFree(token); token = xmlPatScanName(ctxt); if (token == NULL) { if (CUR == '*') { NEXT; PUSH(XML_OP_ALL, token, NULL); return; } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : QName expected\n"); ctxt->error = 1; goto error; } } TODO /* URI = xsltGetQNameURI(ctxt->elem, &token); */ if (token == NULL) { ctxt->error = 1; goto error; } else { name = xmlStrdup(token); if (URI != NULL) URL = xmlStrdup(URI); } PUSH(XML_OP_CHILD, name, URL); } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) { xmlFree(token); token = xmlPatScanName(ctxt); if (token == NULL) { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : QName expected\n"); ctxt->error = 1; goto error; } TODO /* URI = xsltGetQNameURI(ctxt->elem, &token); */ if (token == NULL) { ctxt->error = 1; goto error; } else { name = xmlStrdup(token); if (URI != NULL) URL = xmlStrdup(URI); } PUSH(XML_OP_ATTR, name, URL); } else { ERROR(NULL, NULL, NULL, "xmlCompileStepPattern : 'child' or 'attribute' expected\n"); ctxt->error = 1; goto error; } xmlFree(token); } } else if (CUR == '*') { NEXT; PUSH(XML_OP_ALL, token, NULL); } else { if (name == NULL) { ctxt->error = 1; goto error; } PUSH(XML_OP_ELEM, name, NULL); } return;error: if (token != NULL) xmlFree(token); if (name != NULL) xmlFree(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 == '/') && (NXT(1) == '/')) { /* * since we reverse the query * a leading // can be safely ignored */ NEXT; NEXT; } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) { /* * a leading .// can be safely ignored */ NEXT; NEXT; NEXT; } if (CUR == '@') { TODO } else { xmlCompileStepPattern(ctxt); SKIP_BLANKS; while (CUR == '/') { if ((CUR == '/') && (NXT(1) == '/')) { PUSH(XML_OP_ANCESTOR, NULL, NULL); NEXT; NEXT; SKIP_BLANKS; xmlCompileStepPattern(ctxt); } else { PUSH(XML_OP_PARENT, NULL, NULL); NEXT; SKIP_BLANKS; if ((CUR != 0) || (CUR == '|')) { xmlCompileStepPattern(ctxt); } } } }error: return;}/************************************************************************ * * * The public interfaces * * * ************************************************************************//** * xmlPatterncompile: * @pattern: the pattern to compile * @dict: an optional dictionnary for interned strings * @flags: compilation flags, undefined yet * @namespaces: the prefix definitions, array of [URI, prefix] or NULL * * Compile a pattern. * * Returns the compiled for of the pattern or NULL in case of error */xmlPatternPtrxmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags ATTRIBUTE_UNUSED, const xmlChar **namespaces) { xmlPatternPtr ret = NULL; xmlPatParserContextPtr ctxt = NULL; ctxt = xmlNewPatParserContext(pattern, dict, namespaces); if (ctxt == NULL) goto error; ret = xmlNewPattern(); if (ret == NULL) goto error; ctxt->comp = ret; xmlCompilePathPattern(ctxt); xmlFreePatParserContext(ctxt); xmlReversePattern(ret); return(ret);error: if (ctxt != NULL) xmlFreePatParserContext(ctxt); if (ret != NULL) xmlFreePattern(ret); return(NULL);}/** * xmlPatternMatch: * @comp: the precompiled pattern * @node: a node * * Test wether 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){ if ((comp == NULL) || (node == NULL)) return(-1); return(xmlPatMatch(comp, node));}#endif /* LIBXML_PATTERN_ENABLED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -