📄 xpath.c
字号:
#endif int i; xmlNodeSetPtr ret; xmlXPathTraversalFunction next = NULL; xmlNodePtr cur = NULL; if (ctxt->context->nodelist == NULL) { if (ctxt->context->node == NULL) { fprintf(xmlXPathDebug, "xmlXPathNodeCollectAndTest %s:%d : nodelist and node are NULL\n", __FILE__, __LINE__); return(NULL); } STRANGE return(NULL); }#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "new step : ");#endif switch (axis) { case AXIS_ANCESTOR:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'ancestors' ");#endif next = xmlXPathNextAncestor; break; case AXIS_ANCESTOR_OR_SELF:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'ancestors-or-self' ");#endif next = xmlXPathNextAncestorOrSelf; break; case AXIS_ATTRIBUTE:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'attributes' ");#endif next = (xmlXPathTraversalFunction) xmlXPathNextAttribute; break; break; case AXIS_CHILD:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'child' ");#endif next = xmlXPathNextChild; break; case AXIS_DESCENDANT:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'descendant' ");#endif next = xmlXPathNextDescendant; break; case AXIS_DESCENDANT_OR_SELF:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'descendant-or-self' ");#endif next = xmlXPathNextDescendantOrSelf; break; case AXIS_FOLLOWING:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'following' ");#endif next = xmlXPathNextFollowing; break; case AXIS_FOLLOWING_SIBLING:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'following-siblings' ");#endif next = xmlXPathNextFollowingSibling; break; case AXIS_NAMESPACE:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'namespace' ");#endif next = (xmlXPathTraversalFunction) xmlXPathNextNamespace; break; break; case AXIS_PARENT:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'parent' ");#endif next = xmlXPathNextParent; break; case AXIS_PRECEDING:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'preceding' ");#endif next = xmlXPathNextPreceding; break; case AXIS_PRECEDING_SIBLING:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'preceding-sibling' ");#endif next = xmlXPathNextPrecedingSibling; break; case AXIS_SELF:#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "axis 'self' ");#endif next = xmlXPathNextSelf; break; } if (next == NULL) return(NULL); ret = xmlXPathNodeSetCreate(NULL);#ifdef DEBUG_STEP fprintf(xmlXPathDebug, " context contains %d nodes\n", ctxt->context->nodelist->nodeNr); switch (test) { case NODE_TEST_NONE: fprintf(xmlXPathDebug, " searching for none !!!\n"); break; case NODE_TEST_TYPE: fprintf(xmlXPathDebug, " searching for type %d\n", type); break; case NODE_TEST_PI: fprintf(xmlXPathDebug, " searching for PI !!!\n"); break; case NODE_TEST_ALL: fprintf(xmlXPathDebug, " searching for *\n"); break; case NODE_TEST_NS: fprintf(xmlXPathDebug, " searching for namespace %s\n", prefix); break; case NODE_TEST_NAME: fprintf(xmlXPathDebug, " searching for name %s\n", name); if (prefix != NULL) fprintf(xmlXPathDebug, " with namespace %s\n", prefix); break; } fprintf(xmlXPathDebug, "Testing : ");#endif for (i = 0;i < ctxt->context->nodelist->nodeNr; i++) { ctxt->context->node = ctxt->context->nodelist->nodeTab[i]; cur = NULL; do { cur = next(ctxt, cur); if (cur == NULL) break;#ifdef DEBUG_STEP t++; fprintf(xmlXPathDebug, " %s", cur->name);#endif switch (test) { case NODE_TEST_NONE: STRANGE return(NULL); case NODE_TEST_TYPE: if ((cur->type == type) || ((type == XML_ELEMENT_NODE) && ((cur->type == XML_DOCUMENT_NODE) || (cur->type == XML_HTML_DOCUMENT_NODE)))) {#ifdef DEBUG_STEP n++;#endif xmlXPathNodeSetAdd(ret, cur); } break; case NODE_TEST_PI: if (cur->type == XML_PI_NODE) { if ((name != NULL) && (xmlStrcmp(name, cur->name))) break;#ifdef DEBUG_STEP n++;#endif xmlXPathNodeSetAdd(ret, cur); } break; case NODE_TEST_ALL: if ((cur->type == XML_ELEMENT_NODE) || (cur->type == XML_ATTRIBUTE_NODE)) { /* !!! || (cur->type == XML_TEXT_NODE)) { */#ifdef DEBUG_STEP n++;#endif xmlXPathNodeSetAdd(ret, cur); } break; case NODE_TEST_NS: { TODO /* namespace search */ break; } case NODE_TEST_NAME: switch (cur->type) { case XML_ELEMENT_NODE: if (!xmlStrcmp(name, cur->name) && (((prefix == NULL) || ((cur->ns != NULL) && (!xmlStrcmp(prefix, cur->ns->href)))))) {#ifdef DEBUG_STEP n++;#endif xmlXPathNodeSetAdd(ret, cur); } break; case XML_ATTRIBUTE_NODE: { xmlAttrPtr attr = (xmlAttrPtr) cur; if (!xmlStrcmp(name, attr->name)) {#ifdef DEBUG_STEP n++;#endif xmlXPathNodeSetAdd(ret, cur); } break; } default: break; } break; } } while (cur != NULL); }#ifdef DEBUG_STEP fprintf(xmlXPathDebug, "\nExamined %d nodes, found %d nodes at that step\n", t, n);#endif return(ret);}/************************************************************************ * * * Implicit tree core function library * * * ************************************************************************//** * xmlXPathRoot: * @ctxt: the XPath Parser context * * Initialize the context to the root of the document */voidxmlXPathRoot(xmlXPathParserContextPtr ctxt) { if (ctxt->context->nodelist != NULL) xmlXPathFreeNodeSet(ctxt->context->nodelist); ctxt->context->node = (xmlNodePtr) ctxt->context->doc; ctxt->context->nodelist = xmlXPathNodeSetCreate(ctxt->context->node);}/************************************************************************ * * * The explicit core function library * *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib * * * ************************************************************************//** * xmlXPathLastFunction: * @ctxt: the XPath Parser context * * Implement the last() XPath function * The last function returns the number of nodes in the context node list. */voidxmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(0); if ((ctxt->context->nodelist == NULL) || (ctxt->context->node == NULL) || (ctxt->context->nodelist->nodeNr == 0)) { valuePush(ctxt, xmlXPathNewFloat((double) 0)); } else { valuePush(ctxt, xmlXPathNewFloat((double) ctxt->context->nodelist->nodeNr)); }}/** * xmlXPathPositionFunction: * @ctxt: the XPath Parser context * * Implement the position() XPath function * The position function returns the position of the context node in the * context node list. The first position is 1, and so the last positionr * will be equal to last(). */voidxmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) { int i; CHECK_ARITY(0); if ((ctxt->context->nodelist == NULL) || (ctxt->context->node == NULL) || (ctxt->context->nodelist->nodeNr == 0)) { valuePush(ctxt, xmlXPathNewFloat((double) 0)); } for (i = 0; i < ctxt->context->nodelist->nodeNr;i++) { if (ctxt->context->node == ctxt->context->nodelist->nodeTab[i]) { valuePush(ctxt, xmlXPathNewFloat((double) i + 1)); return; } } valuePush(ctxt, xmlXPathNewFloat((double) 0));}/** * xmlXPathCountFunction: * @ctxt: the XPath Parser context * * Implement the count() XPath function */voidxmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); valuePush(ctxt, xmlXPathNewFloat((double) cur->nodesetval->nodeNr)); xmlXPathFreeObject(cur);}/** * xmlXPathIdFunction: * @ctxt: the XPath Parser context * * Implement the id() XPath function * The id function selects elements by their unique ID * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set, * then the result is the union of the result of applying id to the * string value of each of the nodes in the argument node-set. When the * argument to id is of any other type, the argument is converted to a * string as if by a call to the string function; the string is split * into a whitespace-separated list of tokens (whitespace is any sequence * of characters matching the production S); the result is a node-set * containing the elements in the same document as the context node that * have a unique ID equal to any of the tokens in the list. */voidxmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) { const xmlChar *tokens; const xmlChar *cur; xmlChar *ID; xmlAttrPtr attr; xmlNodePtr elem = NULL; xmlXPathObjectPtr ret, obj; CHECK_ARITY(1); obj = valuePop(ctxt); if (obj == NULL) ERROR(XPATH_INVALID_OPERAND); if (obj->type == XPATH_NODESET) { TODO /* ID function in case of NodeSet */ } if (obj->type != XPATH_STRING) { valuePush(ctxt, obj); xmlXPathStringFunction(ctxt, 1); obj = valuePop(ctxt); if (obj->type != XPATH_STRING) { xmlXPathFreeObject(obj); return; } } tokens = obj->stringval; ret = xmlXPathNewNodeSet(NULL); valuePush(ctxt, ret); if (tokens == NULL) { xmlXPathFreeObject(obj); return; } cur = tokens; while (IS_BLANK(*cur)) cur++; while (*cur != 0) { while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) || (*cur == '.') || (*cur == '-') || (*cur == '_') || (*cur == ':') || (IS_COMBINING(*cur)) || (IS_EXTENDER(*cur))) cur++; if ((!IS_BLANK(*cur)) && (*cur != 0)) break; ID = xmlStrndup(tokens, cur - tokens); attr = xmlGetID(ctxt->context->doc, ID); if (attr != NULL) { elem = attr->parent; xmlXPathNodeSetAdd(ret->nodesetval, elem); } if (ID != NULL) xmlFree(ID); while (IS_BLANK(*cur)) cur++; tokens = cur; } xmlXPathFreeObject(obj); return;}/** * xmlXPathLocalPartFunction: * @ctxt: the XPath Parser context * * Implement the local-part() XPath function * The local-part function returns a string containing the local part * of the name of the node in the argument node-set that is first in * document order. If the node-set is empty or the first node has no * name, an empty string is returned. If the argument is omitted it * defaults to the context node. */voidxmlXPathLocalPartFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); if (cur->nodesetval->nodeNr == 0) { valuePush(ctxt, xmlXPathNewCString("")); } else { int i = 0; /* Should be first in document order !!!!! */ valuePush(ctxt, xmlXPathNewString(cur->nodesetval->nodeTab[i]->name)); } xmlXPathFreeObject(cur);}/** * xmlXPathNamespaceFunction: * @ctxt: the XPath Parser context * * Implement the namespace() XPath function * The namespace function returns a string containing the namespace URI * of the expanded name of the node in the argument node-set that is * first in document order. If the node-set is empty, the first node has * no name, or the expanded name has no namespace URI, an empty string * is returned. If the argument is omitted it defaults to the context node. */voidxmlXPathNamespaceFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; if (nargs == 0) { valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node)); nargs = 1; } CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); if (cur->nodesetval->nodeNr == 0) { valuePush(ctxt, xmlXPathNewCString("")); } else { int i = 0; /* Should be first in document order !!!!! */ if (cur->nodesetval->nodeTab[i]->ns == NULL) valuePush(ctxt, xmlXPathNewCString("")); else valuePush(ctxt, xmlXPathNewString( cur->nodesetval->nodeTab[i]->ns->href)); } xmlXPathFreeObject(cur);}/** * xmlXPathNameFunction: * @ctxt: the XPath Parser context * * Implement the name() XPath function * The name function returns a string containing a QName representing * the name of the node in the argument node-set that is first in documenti * order. The QName must represent the name with respect to the namespace * declarations in effect on the node whose name is being represented. * Typically, this will be the form in which the name occurred in the XML * source. This need not be the case if there are namespace declarations * in effect on the node that associate multiple prefixes with the same * namespace. However, an implementation may include information about * the original prefix in its representation of nodes; in this case, an * implementation can ensure that the returned string is always the same * as the QName used in the XML source. If the argument it omitted it * defaults to the context node. * Libxml keep the original prefix so the "real qualified name" used is * returned. */voidxmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); if (cur->nodesetval->nodeNr == 0) { valuePush(ctxt, xmlXPathNewCString("")); } else { int i = 0; /* Should be first
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -