📄 xpath.c.svn-base
字号:
xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) { int depth1, depth2; int attr1 = 0, attr2 = 0; xmlNodePtr attrNode1 = NULL, attrNode2 = NULL; xmlNodePtr cur, root; if ((node1 == NULL) || (node2 == NULL)) return(-2); /* * a couple of optimizations which will avoid computations in most cases */ if (node1->type == XML_ATTRIBUTE_NODE) { attr1 = 1; attrNode1 = node1; node1 = node1->parent; } if (node2->type == XML_ATTRIBUTE_NODE) { attr2 = 1; attrNode2 = node2; node2 = node2->parent; } if (node1 == node2) { if (attr1 == attr2) { /* not required, but we keep attributes in order */ if (attr1 != 0) { cur = attrNode2->prev; while (cur != NULL) { if (cur == attrNode1) return (1); cur = cur->prev; } return (-1); } return(0); } if (attr2 == 1) return(1); return(-1); } if ((node1->type == XML_NAMESPACE_DECL) || (node2->type == XML_NAMESPACE_DECL)) return(1); if (node1 == node2->prev) return(1); if (node1 == node2->next) return(-1); /* * Speedup using document order if availble. */ if ((node1->type == XML_ELEMENT_NODE) && (node2->type == XML_ELEMENT_NODE) && (0 > (long) node1->content) && (0 > (long) node2->content) && (node1->doc == node2->doc)) { long l1, l2; l1 = -((long) node1->content); l2 = -((long) node2->content); if (l1 < l2) return(1); if (l1 > l2) return(-1); } /* * compute depth to root */ for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { if (cur == node1) return(1); depth2++; } root = cur; for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { if (cur == node2) return(-1); depth1++; } /* * Distinct document (or distinct entities :-( ) case. */ if (root != cur) { return(-2); } /* * get the nearest common ancestor. */ while (depth1 > depth2) { depth1--; node1 = node1->parent; } while (depth2 > depth1) { depth2--; node2 = node2->parent; } while (node1->parent != node2->parent) { node1 = node1->parent; node2 = node2->parent; /* should not happen but just in case ... */ if ((node1 == NULL) || (node2 == NULL)) return(-2); } /* * Find who's first. */ if (node1 == node2->prev) return(1); if (node1 == node2->next) return(-1); /* * Speedup using document order if availble. */ if ((node1->type == XML_ELEMENT_NODE) && (node2->type == XML_ELEMENT_NODE) && (0 > (long) node1->content) && (0 > (long) node2->content) && (node1->doc == node2->doc)) { long l1, l2; l1 = -((long) node1->content); l2 = -((long) node2->content); if (l1 < l2) return(1); if (l1 > l2) return(-1); } for (cur = node1->next;cur != NULL;cur = cur->next) if (cur == node2) return(1); return(-1); /* assume there is no sibling list corruption */}/** * xmlXPathNodeSetSort: * @set: the node set * * Sort the node set in document order */voidxmlXPathNodeSetSort(xmlNodeSetPtr set) { int i, j, incr, len; xmlNodePtr tmp; if (set == NULL) return; /* Use Shell's sort to sort the node-set */ len = set->nodeNr; for (incr = len / 2; incr > 0; incr /= 2) { for (i = incr; i < len; i++) { j = i - incr; while (j >= 0) { if (xmlXPathCmpNodes(set->nodeTab[j], set->nodeTab[j + incr]) == -1) { tmp = set->nodeTab[j]; set->nodeTab[j] = set->nodeTab[j + incr]; set->nodeTab[j + incr] = tmp; j -= incr; } else break; } } }}#define XML_NODESET_DEFAULT 10/** * xmlXPathNodeSetDupNs: * @node: the parent node of the namespace XPath node * @ns: the libxml namespace declaration node. * * Namespace node in libxml don't match the XPath semantic. In a node set * the namespace nodes are duplicated and the next pointer is set to the * parent node in the XPath semantic. * * Returns the newly created object. */static xmlNodePtrxmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) { xmlNsPtr cur; if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) return(NULL); if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return((xmlNodePtr) ns); /* * Allocate a new Namespace and fill the fields. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); if (cur == NULL) { xmlXPathErrMemory(NULL, "duplicating namespace\n"); return(NULL); } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_NAMESPACE_DECL; if (ns->href != NULL) cur->href = xmlStrdup(ns->href); if (ns->prefix != NULL) cur->prefix = xmlStrdup(ns->prefix); cur->next = (xmlNsPtr) node; return((xmlNodePtr) cur);}/** * xmlXPathNodeSetFreeNs: * @ns: the XPath namespace node found in a nodeset. * * Namespace nodes in libxml don't match the XPath semantic. In a node set * the namespace nodes are duplicated and the next pointer is set to the * parent node in the XPath semantic. Check if such a node needs to be freed */voidxmlXPathNodeSetFreeNs(xmlNsPtr ns) { if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) return; if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) { if (ns->href != NULL) xmlFree((xmlChar *)ns->href); if (ns->prefix != NULL) xmlFree((xmlChar *)ns->prefix); xmlFree(ns); }}/** * xmlXPathNodeSetCreate: * @val: an initial xmlNodePtr, or NULL * * Create a new xmlNodeSetPtr of type double and of value @val * * Returns the newly created object. */xmlNodeSetPtrxmlXPathNodeSetCreate(xmlNodePtr val) { xmlNodeSetPtr ret; ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet)); if (ret == NULL) { xmlXPathErrMemory(NULL, "creating nodeset\n"); return(NULL); } memset(ret, 0 , (size_t) sizeof(xmlNodeSet)); if (val != NULL) { ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (ret->nodeTab == NULL) { xmlXPathErrMemory(NULL, "creating nodeset\n"); xmlFree(ret); return(NULL); } memset(ret->nodeTab, 0 , XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); ret->nodeMax = XML_NODESET_DEFAULT; if (val->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) val; ret->nodeTab[ret->nodeNr++] = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); } else ret->nodeTab[ret->nodeNr++] = val; } return(ret);}/** * xmlXPathNodeSetContains: * @cur: the node-set * @val: the node * * checks whether @cur contains @val * * Returns true (1) if @cur contains @val, false (0) otherwise */intxmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) { int i; if (val->type == XML_NAMESPACE_DECL) { for (i = 0; i < cur->nodeNr; i++) { if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) { xmlNsPtr ns1, ns2; ns1 = (xmlNsPtr) val; ns2 = (xmlNsPtr) cur->nodeTab[i]; if (ns1 == ns2) return(1); if ((ns1->next != NULL) && (ns2->next == ns1->next) && (xmlStrEqual(ns1->prefix, ns2->prefix))) return(1); } } } else { for (i = 0; i < cur->nodeNr; i++) { if (cur->nodeTab[i] == val) return(1); } } return(0);}/** * xmlXPathNodeSetAddNs: * @cur: the initial node set * @node: the hosting node * @ns: a the namespace node * * add a new namespace node to an existing NodeSet */voidxmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { int i; if ((ns == NULL) || (node == NULL) || (ns->type != XML_NAMESPACE_DECL) || (node->type != XML_ELEMENT_NODE)) return; /* @@ with_ns to check whether namespace nodes should be looked at @@ */ /* * prevent duplicates */ for (i = 0;i < cur->nodeNr;i++) { if ((cur->nodeTab[i] != NULL) && (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) && (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) && (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix))) return; } /* * grow the nodeTab if needed */ if (cur->nodeMax == 0) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (cur->nodeTab == NULL) { xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } memset(cur->nodeTab, 0 , XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); cur->nodeMax = XML_NODESET_DEFAULT; } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; cur->nodeMax *= 2; temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } cur->nodeTab = temp; } cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);}/** * xmlXPathNodeSetAdd: * @cur: the initial node set * @val: a new xmlNodePtr * * add a new xmlNodePtr to an existing NodeSet */voidxmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { int i; if (val == NULL) return;#if 0 if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' ')) return; /* an XSLT fake node */#endif /* @@ with_ns to check whether namespace nodes should be looked at @@ */ /* * prevent duplcates */ for (i = 0;i < cur->nodeNr;i++) if (cur->nodeTab[i] == val) return; /* * grow the nodeTab if needed */ if (cur->nodeMax == 0) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (cur->nodeTab == NULL) { xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } memset(cur->nodeTab, 0 , XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); cur->nodeMax = XML_NODESET_DEFAULT; } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; cur->nodeMax *= 2; temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } cur->nodeTab = temp; } if (val->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) val; cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); } else cur->nodeTab[cur->nodeNr++] = val;}/** * xmlXPathNodeSetAddUnique: * @cur: the initial node set * @val: a new xmlNodePtr * * add a new xmlNodePtr to an existing NodeSet, optimized version * when we are sure the node is not already in the set. */voidxmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { if (val == NULL) return;#if 0 if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' ')) return; /* an XSLT fake node */#endif /* @@ with_ns to check whether namespace nodes should be looked at @@ */ /* * grow the nodeTab if needed */ if (cur->nodeMax == 0) { cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * sizeof(xmlNodePtr)); if (cur->nodeTab == NULL) { xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } memset(cur->nodeTab, 0 , XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); cur->nodeMax = XML_NODESET_DEFAULT; } else if (cur->nodeNr == cur->nodeMax) { xmlNodePtr *temp; cur->nodeMax *= 2; temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * sizeof(xmlNodePtr)); if (temp == NULL) { xmlXPathErrMemory(NULL, "growing nodeset\n"); return; } cur->nodeTab = temp; } if (val->type == XML_NAMESPACE_DECL) { xmlNsPtr ns = (xmlNsPtr) val; cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); } else cur->nodeTab[cur->nodeNr++] = val;}/** * xmlXPathNodeSetMerge: * @val1: the first NodeSet or NULL * @val2: the second NodeSet * * Merges two nodesets, all nodes from @val2 are added to @val1 * if @val1 is NULL, a new set is created and copied from @val2 * * Returns @val1 once extended or NULL in case of error. */xmlNodeSetPtrxmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) { int i, j, initNr, skip; if (val2 == NULL) return(val1); if (val1 == NULL) { val1 = xmlXPathNodeSetCreate(NULL); } /* @@ with_ns to check whether namespace nodes should be looked at @@ */ initNr = val1->nodeNr; for (i = 0;i < val2->nodeNr;i++) { /* * check against duplicates */ skip = 0; for (j = 0; j < initNr; j++) { if (val1->nodeTab[j] == val2->nodeTab[i]) { skip = 1; break; } else if ((val1->nodeTab[j]->type == XML_NAMESPACE_DECL) && (val2->nodeTab[i]->type == XML_NAMESPACE_DECL)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -