📄 sax2.c.svn-base
字号:
/** * xmlSAX2StartElement: * @ctx: the user data (XML parser context) * @fullname: The element name, including namespace prefix * @atts: An array of name/value attributes pairs, NULL terminated * * called when an opening tag has been processed. */voidxmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlNodePtr ret; xmlNodePtr parent = ctxt->node; xmlNsPtr ns; xmlChar *name; xmlChar *prefix; const xmlChar *att; const xmlChar *value; int i;#ifdef DEBUG_SAX xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2StartElement(%s)\n", fullname);#endif /* * First check on validity: */ if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && ((ctxt->myDoc->intSubset == NULL) || ((ctxt->myDoc->intSubset->notations == NULL) && (ctxt->myDoc->intSubset->elements == NULL) && (ctxt->myDoc->intSubset->attributes == NULL) && (ctxt->myDoc->intSubset->entities == NULL)))) { xmlErrValid(ctxt, XML_ERR_NO_DTD, "Validation failed: no DTD found !", NULL, NULL); ctxt->validate = 0; } /* * Split the full name into a namespace prefix and the tag name */ name = xmlSplitQName(ctxt, fullname, &prefix); /* * Note : the namespace resolution is deferred until the end of the * attributes parsing, since local namespace can be defined as * an attribute at this level. */ ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL); if (ret == NULL) { if (prefix != NULL) xmlFree(prefix); ctxt->errNo = XML_ERR_NO_MEMORY; ctxt->instate = XML_PARSER_EOF; ctxt->disableSAX = 1; return; } if (ctxt->myDoc->children == NULL) {#ifdef DEBUG_SAX_TREE xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);#endif xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret); } else if (parent == NULL) { parent = ctxt->myDoc->children; } ctxt->nodemem = -1; if (ctxt->linenumbers) { if (ctxt->input != NULL) { if (ctxt->input->line < 65535) ret->line = (short) ctxt->input->line; else ret->line = 65535; } } /* * We are parsing a new node. */#ifdef DEBUG_SAX_TREE xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);#endif nodePush(ctxt, ret); /* * Link the child element */ if (parent != NULL) { if (parent->type == XML_ELEMENT_NODE) {#ifdef DEBUG_SAX_TREE xmlGenericError(xmlGenericErrorContext, "adding child %s to %s\n", name, parent->name);#endif xmlAddChild(parent, ret); } else {#ifdef DEBUG_SAX_TREE xmlGenericError(xmlGenericErrorContext, "adding sibling %s to ", name); xmlDebugDumpOneNode(stderr, parent, 0);#endif xmlAddSibling(parent, ret); } } /* * Insert all the defaulted attributes from the DTD especially namespaces */ if ((!ctxt->html) && ((ctxt->myDoc->intSubset != NULL) || (ctxt->myDoc->extSubset != NULL))) { xmlCheckDefaultedAttributes(ctxt, name, prefix, atts); } /* * process all the attributes whose name start with "xmlns" */ if (atts != NULL) { i = 0; att = atts[i++]; value = atts[i++]; if (!ctxt->html) { while ((att != NULL) && (value != NULL)) { if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') && (att[3] == 'n') && (att[4] == 's')) xmlSAX2AttributeInternal(ctxt, att, value, prefix); att = atts[i++]; value = atts[i++]; } } } /* * Search the namespace, note that since the attributes have been * processed, the local namespaces are available. */ ns = xmlSearchNs(ctxt->myDoc, ret, prefix); if ((ns == NULL) && (parent != NULL)) ns = xmlSearchNs(ctxt->myDoc, parent, prefix); if ((prefix != NULL) && (ns == NULL)) { ns = xmlNewNs(ret, NULL, prefix); if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL)) ctxt->sax->warning(ctxt->userData, "Namespace prefix %s is not defined\n", prefix); } /* * set the namespace node, making sure that if the default namspace * is unbound on a parent we simply kee it NULL */ if ((ns != NULL) && (ns->href != NULL) && ((ns->href[0] != 0) || (ns->prefix != NULL))) xmlSetNs(ret, ns); /* * process all the other attributes */ if (atts != NULL) { i = 0; att = atts[i++]; value = atts[i++]; if (ctxt->html) { while (att != NULL) { xmlSAX2AttributeInternal(ctxt, att, value, NULL); att = atts[i++]; value = atts[i++]; } } else { while ((att != NULL) && (value != NULL)) { if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') || (att[3] != 'n') || (att[4] != 's')) xmlSAX2AttributeInternal(ctxt, att, value, NULL); /* * Next ones */ att = atts[i++]; value = atts[i++]; } } }#ifdef LIBXML_VALID_ENABLED /* * If it's the Document root, finish the DTD validation and * check the document root element for validity */ if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) { int chk; chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc); if (chk <= 0) ctxt->valid = 0; if (chk < 0) ctxt->wellFormed = 0; ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc); ctxt->vctxt.finishDtd = 1; }#endif /* LIBXML_VALID_ENABLED */ if (prefix != NULL) xmlFree(prefix);}/** * xmlSAX2EndElement: * @ctx: the user data (XML parser context) * @name: The element name * * called when the end of an element has been detected. */voidxmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED){ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; xmlParserNodeInfo node_info; xmlNodePtr cur = ctxt->node;#ifdef DEBUG_SAX if (name == NULL) xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n"); else xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);#endif /* Capture end position and add node */ if (cur != NULL && ctxt->record_info) { node_info.end_pos = ctxt->input->cur - ctxt->input->base; node_info.end_line = ctxt->input->line; node_info.node = cur; xmlParserAddNodeInfo(ctxt, &node_info); } ctxt->nodemem = -1;#ifdef LIBXML_VALID_ENABLED if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc && ctxt->myDoc->intSubset) ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);#endif /* LIBXML_VALID_ENABLED */ /* * end of parsing of this node. */#ifdef DEBUG_SAX_TREE xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);#endif nodePop(ctxt);}#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE *//* * xmlSAX2TextNode: * @ctxt: the parser context * @str: the input string * @len: the string length * * Remove the entities from an attribute value * * Returns the newly allocated string or NULL if not needed or error */static xmlNodePtrxmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { xmlNodePtr ret; const xmlChar *intern = NULL; /* * Allocate */ if (ctxt->freeElems != NULL) { ret = ctxt->freeElems; ctxt->freeElems = ret->next; ctxt->freeElemsNr--; } else { ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); } if (ret == NULL) { if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) ctxt->sax->error(ctxt->userData, "SAX.xmlSAX2Characters(): out of memory\n"); ctxt->errNo = XML_ERR_NO_MEMORY; ctxt->instate = XML_PARSER_EOF; ctxt->disableSAX = 1; return(NULL); } /* * intern the formatting blanks found between tags, or the * very short strings */ if (ctxt->dictNames) { xmlChar cur = str[len]; if ((len <= 3) && ((cur == '"') || (cur == '\'') || ((cur == '<') && (str[len + 1] != '!')))) { intern = xmlDictLookup(ctxt->dict, str, len); } else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') && (str[len + 1] != '!')) { int i; for (i = 1;i < len;i++) { if (!IS_BLANK_CH(str[i])) goto skip; } intern = xmlDictLookup(ctxt->dict, str, len); } }skip: memset(ret, 0, sizeof(xmlNode)); ret->type = XML_TEXT_NODE; ret->name = xmlStringText; if (intern == NULL) ret->content = xmlStrndup(str, len); else ret->content = (xmlChar *) intern; if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue(ret); return(ret);}#ifdef LIBXML_VALID_ENABLED/* * xmlSAX2DecodeAttrEntities: * @ctxt: the parser context * @str: the input string * @len: the string length * * Remove the entities from an attribute value * * Returns the newly allocated string or NULL if not needed or error */static xmlChar *xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, const xmlChar *end) { const xmlChar *in; xmlChar *ret; in = str; while (in < end) if (*in++ == '&') goto decode; return(NULL);decode: ctxt->depth++; ret = xmlStringLenDecodeEntities(ctxt, str, end - str, XML_SUBSTITUTE_REF, 0,0,0); ctxt->depth--; return(ret);}#endif /* LIBXML_VALID_ENABLED *//** * xmlSAX2AttributeNs: * @ctx: the user data (XML parser context) * @localname: the local name of the attribute * @prefix: the attribute namespace prefix if available * @URI: the attribute namespace name if available * @value: Start of the attribute value * @valueend: end of the attribute value * * Handle an attribute that has been read by the parser. * The default handling is to convert the attribute into an * DOM subtree and past it in a new xmlAttr element added to * the element. */static voidxmlSAX2AttributeNs(xmlParserCtxtPtr ctxt, const xmlChar * localname, const xmlChar * prefix, const xmlChar * value, const xmlChar * valueend){ xmlAttrPtr ret; xmlNsPtr namespace = NULL; xmlChar *dup = NULL; /* * Note: if prefix == NULL, the attribute is not in the default namespace */ if (prefix != NULL) namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix); /* * allocate the node */ if (ctxt->freeAttrs != NULL) { ret = ctxt->freeAttrs; ctxt->freeAttrs = ret->next; ctxt->freeAttrsNr--; memset(ret, 0, sizeof(xmlAttr)); ret->type = XML_ATTRIBUTE_NODE; ret->parent = ctxt->node; ret->doc = ctxt->myDoc; ret->ns = namespace; if (ctxt->dictNames) ret->name = localname; else ret->name = xmlStrdup(localname); /* link at the end to preserv order, TODO speed up with a last */ if (ctxt->node->properties == NULL) { ctxt->node->properties = ret; } else { xmlAttrPtr prev = ctxt->node->properties; while (prev->next != NULL) prev = prev->next; prev->next = ret; ret->prev = prev; } if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)) xmlRegisterNodeDefaultValue((xmlNodePtr)ret); } else { if (ctxt->dictNames) ret = xmlNewNsPropEatName(ctxt->node, namespace, (xmlChar *) localname, NULL); else ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL); if (ret == NULL) { ctxt->errNo = XML_ERR_NO_MEMORY; ctxt->instate = XML_PARSER_EOF; ctxt->disableSAX = 1; return; } } if ((ctxt->replaceEntities == 0) && (!ctxt->html)) { xmlNodePtr tmp; /* * We know that if there is an entity reference, then * the string has been dup'ed and terminates with 0 * otherwise with ' or " */ if (*valueend != 0) { tmp = xmlSAX2TextNode(ctxt, value, valueend - value); ret->children = tmp; ret->last = tmp; if (tmp != NULL) { tmp->doc = ret->doc; tmp->parent = (xmlNodePtr) ret; } } else { ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value, valueend - value); tmp = ret->children; while (tmp != NULL) { tmp->parent = (xmlNodePtr) ret; if (tmp->next == NULL) ret->last = tmp; tmp = tmp->next; } } } else if (value != NULL) { xmlNodePtr tmp; tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -