📄 sax2.c
字号:
elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
internal = 0;
}
process_external_subset:
if (elemDecl != NULL) {
xmlAttributePtr attr = elemDecl->attributes;
/*
* Check against defaulted attributes from the external subset
* if the document is stamped as standalone
*/
if ((ctxt->myDoc->standalone == 1) &&
(ctxt->myDoc->extSubset != NULL) &&
(ctxt->validate)) {
while (attr != NULL) {
if ((attr->defaultValue != NULL) &&
(xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
attr->elem, attr->name,
attr->prefix) == attr) &&
(xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
attr->elem, attr->name,
attr->prefix) == NULL)) {
xmlChar *fulln;
if (attr->prefix != NULL) {
fulln = xmlStrdup(attr->prefix);
fulln = xmlStrcat(fulln, BAD_CAST ":");
fulln = xmlStrcat(fulln, attr->name);
} else {
fulln = xmlStrdup(attr->name);
}
/*
* Check that the attribute is not declared in the
* serialization
*/
att = NULL;
if (atts != NULL) {
i = 0;
att = atts[i];
while (att != NULL) {
if (xmlStrEqual(att, fulln))
break;
i += 2;
att = atts[i];
}
}
if (att == NULL) {
xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
"standalone: attribute %s on %s defaulted from external subset\n",
(const char *)fulln,
(const char *)attr->elem);
}
}
attr = attr->nexth;
}
}
/*
* Actually insert defaulted values when needed
*/
attr = elemDecl->attributes;
while (attr != NULL) {
/*
* Make sure that attributes redefinition occuring in the
* internal subset are not overriden by definitions in the
* external subset.
*/
if (attr->defaultValue != NULL) {
/*
* the element should be instantiated in the tree if:
* - this is a namespace prefix
* - the user required for completion in the tree
* like XSLT
* - there isn't already an attribute definition
* in the internal subset overriding it.
*/
if (((attr->prefix != NULL) &&
(xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
((attr->prefix == NULL) &&
(xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
(ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
xmlAttributePtr tst;
tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
attr->elem, attr->name,
attr->prefix);
if ((tst == attr) || (tst == NULL)) {
xmlChar fn[50];
xmlChar *fulln;
fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
if (fulln == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
return;
}
/*
* Check that the attribute is not declared in the
* serialization
*/
att = NULL;
if (atts != NULL) {
i = 0;
att = atts[i];
while (att != NULL) {
if (xmlStrEqual(att, fulln))
break;
i += 2;
att = atts[i];
}
}
if (att == NULL) {
xmlSAX2AttributeInternal(ctxt, fulln,
attr->defaultValue, prefix);
}
if ((fulln != fn) && (fulln != attr->name))
xmlFree(fulln);
}
}
}
attr = attr->nexth;
}
if (internal == 1) {
elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
name, prefix);
internal = 0;
goto process_external_subset;
}
}
}
/**
* 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.
*/
void
xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlNodePtr ret;
xmlNodePtr parent;
xmlNsPtr ns;
xmlChar *name;
xmlChar *prefix;
const xmlChar *att;
const xmlChar *value;
int i;
if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
parent = ctxt->node;
#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);
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
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 == XML_CTXT_FINISH_DTD_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 = XML_CTXT_FINISH_DTD_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.
*/
void
xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlParserNodeInfo node_info;
xmlNodePtr cur;
if (ctx == NULL) return;
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 xmlNodePtr
xmlSAX2TextNode(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) {
xmlErrMemory(ctxt, "xmlSAX2Characters");
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);
if (ret->content == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
xmlFree(ret);
return(NULL);
}
} else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -