📄 sax2.c
字号:
/**
* xmlSAX2SetDocumentLocator:
* @ctx: the user data (XML parser context)
* @loc: A SAX Locator
*
* Receive the document locator at startup, actually xmlDefaultSAXLocator
* Everything is available on the context, so this is useless in our case.
*/
void
xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
{
/* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
#ifdef DEBUG_SAX
xmlGenericError(xmlGenericErrorContext,
"SAX.xmlSAX2SetDocumentLocator()\n");
#endif
}
/**
* xmlSAX2StartDocument:
* @ctx: the user data (XML parser context)
*
* called when the document start being processed.
*/
void
xmlSAX2StartDocument(void *ctx)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlDocPtr doc;
if (ctx == NULL) return;
#ifdef DEBUG_SAX
xmlGenericError(xmlGenericErrorContext,
"SAX.xmlSAX2StartDocument()\n");
#endif
if (ctxt->html) {
#ifdef LIBXML_HTML_ENABLED
if (ctxt->myDoc == NULL)
ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
if (ctxt->myDoc == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
return;
}
#else
xmlGenericError(xmlGenericErrorContext,
"libxml2 built without HTML support\n");
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
ctxt->instate = XML_PARSER_EOF;
ctxt->disableSAX = 1;
return;
#endif
} else {
doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
if (doc != NULL) {
if (ctxt->encoding != NULL)
doc->encoding = xmlStrdup(ctxt->encoding);
else
doc->encoding = NULL;
doc->standalone = ctxt->standalone;
} else {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
return;
}
if ((ctxt->dictNames) && (doc != NULL)) {
doc->dict = ctxt->dict;
xmlDictReference(doc->dict);
}
}
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
if (ctxt->myDoc->URL == NULL)
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
}
}
/**
* xmlSAX2EndDocument:
* @ctx: the user data (XML parser context)
*
* called when the document end has been detected.
*/
void
xmlSAX2EndDocument(void *ctx)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
#ifdef DEBUG_SAX
xmlGenericError(xmlGenericErrorContext,
"SAX.xmlSAX2EndDocument()\n");
#endif
if (ctx == NULL) return;
#ifdef LIBXML_VALID_ENABLED
if (ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset)
ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
#endif /* LIBXML_VALID_ENABLED */
/*
* Grab the encoding if it was added on-the-fly
*/
if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
(ctxt->myDoc->encoding == NULL)) {
ctxt->myDoc->encoding = ctxt->encoding;
ctxt->encoding = NULL;
}
if ((ctxt->inputTab != NULL) &&
(ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
(ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
(ctxt->myDoc->encoding == NULL)) {
ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
}
if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
ctxt->myDoc->charset = ctxt->charset;
}
}
#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
/**
* xmlSAX2AttributeInternal:
* @ctx: the user data (XML parser context)
* @fullname: The attribute name, including namespace prefix
* @value: The attribute value
* @prefix: the prefix on the element node
*
* 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
xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
{
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
xmlAttrPtr ret;
xmlChar *name;
xmlChar *ns;
xmlChar *nval;
xmlNsPtr namespace;
/*
* Split the full name into a namespace prefix and the tag name
*/
name = xmlSplitQName(ctxt, fullname, &ns);
if ((name != NULL) && (name[0] == 0)) {
if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
"invalid namespace declaration '%s'\n",
fullname, NULL);
} else {
xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
"Avoid attribute ending with ':' like '%s'\n",
fullname, NULL);
}
if (ns != NULL)
xmlFree(ns);
ns = NULL;
xmlFree(name);
name = xmlStrdup(fullname);
}
if (name == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
if (ns != NULL)
xmlFree(ns);
return;
}
#ifdef LIBXML_VALID_ENABLED
/*
* Do the last stage of the attribute normalization
* Needed for HTML too:
* http://www.w3.org/TR/html4/types.html#h-6.2
*/
ctxt->vctxt.valid = 1;
nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
ctxt->myDoc, ctxt->node,
fullname, value);
if (ctxt->vctxt.valid != 1) {
ctxt->valid = 0;
}
if (nval != NULL)
value = nval;
#else
nval = NULL;
#endif /* LIBXML_VALID_ENABLED */
/*
* Check whether it's a namespace definition
*/
if ((!ctxt->html) && (ns == NULL) &&
(name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
(name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
xmlNsPtr nsret;
xmlChar *val;
if (!ctxt->replaceEntities) {
ctxt->depth++;
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
0,0,0);
ctxt->depth--;
} else {
val = (xmlChar *) value;
}
if (val[0] != 0) {
xmlURIPtr uri;
uri = xmlParseURI((const char *)val);
if (uri == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"xmlns: %s not a valid URI\n", val);
} else {
if (uri->scheme == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
ctxt->sax->warning(ctxt->userData,
"xmlns: URI %s is not absolute\n", val);
}
xmlFreeURI(uri);
}
}
/* a default namespace definition */
nsret = xmlNewNs(ctxt->node, val, NULL);
#ifdef LIBXML_VALID_ENABLED
/*
* Validate also for namespace decls, they are attributes from
* an XML-1.0 perspective
*/
if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset)
ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
ctxt->node, prefix, nsret, val);
#endif /* LIBXML_VALID_ENABLED */
if (name != NULL)
xmlFree(name);
if (nval != NULL)
xmlFree(nval);
if (val != value)
xmlFree(val);
return;
}
if ((!ctxt->html) &&
(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
(ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
xmlNsPtr nsret;
xmlChar *val;
if (!ctxt->replaceEntities) {
ctxt->depth++;
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
0,0,0);
ctxt->depth--;
if (val == NULL) {
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
xmlFree(ns);
if (name != NULL)
xmlFree(name);
return;
}
} else {
val = (xmlChar *) value;
}
if (val[0] == 0) {
xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
"Empty namespace name for prefix %s\n", name, NULL);
}
if ((ctxt->pedantic != 0) && (val[0] != 0)) {
xmlURIPtr uri;
uri = xmlParseURI((const char *)val);
if (uri == NULL) {
xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
"xmlns:%s: %s not a valid URI\n", name, value);
} else {
if (uri->scheme == NULL) {
xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
"xmlns:%s: URI %s is not absolute\n", name, value);
}
xmlFreeURI(uri);
}
}
/* a standard namespace definition */
nsret = xmlNewNs(ctxt->node, val, name);
xmlFree(ns);
#ifdef LIBXML_VALID_ENABLED
/*
* Validate also for namespace decls, they are attributes from
* an XML-1.0 perspective
*/
if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset)
ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
ctxt->node, prefix, nsret, value);
#endif /* LIBXML_VALID_ENABLED */
if (name != NULL)
xmlFree(name);
if (nval != NULL)
xmlFree(nval);
if (val != value)
xmlFree(val);
return;
}
if (ns != NULL) {
xmlAttrPtr prop;
namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
if (namespace == NULL) {
xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
"Namespace prefix %s of attribute %s is not defined\n",
ns, name);
}
prop = ctxt->node->properties;
while (prop != NULL) {
if (prop->ns != NULL) {
if ((xmlStrEqual(name, prop->name)) &&
((namespace == prop->ns) ||
(xmlStrEqual(namespace->href, prop->ns->href)))) {
xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
"Attribute %s in %s redefined\n",
name, namespace->href);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
goto error;
}
}
prop = prop->next;
}
} else {
namespace = NULL;
}
/* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
if (ret != NULL) {
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
xmlNodePtr tmp;
ret->children = xmlStringGetNodeList(ctxt->myDoc, 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) {
ret->children = xmlNewDocText(ctxt->myDoc, value);
ret->last = ret->children;
if (ret->children != NULL)
ret->children->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) {
xmlChar *val;
ctxt->depth++;
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
0,0,0);
ctxt->depth--;
if (val == NULL)
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
ctxt->myDoc, ctxt->node, ret, value);
else {
xmlChar *nvalnorm;
/*
* Do the last stage of the attribute normalization
* It need to be done twice ... it's an extra burden related
* to the ability to keep xmlSAX2References in attributes
*/
nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
ctxt->node, fullname, val);
if (nvalnorm != NULL) {
xmlFree(val);
val = nvalnorm;
}
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
ctxt->myDoc, ctxt->node, ret, val);
xmlFree(val);
}
} else {
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
ctxt->node, ret, value);
}
} 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))
xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
/*
* Add the xml:id value
*
* Open issue: normalization of the value.
*/
if (xmlValidateNCName(value, 1) != 0) {
xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
"xml:id : attribute value %s is not an NCName\n",
(const char *) value, NULL);
}
xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
}
}
error:
if (nval != NULL)
xmlFree(nval);
if (ns != NULL)
xmlFree(ns);
}
/*
* xmlCheckDefaultedAttributes:
*
* Check defaulted attributes from the DTD
*/
static void
xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
const xmlChar *prefix, const xmlChar **atts) {
xmlElementPtr elemDecl;
const xmlChar *att;
int internal = 1;
int i;
elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
if (elemDecl == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -