📄 relaxng.c
字号:
*/
xmlRelaxNGIncludePop(ctxt);
#ifdef DEBUG_INCLUDE
xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
#endif
/*
* Check that the top element is a grammar
*/
root = xmlDocGetRootElement(doc);
if (root == NULL) {
xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
"xmlRelaxNG: included document is empty %s\n", URL,
NULL);
return (NULL);
}
if (!IS_RELAXNG(root, "grammar")) {
xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
"xmlRelaxNG: included document %s root is not a grammar\n",
URL, NULL);
return (NULL);
}
/*
* Elimination of redefined rules in the include.
*/
cur = node->children;
while (cur != NULL) {
if (IS_RELAXNG(cur, "start")) {
int found = 0;
found =
xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
if (!found) {
xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
"xmlRelaxNG: include %s has a start but not the included grammar\n",
URL, NULL);
}
} else if (IS_RELAXNG(cur, "define")) {
xmlChar *name;
name = xmlGetProp(cur, BAD_CAST "name");
if (name == NULL) {
xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
"xmlRelaxNG: include %s has define without name\n",
URL, NULL);
} else {
int found;
xmlRelaxNGNormExtSpace(name);
found = xmlRelaxNGRemoveRedefine(ctxt, URL,
root->children, name);
if (!found) {
xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
"xmlRelaxNG: include %s has a define %s but not the included grammar\n",
URL, name);
}
xmlFree(name);
}
}
cur = cur->next;
}
return (ret);
}
/**
* xmlRelaxNGValidErrorPush:
* @ctxt: the validation context
* @err: the error code
* @arg1: the first string argument
* @arg2: the second string argument
* @dup: arg need to be duplicated
*
* Pushes a new error on top of the error stack
*
* Returns 0 in case of error, the index in the stack otherwise
*/
static int
xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
xmlRelaxNGValidErr err, const xmlChar * arg1,
const xmlChar * arg2, int dup)
{
xmlRelaxNGValidErrorPtr cur;
#ifdef DEBUG_ERROR
xmlGenericError(xmlGenericErrorContext,
"Pushing error %d at %d on stack\n", err, ctxt->errNr);
#endif
if (ctxt->errTab == NULL) {
ctxt->errMax = 8;
ctxt->errNr = 0;
ctxt->errTab =
(xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
sizeof
(xmlRelaxNGValidError));
if (ctxt->errTab == NULL) {
xmlRngVErrMemory(ctxt, "pushing error\n");
return (0);
}
ctxt->err = NULL;
}
if (ctxt->errNr >= ctxt->errMax) {
ctxt->errMax *= 2;
ctxt->errTab =
(xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
ctxt->errMax *
sizeof
(xmlRelaxNGValidError));
if (ctxt->errTab == NULL) {
xmlRngVErrMemory(ctxt, "pushing error\n");
return (0);
}
ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
}
if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
(ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
return (ctxt->errNr);
cur = &ctxt->errTab[ctxt->errNr];
cur->err = err;
if (dup) {
cur->arg1 = xmlStrdup(arg1);
cur->arg2 = xmlStrdup(arg2);
cur->flags = ERROR_IS_DUP;
} else {
cur->arg1 = arg1;
cur->arg2 = arg2;
cur->flags = 0;
}
if (ctxt->state != NULL) {
cur->node = ctxt->state->node;
cur->seq = ctxt->state->seq;
} else {
cur->node = NULL;
cur->seq = NULL;
}
ctxt->err = cur;
return (ctxt->errNr++);
}
/**
* xmlRelaxNGValidErrorPop:
* @ctxt: the validation context
*
* Pops the top error from the error stack
*/
static void
xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
{
xmlRelaxNGValidErrorPtr cur;
if (ctxt->errNr <= 0) {
ctxt->err = NULL;
return;
}
ctxt->errNr--;
if (ctxt->errNr > 0)
ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
else
ctxt->err = NULL;
cur = &ctxt->errTab[ctxt->errNr];
if (cur->flags & ERROR_IS_DUP) {
if (cur->arg1 != NULL)
xmlFree((xmlChar *) cur->arg1);
cur->arg1 = NULL;
if (cur->arg2 != NULL)
xmlFree((xmlChar *) cur->arg2);
cur->arg2 = NULL;
cur->flags = 0;
}
}
/**
* xmlRelaxNGDocumentPush:
* @ctxt: the parser context
* @value: the element doc
*
* Pushes a new doc on top of the doc stack
*
* Returns 0 in case of error, the index in the stack otherwise
*/
static int
xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
xmlRelaxNGDocumentPtr value)
{
if (ctxt->docTab == NULL) {
ctxt->docMax = 4;
ctxt->docNr = 0;
ctxt->docTab =
(xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
sizeof(ctxt->docTab[0]));
if (ctxt->docTab == NULL) {
xmlRngPErrMemory(ctxt, "adding document\n");
return (0);
}
}
if (ctxt->docNr >= ctxt->docMax) {
ctxt->docMax *= 2;
ctxt->docTab =
(xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
ctxt->docMax *
sizeof(ctxt->docTab[0]));
if (ctxt->docTab == NULL) {
xmlRngPErrMemory(ctxt, "adding document\n");
return (0);
}
}
ctxt->docTab[ctxt->docNr] = value;
ctxt->doc = value;
return (ctxt->docNr++);
}
/**
* xmlRelaxNGDocumentPop:
* @ctxt: the parser context
*
* Pops the top doc from the doc stack
*
* Returns the doc just removed
*/
static xmlRelaxNGDocumentPtr
xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
{
xmlRelaxNGDocumentPtr ret;
if (ctxt->docNr <= 0)
return (0);
ctxt->docNr--;
if (ctxt->docNr > 0)
ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
else
ctxt->doc = NULL;
ret = ctxt->docTab[ctxt->docNr];
ctxt->docTab[ctxt->docNr] = 0;
return (ret);
}
/**
* xmlRelaxNGLoadExternalRef:
* @ctxt: the parser context
* @URL: the normalized URL
* @ns: the inherited ns if any
*
* First lookup if the document is already loaded into the parser context,
* check against recursion. If not found the resource is loaded and
* the content is preprocessed before being returned back to the caller.
*
* Returns the xmlRelaxNGDocumentPtr or NULL in case of error
*/
static xmlRelaxNGDocumentPtr
xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
const xmlChar * URL, const xmlChar * ns)
{
xmlRelaxNGDocumentPtr ret = NULL;
xmlDocPtr doc;
xmlNodePtr root;
int i;
/*
* check against recursion in the stack
*/
for (i = 0; i < ctxt->docNr; i++) {
if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
"Detected an externalRef recursion for %s\n", URL,
NULL);
return (NULL);
}
}
/*
* load the document
*/
doc = xmlReadFile((const char *) URL,NULL,0);
if (doc == NULL) {
xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
"xmlRelaxNG: could not load %s\n", URL, NULL);
return (NULL);
}
/*
* Allocate the document structures and register it first.
*/
ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
if (ret == NULL) {
xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
"xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
xmlFreeDoc(doc);
return (NULL);
}
memset(ret, 0, sizeof(xmlRelaxNGDocument));
ret->doc = doc;
ret->href = xmlStrdup(URL);
ret->next = ctxt->documents;
ctxt->documents = ret;
/*
* transmit the ns if needed
*/
if (ns != NULL) {
root = xmlDocGetRootElement(doc);
if (root != NULL) {
if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
xmlSetProp(root, BAD_CAST "ns", ns);
}
}
}
/*
* push it on the stack and register it in the hash table
*/
xmlRelaxNGDocumentPush(ctxt, ret);
/*
* Some preprocessing of the document content
*/
doc = xmlRelaxNGCleanupDoc(ctxt, doc);
if (doc == NULL) {
ctxt->doc = NULL;
return (NULL);
}
xmlRelaxNGDocumentPop(ctxt);
return (ret);
}
/************************************************************************
* *
* Error functions *
* *
************************************************************************/
#define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
#define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
#define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
#define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
#define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
static const char *
xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
{
if (def == NULL)
return ("none");
switch (def->type) {
case XML_RELAXNG_EMPTY:
return ("empty");
case XML_RELAXNG_NOT_ALLOWED:
return ("notAllowed");
case XML_RELAXNG_EXCEPT:
return ("except");
case XML_RELAXNG_TEXT:
return ("text");
case XML_RELAXNG_ELEMENT:
return ("element");
case XML_RELAXNG_DATATYPE:
return ("datatype");
case XML_RELAXNG_VALUE:
return ("value");
case XML_RELAXNG_LIST:
return ("list");
case XML_RELAXNG_ATTRIBUTE:
return ("attribute");
case XML_RELAXNG_DEF:
return ("def");
case XML_RELAXNG_REF:
return ("ref");
case XML_RELAXNG_EXTERNALREF:
return ("externalRef");
case XML_RELAXNG_PARENTREF:
return ("parentRef");
case XML_RELAXNG_OPTIONAL:
return ("optional");
case XML_RELAXNG_ZEROORMORE:
return ("zeroOrMore");
case XML_RELAXNG_ONEORMORE:
return ("oneOrMore");
case XML_RELAXNG_CHOICE:
return ("choice");
case XML_RELAXNG_GROUP:
return ("group");
case XML_RELAXNG_INTERLEAVE:
return ("interleave");
case XML_RELAXNG_START:
return ("start");
case XML_RELAXNG_NOOP:
return ("noop");
case XML_RELAXNG_PARAM:
return ("param");
}
return ("unknown");
}
/**
* xmlRelaxNGGetErrorString:
* @err: the error code
* @arg1: the first string argument
* @arg2: the second string argument
*
* computes a formatted error string for the given error code and args
*
* Returns the error string, it must be deallocated by the caller
*/
static xmlChar *
xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
const xmlChar * arg2)
{
char msg[1000];
if (arg1 == NULL)
arg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -