📄 sax2.c
字号:
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 void
xmlSAX2AttributeNs(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) {
xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
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->doc = ret->doc;
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);
ret->children = tmp;
ret->last = tmp;
if (tmp != NULL) {
tmp->doc = ret->doc;
tmp->parent = (xmlNodePtr) ret;
}
}
#ifdef LIBXML_VALID_ENABLED
if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset) {
/*
* If we don't substitute entities, the validation should be
* done on a value with replaced entities anyway.
*/
if (!ctxt->replaceEntities) {
dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
if (dup == NULL) {
if (*valueend == 0) {
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
ctxt->myDoc, ctxt->node, ret, value);
} else {
/*
* That should already be normalized.
* cheaper to finally allocate here than duplicate
* entry points in the full validation code
*/
dup = xmlStrndup(value, valueend - value);
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
ctxt->myDoc, ctxt->node, ret, dup);
}
} else {
/*
* dup now contains a string of the flattened attribute
* content with entities substitued. Check if we need to
* apply an extra layer of normalization.
* It need to be done twice ... it's an extra burden related
* to the ability to keep references in attributes
*/
if (ctxt->attsSpecial != NULL) {
xmlChar *nvalnorm;
xmlChar fn[50];
xmlChar *fullname;
fullname = xmlBuildQName(localname, prefix, fn, 50);
if (fullname != NULL) {
ctxt->vctxt.valid = 1;
nvalnorm = xmlValidCtxtNormalizeAttributeValue(
&ctxt->vctxt, ctxt->myDoc,
ctxt->node, fullname, dup);
if (ctxt->vctxt.valid != 1)
ctxt->valid = 0;
if ((fullname != fn) && (fullname != localname))
xmlFree(fullname);
if (nvalnorm != NULL) {
xmlFree(dup);
dup = nvalnorm;
}
}
}
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
ctxt->myDoc, ctxt->node, ret, dup);
}
} else {
/*
* if entities already have been substitued, then
* the attribute as passed is already normalized
*/
dup = xmlStrndup(value, valueend - value);
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
ctxt->myDoc, ctxt->node, ret, dup);
}
} else
#endif /* LIBXML_VALID_ENABLED */
if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
(((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
/*
* when validating, the ID registration is done at the attribute
* validation level. Otherwise we have to do specific handling here.
*/
if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
/* might be worth duplicate entry points and not copy */
if (dup == NULL)
dup = xmlStrndup(value, valueend - value);
xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
if (dup == NULL)
dup = xmlStrndup(value, valueend - value);
xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
} else if ((prefix == ctxt->str_xml) &&
(localname[0] == 'i') && (localname[1] == 'd') &&
(localname[2] == 0)) {
/*
* Add the xml:id value
*
* Open issue: normalization of the value.
*/
if (dup == NULL)
dup = xmlStrndup(value, valueend - value);
#ifdef LIBXML_VALID_ENABLED
if (xmlValidateNCName(dup, 1) != 0) {
xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
"xml:id : attribute value %s is not an NCName\n",
(const char *) dup, NULL);
}
#endif
xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
}
}
if (dup != NULL)
xmlFree(dup);
}
/**
* xmlSAX2StartElementNs:
* @ctx: the user data (XML parser context)
* @localname: the local name of the element
* @prefix: the element namespace prefix if available
* @URI: the element namespace name if available
* @nb_namespaces: number of namespace definitions on that node
* @namespaces: pointer to the array of prefix/URI pairs namespace definitions
* @nb_attributes: the number of attributes on that node
* @nb_defaulted: the number of defaulted attributes.
* @attributes: pointer to the array of (localname/prefix/URI/value/end)
* attribute values.
*
* SAX2 callback when an element start has been detected by the parser.
* It provides the namespace informations for the element, as well as
* the new namespace declarations on the element.
*/
void
xmlSAX2StartElementNs(void *ctx,
const xmlChar *localname,
const xmlChar *prefix,
const xmlChar *URI,
int nb_namespaces,
const xmlChar **namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar **attributes)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlNodePtr ret;
xmlNodePtr parent;
xmlNsPtr last = NULL, ns;
const xmlChar *uri, *pref;
int i, j;
if (ctx == NULL) return;
parent = ctxt->node;
/*
* 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;
}
/*
* allocate the node
*/
if (ctxt->freeElems != NULL) {
ret = ctxt->freeElems;
ctxt->freeElems = ret->next;
ctxt->freeElemsNr--;
memset(ret, 0, sizeof(xmlNode));
ret->type = XML_ELEMENT_NODE;
if (ctxt->dictNames)
ret->name = localname;
else {
ret->name = xmlStrdup(localname);
if (ret->name == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
return;
}
}
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue(ret);
} else {
if (ctxt->dictNames)
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
(xmlChar *) localname, NULL);
else
ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
if (ret == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
return;
}
}
if (ctxt->linenumbers) {
if (ctxt->input != NULL) {
if (ctxt->input->line < 65535)
ret->line = (short) ctxt->input->line;
else
ret->line = 65535;
}
}
if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
}
/*
* Build the namespace list
*/
for (i = 0,j = 0;j < nb_namespaces;j++) {
pref = namespaces[i++];
uri = namespaces[i++];
ns = xmlNewNs(NULL, uri, pref);
if (ns != NULL) {
if (last == NULL) {
ret->nsDef = last = ns;
} else {
last->next = ns;
last = ns;
}
if ((URI != NULL) && (prefix == pref))
ret->ns = ns;
} else {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
return;
}
#ifdef LIBXML_VALID_ENABLED
if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset) {
ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
ret, prefix, ns, uri);
}
#endif /* LIBXML_VALID_ENABLED */
}
ctxt->nodemem = -1;
/*
* We are parsing a new node.
*/
nodePush(ctxt, ret);
/*
* Link the child element
*/
if (parent != NULL) {
if (parent->type == XML_ELEMENT_NODE) {
xmlAddChild(parent, ret);
} else {
xmlAddSibling(parent, ret);
}
}
/*
* Insert the defaulted attributes from the DTD only if requested:
*/
if ((nb_defaulted != 0) &&
((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
nb_attributes -= nb_defaulted;
/*
* Search the namespace if it wasn't already found
* Note that, if prefix is NULL, this searches for the default Ns
*/
if ((URI != NULL) && (ret->ns == NULL)) {
ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
if (ret->ns == NULL) {
ns = xmlNewNs(ret, NULL, prefix);
if (ns == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
return;
}
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"Namespace prefix %s was not found\n", prefix);
}
}
/*
* process all the other attributes
*/
if (nb_attributes > 0) {
for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
attributes[j+3], attributes[j+4]);
}
}
#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-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -