📄 pattern.c.svn-base
字号:
/* * pattern.c: Implemetation of selectors for nodes * * Reference: * http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ * to some extent * http://www.w3.org/TR/1999/REC-xml-19991116 * * See Copyright for the status of this software. * * daniel@veillard.com */#define IN_LIBXML#include "libxml.h"#include <string.h>#include <libxml/xmlmemory.h>#include <libxml/tree.h>#include <libxml/hash.h>#include <libxml/dict.h>#include <libxml/xmlerror.h>#include <libxml/parserInternals.h>#include <libxml/pattern.h>#ifdef LIBXML_PATTERN_ENABLED#define ERROR(a, b, c, d)#define ERROR5(a, b, c, d, e)/* * Types are private: */typedef enum { XML_OP_END=0, XML_OP_ROOT, XML_OP_ELEM, XML_OP_CHILD, XML_OP_ATTR, XML_OP_PARENT, XML_OP_ANCESTOR, XML_OP_NS, XML_OP_ALL} xmlPatOp;typedef struct _xmlStepOp xmlStepOp;typedef xmlStepOp *xmlStepOpPtr;struct _xmlStepOp { xmlPatOp op; const xmlChar *value; const xmlChar *value2;};struct _xmlPattern { void *data; /* the associated template */ struct _xmlPattern *next; /* siblings */ const xmlChar *pattern; /* the pattern */ /* TODO fix the statically allocated size steps[] */ int nbStep; int maxStep; xmlStepOp steps[10]; /* ops for computation */};typedef struct _xmlPatParserContext xmlPatParserContext;typedef xmlPatParserContext *xmlPatParserContextPtr;struct _xmlPatParserContext { const xmlChar *cur; /* the current char being parsed */ const xmlChar *base; /* the full expression */ int error; /* error code */ xmlDictPtr dict; /* the dictionnary if any */ xmlPatternPtr comp; /* the result */ xmlNodePtr elem; /* the current node if any */ const xmlChar **namespaces; /* the namespaces definitions */ int nb_namespaces; /* the number of namespaces */};/************************************************************************ * * * Type functions * * * ************************************************************************//** * xmlNewPattern: * * Create a new XSLT Pattern * * Returns the newly allocated xmlPatternPtr or NULL in case of error */static xmlPatternPtrxmlNewPattern(void) { xmlPatternPtr cur; cur = (xmlPatternPtr) xmlMalloc(sizeof(xmlPattern)); if (cur == NULL) { ERROR(NULL, NULL, NULL, "xmlNewPattern : malloc failed\n"); return(NULL); } memset(cur, 0, sizeof(xmlPattern)); cur->maxStep = 10; return(cur);}/** * xmlFreePattern: * @comp: an XSLT comp * * Free up the memory allocated by @comp */voidxmlFreePattern(xmlPatternPtr comp) { xmlStepOpPtr op; int i; if (comp == NULL) return; if (comp->pattern != NULL) xmlFree((xmlChar *)comp->pattern); for (i = 0;i < comp->nbStep;i++) { op = &comp->steps[i]; if (op->value != NULL) xmlFree((xmlChar *) op->value); if (op->value2 != NULL) xmlFree((xmlChar *) op->value2); } memset(comp, -1, sizeof(xmlPattern)); xmlFree(comp);}/** * xmlFreePatternList: * @comp: an XSLT comp list * * Free up the memory allocated by all the elements of @comp */voidxmlFreePatternList(xmlPatternPtr comp) { xmlPatternPtr cur; while (comp != NULL) { cur = comp; comp = comp->next; xmlFreePattern(cur); }}/** * xmlNewPatParserContext: * @pattern: the pattern context * @dict: the inherited dictionnary or NULL * @namespaces: the prefix definitions, array of [URI, prefix] or NULL * * Create a new XML pattern parser context * * Returns the newly allocated xmlPatParserContextPtr or NULL in case of error */static xmlPatParserContextPtrxmlNewPatParserContext(const xmlChar *pattern, xmlDictPtr dict, const xmlChar **namespaces) { xmlPatParserContextPtr cur; if (pattern == NULL) return(NULL); cur = (xmlPatParserContextPtr) xmlMalloc(sizeof(xmlPatParserContext)); if (cur == NULL) { ERROR(NULL, NULL, NULL, "xmlNewPatParserContext : malloc failed\n"); return(NULL); } memset(cur, 0, sizeof(xmlPatParserContext)); cur->dict = dict; cur->cur = pattern; cur->base = pattern; if (namespaces != NULL) { int i; for (i = 0;namespaces[2 * i] != NULL;i++); cur->nb_namespaces = i; } else { cur->nb_namespaces = 0; } cur->namespaces = namespaces; return(cur);}/** * xmlFreePatParserContext: * @ctxt: an XSLT parser context * * Free up the memory allocated by @ctxt */static voidxmlFreePatParserContext(xmlPatParserContextPtr ctxt) { if (ctxt == NULL) return; memset(ctxt, -1, sizeof(xmlPatParserContext)); xmlFree(ctxt);}/** * xmlPatternAdd: * @comp: the compiled match expression * @op: an op * @value: the first value * @value2: the second value * * Add an step to an XSLT Compiled Match * * Returns -1 in case of failure, 0 otherwise. */static intxmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED, xmlPatternPtr comp, xmlPatOp op, xmlChar * value, xmlChar * value2){ if (comp->nbStep >= 10) { ERROR(ctxt, NULL, NULL, "xmlPatternAdd: overflow\n"); return (-1); } comp->steps[comp->nbStep].op = op; comp->steps[comp->nbStep].value = value; comp->steps[comp->nbStep].value2 = value2; comp->nbStep++; return (0);}#if 0/** * xsltSwapTopPattern: * @comp: the compiled match expression * * reverse the two top steps. */static voidxsltSwapTopPattern(xmlPatternPtr comp) { int i; int j = comp->nbStep - 1; if (j > 0) { register const xmlChar *tmp; register xmlPatOp op; i = j - 1; tmp = comp->steps[i].value; comp->steps[i].value = comp->steps[j].value; comp->steps[j].value = tmp; tmp = comp->steps[i].value2; comp->steps[i].value2 = comp->steps[j].value2; comp->steps[j].value2 = tmp; op = comp->steps[i].op; comp->steps[i].op = comp->steps[j].op; comp->steps[j].op = op; }}#endif/** * xmlReversePattern: * @comp: the compiled match expression * * reverse all the stack of expressions */static voidxmlReversePattern(xmlPatternPtr comp) { int i = 0; int j = comp->nbStep - 1; while (j > i) { register const xmlChar *tmp; register xmlPatOp op; tmp = comp->steps[i].value; comp->steps[i].value = comp->steps[j].value; comp->steps[j].value = tmp; tmp = comp->steps[i].value2; comp->steps[i].value2 = comp->steps[j].value2; comp->steps[j].value2 = tmp; op = comp->steps[i].op; comp->steps[i].op = comp->steps[j].op; comp->steps[j].op = op; j--; i++; } comp->steps[comp->nbStep++].op = XML_OP_END;}/************************************************************************ * * * The interpreter for the precompiled patterns * * * ************************************************************************//** * xmlPatMatch: * @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 */static intxmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) { int i; xmlStepOpPtr step; if ((comp == NULL) || (node == NULL)) return(-1); for (i = 0;i < comp->nbStep;i++) { step = &comp->steps[i]; switch (step->op) { case XML_OP_END: return(1); case XML_OP_ROOT: if ((node->type == XML_DOCUMENT_NODE) ||#ifdef LIBXML_DOCB_ENABLED (node->type == XML_DOCB_DOCUMENT_NODE) ||#endif (node->type == XML_HTML_DOCUMENT_NODE)) continue; return(0); case XML_OP_ELEM: if (node->type != XML_ELEMENT_NODE) return(0); if (step->value == NULL) continue; if (step->value[0] != node->name[0]) return(0); if (!xmlStrEqual(step->value, node->name)) return(0); /* Namespace test */ if (node->ns == NULL) { if (step->value2 != NULL) return(0); } else if (node->ns->href != NULL) { if (step->value2 == NULL) return(0); if (!xmlStrEqual(step->value2, node->ns->href)) return(0); } continue; case XML_OP_CHILD: { xmlNodePtr lst; if ((node->type != XML_ELEMENT_NODE) && (node->type != XML_DOCUMENT_NODE) &&#ifdef LIBXML_DOCB_ENABLED (node->type != XML_DOCB_DOCUMENT_NODE) &&#endif (node->type != XML_HTML_DOCUMENT_NODE)) return(0); lst = node->children; if (step->value != NULL) { while (lst != NULL) { if ((lst->type == XML_ELEMENT_NODE) && (step->value[0] == lst->name[0]) && (xmlStrEqual(step->value, lst->name))) break; lst = lst->next; } if (lst != NULL) continue; } return(0); } case XML_OP_ATTR: if (node->type != XML_ATTRIBUTE_NODE) return(0); if (step->value != NULL) { if (step->value[0] != node->name[0]) return(0); if (!xmlStrEqual(step->value, node->name)) return(0); } /* Namespace test */ if (node->ns == NULL) { if (step->value2 != NULL) return(0); } else if (step->value2 != NULL) { if (!xmlStrEqual(step->value2, node->ns->href)) return(0); } continue; case XML_OP_PARENT: if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE) ||#ifdef LIBXML_DOCB_ENABLED (node->type == XML_DOCB_DOCUMENT_NODE) ||#endif (node->type == XML_NAMESPACE_DECL)) return(0); node = node->parent; if (node == NULL) return(0); if (step->value == NULL) continue; if (step->value[0] != node->name[0]) return(0); if (!xmlStrEqual(step->value, node->name)) return(0); /* Namespace test */ if (node->ns == NULL) { if (step->value2 != NULL) return(0); } else if (node->ns->href != NULL) { if (step->value2 == NULL) return(0); if (!xmlStrEqual(step->value2, node->ns->href)) return(0); } continue; case XML_OP_ANCESTOR: /* TODO: implement coalescing of ANCESTOR/NODE ops */ if (step->value == NULL) { i++; step = &comp->steps[i]; if (step->op == XML_OP_ROOT) return(1); if (step->op != XML_OP_ELEM) return(0); if (step->value == NULL) return(-1); } if (node == NULL) return(0); if ((node->type == XML_DOCUMENT_NODE) || (node->type == XML_HTML_DOCUMENT_NODE) ||#ifdef LIBXML_DOCB_ENABLED (node->type == XML_DOCB_DOCUMENT_NODE) ||#endif (node->type == XML_NAMESPACE_DECL)) return(0); node = node->parent; while (node != NULL) { if (node == NULL) return(0); if ((node->type == XML_ELEMENT_NODE) && (step->value[0] == node->name[0]) && (xmlStrEqual(step->value, node->name))) { /* Namespace test */ if (node->ns == NULL) { if (step->value2 == NULL) break; } else if (node->ns->href != NULL) { if ((step->value2 != NULL) && (xmlStrEqual(step->value2, node->ns->href))) break; } } node = node->parent; } if (node == NULL) return(0); continue; case XML_OP_NS: if (node->type != XML_ELEMENT_NODE) return(0); if (node->ns == NULL) { if (step->value != NULL) return(0); } else if (node->ns->href != NULL) { if (step->value == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -