📄 parser.c
字号:
* @msg: the error message
* @str1: extra data
*
* Handle a validity error.
*/
static void
xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1)
{
xmlStructuredErrorFunc schannel = NULL;
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
return;
ctxt->errNo = error;
if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
schannel = ctxt->sax->serror;
__xmlRaiseError(schannel,
ctxt->vctxt.error, ctxt->vctxt.userData,
ctxt, NULL, XML_FROM_DTD, error,
XML_ERR_ERROR, NULL, 0, (const char *) str1,
NULL, NULL, 0, 0,
msg, (const char *) str1);
ctxt->valid = 0;
}
/**
* xmlFatalErrMsgInt:
* @ctxt: an XML parser context
* @error: the error number
* @msg: the error message
* @val: an integer value
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
static void
xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, int val)
{
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
return;
ctxt->errNo = error;
__xmlRaiseError(NULL, NULL, NULL,
ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0)
ctxt->disableSAX = 1;
}
/**
* xmlFatalErrMsgStrIntStr:
* @ctxt: an XML parser context
* @error: the error number
* @msg: the error message
* @str1: an string info
* @val: an integer value
* @str2: an string info
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
static void
xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar *str1, int val,
const xmlChar *str2)
{
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
return;
ctxt->errNo = error;
__xmlRaiseError(NULL, NULL, NULL,
ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
NULL, 0, (const char *) str1, (const char *) str2,
NULL, val, 0, msg, str1, val, str2);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0)
ctxt->disableSAX = 1;
}
/**
* xmlFatalErrMsgStr:
* @ctxt: an XML parser context
* @error: the error number
* @msg: the error message
* @val: a string value
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
static void
xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar * val)
{
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
return;
ctxt->errNo = error;
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
XML_FROM_PARSER, error, XML_ERR_FATAL,
NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
val);
ctxt->wellFormed = 0;
if (ctxt->recovery == 0)
ctxt->disableSAX = 1;
}
/**
* xmlErrMsgStr:
* @ctxt: an XML parser context
* @error: the error number
* @msg: the error message
* @val: a string value
*
* Handle a non fatal parser error
*/
static void
xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg, const xmlChar * val)
{
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
return;
ctxt->errNo = error;
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
XML_FROM_PARSER, error, XML_ERR_ERROR,
NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
val);
}
/**
* xmlNsErr:
* @ctxt: an XML parser context
* @error: the error number
* @msg: the message
* @info1: extra information string
* @info2: extra information string
*
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
*/
static void
xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
const char *msg,
const xmlChar * info1, const xmlChar * info2,
const xmlChar * info3)
{
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
(ctxt->instate == XML_PARSER_EOF))
return;
ctxt->errNo = error;
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
XML_ERR_ERROR, NULL, 0, (const char *) info1,
(const char *) info2, (const char *) info3, 0, 0, msg,
info1, info2, info3);
ctxt->nsWellFormed = 0;
}
/************************************************************************
* *
* SAX2 defaulted attributes handling *
* *
************************************************************************/
/**
* xmlDetectSAX2:
* @ctxt: an XML parser context
*
* Do the SAX2 detection and specific intialization
*/
static void
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
if (ctxt == NULL) return;
#ifdef LIBXML_SAX1_ENABLED
if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
((ctxt->sax->startElementNs != NULL) ||
(ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
#else
ctxt->sax2 = 1;
#endif /* LIBXML_SAX1_ENABLED */
ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
(ctxt->str_xml_ns == NULL)) {
xmlErrMemory(ctxt, NULL);
}
}
typedef struct _xmlDefAttrs xmlDefAttrs;
typedef xmlDefAttrs *xmlDefAttrsPtr;
struct _xmlDefAttrs {
int nbAttrs; /* number of defaulted attributes on that element */
int maxAttrs; /* the size of the array */
const xmlChar *values[4]; /* array of localname/prefix/values */
};
/**
* xmlAddDefAttrs:
* @ctxt: an XML parser context
* @fullname: the element fullname
* @fullattr: the attribute fullname
* @value: the attribute value
*
* Add a defaulted attribute for an element
*/
static void
xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
const xmlChar *fullname,
const xmlChar *fullattr,
const xmlChar *value) {
xmlDefAttrsPtr defaults;
int len;
const xmlChar *name;
const xmlChar *prefix;
if (ctxt->attsDefault == NULL) {
ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
if (ctxt->attsDefault == NULL)
goto mem_error;
}
/*
* split the element name into prefix:localname , the string found
* are within the DTD and then not associated to namespace names.
*/
name = xmlSplitQName3(fullname, &len);
if (name == NULL) {
name = xmlDictLookup(ctxt->dict, fullname, -1);
prefix = NULL;
} else {
name = xmlDictLookup(ctxt->dict, name, -1);
prefix = xmlDictLookup(ctxt->dict, fullname, len);
}
/*
* make sure there is some storage
*/
defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
if (defaults == NULL) {
defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
(4 * 4) * sizeof(const xmlChar *));
if (defaults == NULL)
goto mem_error;
defaults->nbAttrs = 0;
defaults->maxAttrs = 4;
xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL);
} else if (defaults->nbAttrs >= defaults->maxAttrs) {
xmlDefAttrsPtr temp;
temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
(2 * defaults->maxAttrs * 4) * sizeof(const xmlChar *));
if (temp == NULL)
goto mem_error;
defaults = temp;
defaults->maxAttrs *= 2;
xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix, defaults, NULL);
}
/*
* plit the element name into prefix:localname , the string found
* are within the DTD and hen not associated to namespace names.
*/
name = xmlSplitQName3(fullattr, &len);
if (name == NULL) {
name = xmlDictLookup(ctxt->dict, fullattr, -1);
prefix = NULL;
} else {
name = xmlDictLookup(ctxt->dict, name, -1);
prefix = xmlDictLookup(ctxt->dict, fullattr, len);
}
defaults->values[4 * defaults->nbAttrs] = name;
defaults->values[4 * defaults->nbAttrs + 1] = prefix;
/* intern the string and precompute the end */
len = xmlStrlen(value);
value = xmlDictLookup(ctxt->dict, value, len);
defaults->values[4 * defaults->nbAttrs + 2] = value;
defaults->values[4 * defaults->nbAttrs + 3] = value + len;
defaults->nbAttrs++;
return;
mem_error:
xmlErrMemory(ctxt, NULL);
return;
}
/**
* xmlAddSpecialAttr:
* @ctxt: an XML parser context
* @fullname: the element fullname
* @fullattr: the attribute fullname
* @type: the attribute type
*
* Register that this attribute is not CDATA
*/
static void
xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
const xmlChar *fullname,
const xmlChar *fullattr,
int type)
{
if (ctxt->attsSpecial == NULL) {
ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
if (ctxt->attsSpecial == NULL)
goto mem_error;
}
xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
(void *) (long) type);
return;
mem_error:
xmlErrMemory(ctxt, NULL);
return;
}
/**
* xmlCheckLanguageID:
* @lang: pointer to the string value
*
* Checks that the value conforms to the LanguageID production:
*
* NOTE: this is somewhat deprecated, those productions were removed from
* the XML Second edition.
*
* [33] LanguageID ::= Langcode ('-' Subcode)*
* [34] Langcode ::= ISO639Code | IanaCode | UserCode
* [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
* [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
* [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
* [38] Subcode ::= ([a-z] | [A-Z])+
*
* Returns 1 if correct 0 otherwise
**/
int
xmlCheckLanguageID(const xmlChar * lang)
{
const xmlChar *cur = lang;
if (cur == NULL)
return (0);
if (((cur[0] == 'i') && (cur[1] == '-')) ||
((cur[0] == 'I') && (cur[1] == '-'))) {
/*
* IANA code
*/
cur += 2;
while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */
((cur[0] >= 'a') && (cur[0] <= 'z')))
cur++;
} else if (((cur[0] == 'x') && (cur[1] == '-')) ||
((cur[0] == 'X') && (cur[1] == '-'))) {
/*
* User code
*/
cur += 2;
while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */
((cur[0] >= 'a') && (cur[0] <= 'z')))
cur++;
} else if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
((cur[0] >= 'a') && (cur[0] <= 'z'))) {
/*
* ISO639
*/
cur++;
if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
((cur[0] >= 'a') && (cur[0] <= 'z')))
cur++;
else
return (0);
} else
return (0);
while (cur[0] != 0) { /* non input consuming */
if (cur[0] != '-')
return (0);
cur++;
if (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
((cur[0] >= 'a') && (cur[0] <= 'z')))
cur++;
else
return (0);
while (((cur[0] >= 'A') && (cur[0] <= 'Z')) || /* non input consuming */
((cur[0] >= 'a') && (cur[0] <= 'z')))
cur++;
}
return (1);
}
/************************************************************************
* *
* Parser stacks related functions and macros *
* *
************************************************************************/
xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
const xmlChar ** str);
#ifdef SAX2
/**
* nsPush:
* @ctxt: an XML parser context
* @prefix: the namespace prefix or NULL
* @URL: the namespace name
*
* Pushes a new parser namespace on top of the ns stack
*
* Returns -1 in case of error, -2 if the namespace should be discarded
* and the index in the stack otherwise.
*/
static int
nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
{
if (ctxt->options & XML_PARSE_NSCLEAN) {
int i;
for (i = 0;i < ctxt->nsNr;i += 2) {
if (ctxt->nsTab[i] == prefix) {
/* in scope */
if (ctxt->nsTab[i + 1] == URL)
return(-2);
/* out of scope keep it */
break;
}
}
}
if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
ctxt->nsMax = 10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -