mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-08-01 10:06:59 +03:00
Cleanup and testing with the KDE help center files:
- valid.c: cleanup, more useful debugging - parserInternals.c: cleanup vctxt.nodeTab (de)allocation - xmlIO.c: entity loading is printed as an error when validating Daniel
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
Sat Apr 21 16:12:59 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
|
* valid.c: cleanup, more useful debugging
|
||||||
|
* parserInternals.c: cleanup vctxt.nodeTab (de)allocation
|
||||||
|
* xmlIO.c: entity loading is printed as an error when validating
|
||||||
|
|
||||||
Sat Apr 21 12:25:49 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
Sat Apr 21 12:25:49 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||||
|
|
||||||
* valid.c: fixed to validate within entities
|
* valid.c: fixed to validate within entities
|
||||||
|
@ -277,17 +277,7 @@ xmlSetFeature(xmlParserCtxtPtr ctxt, const char *name, void *value) {
|
|||||||
ctxt->vctxt.warning = xmlParserValidityWarning;
|
ctxt->vctxt.warning = xmlParserValidityWarning;
|
||||||
if (ctxt->vctxt.error == NULL)
|
if (ctxt->vctxt.error == NULL)
|
||||||
ctxt->vctxt.error = xmlParserValidityError;
|
ctxt->vctxt.error = xmlParserValidityError;
|
||||||
/* Allocate the Node stack */
|
ctxt->vctxt.nodeMax = 0;
|
||||||
ctxt->vctxt.nodeTab = (xmlNodePtr *)
|
|
||||||
xmlMalloc(4 * sizeof(xmlNodePtr));
|
|
||||||
if (ctxt->vctxt.nodeTab == NULL) {
|
|
||||||
ctxt->vctxt.nodeMax = 0;
|
|
||||||
ctxt->validate = 0;
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
ctxt->vctxt.nodeNr = 0;
|
|
||||||
ctxt->vctxt.nodeMax = 4;
|
|
||||||
ctxt->vctxt.node = NULL;
|
|
||||||
}
|
}
|
||||||
ctxt->validate = newvalidate;
|
ctxt->validate = newvalidate;
|
||||||
} else if (!strcmp(name, "keep blanks")) {
|
} else if (!strcmp(name, "keep blanks")) {
|
||||||
@ -2223,20 +2213,7 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
ctxt->vctxt.warning = NULL;
|
ctxt->vctxt.warning = NULL;
|
||||||
else
|
else
|
||||||
ctxt->vctxt.warning = xmlParserValidityWarning;
|
ctxt->vctxt.warning = xmlParserValidityWarning;
|
||||||
/* Allocate the Node stack */
|
ctxt->vctxt.nodeMax = 0;
|
||||||
ctxt->vctxt.nodeTab = (xmlNodePtr *) xmlMalloc(4 * sizeof(xmlNodePtr));
|
|
||||||
if (ctxt->vctxt.nodeTab == NULL) {
|
|
||||||
xmlGenericError(xmlGenericErrorContext,
|
|
||||||
"xmlInitParserCtxt: out of memory\n");
|
|
||||||
ctxt->vctxt.nodeMax = 0;
|
|
||||||
ctxt->validate = 0;
|
|
||||||
ctxt->vctxt.error = NULL;
|
|
||||||
ctxt->vctxt.warning = NULL;
|
|
||||||
} else {
|
|
||||||
ctxt->vctxt.nodeNr = 0;
|
|
||||||
ctxt->vctxt.nodeMax = 4;
|
|
||||||
ctxt->vctxt.node = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ctxt->vctxt.error = NULL;
|
ctxt->vctxt.error = NULL;
|
||||||
ctxt->vctxt.warning = NULL;
|
ctxt->vctxt.warning = NULL;
|
||||||
@ -2283,7 +2260,6 @@ xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
|
|||||||
if (ctxt->intSubName != NULL) xmlFree((char *) ctxt->intSubName);
|
if (ctxt->intSubName != NULL) xmlFree((char *) ctxt->intSubName);
|
||||||
if (ctxt->extSubURI != NULL) xmlFree((char *) ctxt->extSubURI);
|
if (ctxt->extSubURI != NULL) xmlFree((char *) ctxt->extSubURI);
|
||||||
if (ctxt->extSubSystem != NULL) xmlFree((char *) ctxt->extSubSystem);
|
if (ctxt->extSubSystem != NULL) xmlFree((char *) ctxt->extSubSystem);
|
||||||
if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
|
|
||||||
if ((ctxt->sax != NULL) && (ctxt->sax != &xmlDefaultSAXHandler))
|
if ((ctxt->sax != NULL) && (ctxt->sax != &xmlDefaultSAXHandler))
|
||||||
xmlFree(ctxt->sax);
|
xmlFree(ctxt->sax);
|
||||||
if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
|
if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
|
||||||
|
455
valid.c
455
valid.c
@ -28,14 +28,22 @@
|
|||||||
#include <libxml/xmlerror.h>
|
#include <libxml/xmlerror.h>
|
||||||
#include <libxml/list.h>
|
#include <libxml/list.h>
|
||||||
|
|
||||||
#define ALLOW_UNDETERMINISTIC_MODELS
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic function for accessing stacks in the Validity Context
|
* Generic function for accessing stacks in the Validity Context
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PUSH_AND_POP(scope, type, name) \
|
#define PUSH_AND_POP(scope, type, name) \
|
||||||
scope int name##VPush(xmlValidCtxtPtr ctxt, type value) { \
|
scope int name##VPush(xmlValidCtxtPtr ctxt, type value) { \
|
||||||
|
if (ctxt->name##Max <= 0) { \
|
||||||
|
ctxt->name##Max = 4; \
|
||||||
|
ctxt->name##Tab = (type *) xmlMalloc( \
|
||||||
|
ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \
|
||||||
|
if (ctxt->name##Tab == NULL) { \
|
||||||
|
xmlGenericError(xmlGenericErrorContext, \
|
||||||
|
"malloc failed !\n"); \
|
||||||
|
return(0); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
if (ctxt->name##Nr >= ctxt->name##Max) { \
|
if (ctxt->name##Nr >= ctxt->name##Max) { \
|
||||||
ctxt->name##Max *= 2; \
|
ctxt->name##Max *= 2; \
|
||||||
ctxt->name##Tab = (type *) xmlRealloc(ctxt->name##Tab, \
|
ctxt->name##Tab = (type *) xmlRealloc(ctxt->name##Tab, \
|
||||||
@ -63,8 +71,6 @@ scope type name##VPop(xmlValidCtxtPtr ctxt) { \
|
|||||||
return(ret); \
|
return(ret); \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
#ifdef ALLOW_UNDETERMINISTIC_MODELS
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I will use a home made algorithm less complex and easier to
|
* I will use a home made algorithm less complex and easier to
|
||||||
* debug/maintin than a generic NFA -> DFA state based algo. The
|
* debug/maintin than a generic NFA -> DFA state based algo. The
|
||||||
@ -133,9 +139,6 @@ vstateVPop(xmlValidCtxtPtr ctxt) {
|
|||||||
return(ctxt->vstateNr);
|
return(ctxt->vstateNr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* ALLOW_UNDETERMINISTIC_MODELS */
|
|
||||||
|
|
||||||
PUSH_AND_POP(static, xmlNodePtr, node)
|
PUSH_AND_POP(static, xmlNodePtr, node)
|
||||||
|
|
||||||
/* #define DEBUG_VALID_ALGO */
|
/* #define DEBUG_VALID_ALGO */
|
||||||
@ -3228,270 +3231,6 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
|||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ALLOW_UNDETERMINISTIC_MODELS
|
|
||||||
|
|
||||||
/* Find the next XML_ELEMENT_NODE, subject to the content constraints.
|
|
||||||
* Return -1 if we found something unexpected, or 1 otherwise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
xmlValidateFindNextElement(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
|
|
||||||
xmlElementContentPtr cont)
|
|
||||||
{
|
|
||||||
DEBUG_VALID_MSG("skipping to next element");
|
|
||||||
while (*child && (*child)->type != XML_ELEMENT_NODE) {
|
|
||||||
switch ((*child)->type) {
|
|
||||||
/*
|
|
||||||
* If there is an entity declared and it's not empty
|
|
||||||
* Push the current node on the stack and process with the
|
|
||||||
* entity content.
|
|
||||||
*/
|
|
||||||
case XML_ENTITY_REF_NODE:
|
|
||||||
if (((*child)->children != NULL) &&
|
|
||||||
((*child)->children->children != NULL)) {
|
|
||||||
nodeVPush(ctxt, *child);
|
|
||||||
*child = (*child)->children->children;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* These things are ignored (skipped) during validation. */
|
|
||||||
case XML_PI_NODE:
|
|
||||||
case XML_COMMENT_NODE:
|
|
||||||
case XML_XINCLUDE_START:
|
|
||||||
case XML_XINCLUDE_END:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XML_TEXT_NODE:
|
|
||||||
if (xmlIsBlankNode(*child)
|
|
||||||
&& (cont->type == XML_ELEMENT_CONTENT_ELEMENT
|
|
||||||
|| cont->type == XML_ELEMENT_CONTENT_SEQ
|
|
||||||
|| cont->type == XML_ELEMENT_CONTENT_OR))
|
|
||||||
break;
|
|
||||||
DEBUG_VALID_MSG("failed non-blank");
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
default:
|
|
||||||
DEBUG_VALID_MSG("failed unknown type");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
*child = (*child)->next;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_VALID_ALGO
|
|
||||||
if (*child != NULL) {
|
|
||||||
DEBUG_VALID_MSG((*child)->name);
|
|
||||||
}
|
|
||||||
DEBUG_VALID_MSG("found ...");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int xmlValidateElementTypeElement(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
|
|
||||||
xmlElementContentPtr cont);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xmlValidateElementTypeExpr:
|
|
||||||
* @ctxt: the validation context
|
|
||||||
* @child: pointer to the child list
|
|
||||||
* @cont: pointer to the content declaration
|
|
||||||
*
|
|
||||||
* Try to validate the content of an element of type element
|
|
||||||
* but don't handle the occurence factor
|
|
||||||
*
|
|
||||||
* returns 1 if valid or 0 and -1 if PCDATA stuff is found,
|
|
||||||
* also update child value in-situ.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
xmlValidateElementTypeExpr(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
|
|
||||||
xmlElementContentPtr cont) {
|
|
||||||
xmlNodePtr cur;
|
|
||||||
int ret = 1;
|
|
||||||
|
|
||||||
if (cont == NULL) return(-1);
|
|
||||||
DEBUG_VALID_STATE(*child, cont)
|
|
||||||
ret = xmlValidateFindNextElement(ctxt, child, cont);
|
|
||||||
if (ret < 0)
|
|
||||||
return(-1);
|
|
||||||
DEBUG_VALID_STATE(*child, cont)
|
|
||||||
switch (cont->type) {
|
|
||||||
case XML_ELEMENT_CONTENT_PCDATA:
|
|
||||||
if (*child == NULL) return(0);
|
|
||||||
if ((*child)->type == XML_TEXT_NODE) {
|
|
||||||
DEBUG_VALID_MSG("pcdata found");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
case XML_ELEMENT_CONTENT_ELEMENT:
|
|
||||||
if (*child == NULL) return(0);
|
|
||||||
ret = (xmlStrEqual((*child)->name, cont->name));
|
|
||||||
if (ret == 1) {
|
|
||||||
DEBUG_VALID_MSG("element found, skip to next");
|
|
||||||
while ((*child)->next == NULL) {
|
|
||||||
if (((*child)->parent != NULL) &&
|
|
||||||
((*child)->parent->type == XML_ENTITY_DECL)) {
|
|
||||||
*child = nodeVPop(ctxt);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*child = (*child)->next;
|
|
||||||
}
|
|
||||||
return(ret);
|
|
||||||
case XML_ELEMENT_CONTENT_OR:
|
|
||||||
cur = *child;
|
|
||||||
ret = xmlValidateElementTypeElement(ctxt, child, cont->c1);
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
if (ret == 1) {
|
|
||||||
DEBUG_VALID_MSG("or succeeded first branch");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
/* rollback and retry the other path */
|
|
||||||
*child = cur;
|
|
||||||
ret = xmlValidateElementTypeElement(ctxt, child, cont->c2);
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
if (ret == 0) {
|
|
||||||
DEBUG_VALID_MSG("or failed both branches");
|
|
||||||
*child = cur;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
DEBUG_VALID_MSG("or succeeded second branch");
|
|
||||||
return(1);
|
|
||||||
case XML_ELEMENT_CONTENT_SEQ:
|
|
||||||
cur = *child;
|
|
||||||
ret = xmlValidateElementTypeElement(ctxt, child, cont->c1);
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
if (ret == 0) {
|
|
||||||
DEBUG_VALID_MSG("sequence failed");
|
|
||||||
*child = cur;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
ret = xmlValidateElementTypeElement(ctxt, child, cont->c2);
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
if (ret == 0) {
|
|
||||||
*child = cur;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
DEBUG_VALID_MSG("sequence succeeded");
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* xmlValidateElementTypeElement:
|
|
||||||
* @ctxt: the validation context
|
|
||||||
* @child: pointer to the child list
|
|
||||||
* @cont: pointer to the content declaration
|
|
||||||
*
|
|
||||||
* Try to validate the content of an element of type element
|
|
||||||
* yeah, Yet Another Regexp Implementation, and recursive
|
|
||||||
*
|
|
||||||
* returns 1 if valid or 0 and -1 if PCDATA stuff is found,
|
|
||||||
* also update child and content values in-situ.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
xmlValidateElementTypeElement(xmlValidCtxtPtr ctxt, xmlNodePtr *child,
|
|
||||||
xmlElementContentPtr cont) {
|
|
||||||
xmlNodePtr cur;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (cont == NULL) return(-1);
|
|
||||||
|
|
||||||
DEBUG_VALID_STATE(*child, cont)
|
|
||||||
ret = xmlValidateFindNextElement(ctxt, child, cont);
|
|
||||||
if (ret < 0)
|
|
||||||
return(-1);
|
|
||||||
DEBUG_VALID_STATE(*child, cont)
|
|
||||||
cur = *child;
|
|
||||||
ret = xmlValidateElementTypeExpr(ctxt, child, cont);
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
switch (cont->ocur) {
|
|
||||||
case XML_ELEMENT_CONTENT_ONCE:
|
|
||||||
if (ret == 1) {
|
|
||||||
DEBUG_VALID_MSG("once found, skip to next");
|
|
||||||
/* skip ignorable elems */
|
|
||||||
while ((*child != NULL) &&
|
|
||||||
((*child)->type == XML_PI_NODE
|
|
||||||
|| (*child)->type == XML_COMMENT_NODE
|
|
||||||
|| (*child)->type == XML_XINCLUDE_START
|
|
||||||
|| (*child)->type == XML_XINCLUDE_END)) {
|
|
||||||
while ((*child)->next == NULL) {
|
|
||||||
if (((*child)->parent != NULL) &&
|
|
||||||
((*child)->parent->type == XML_ENTITY_REF_NODE)) {
|
|
||||||
*child = (*child)->parent;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*child = (*child)->next;
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
*child = cur;
|
|
||||||
return(0);
|
|
||||||
case XML_ELEMENT_CONTENT_OPT:
|
|
||||||
if (ret == 0) {
|
|
||||||
*child = cur;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
if (ret == 1) {
|
|
||||||
DEBUG_VALID_MSG("optional found, skip to next");
|
|
||||||
/* skip ignorable elems */
|
|
||||||
while ((*child != NULL) &&
|
|
||||||
((*child)->type == XML_PI_NODE
|
|
||||||
|| (*child)->type == XML_COMMENT_NODE
|
|
||||||
|| (*child)->type == XML_XINCLUDE_START
|
|
||||||
|| (*child)->type == XML_XINCLUDE_END)) {
|
|
||||||
while ((*child)->next == NULL) {
|
|
||||||
if (((*child)->parent != NULL) &&
|
|
||||||
((*child)->parent->type == XML_ENTITY_REF_NODE)) {
|
|
||||||
*child = (*child)->parent;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*child = (*child)->next;
|
|
||||||
}
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case XML_ELEMENT_CONTENT_MULT:
|
|
||||||
if (ret == 0) {
|
|
||||||
*child = cur;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* no break on purpose */
|
|
||||||
case XML_ELEMENT_CONTENT_PLUS:
|
|
||||||
if (ret == 0) {
|
|
||||||
*child = cur;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
DEBUG_VALID_MSG("mult/plus found");
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
cur = *child;
|
|
||||||
do {
|
|
||||||
if (*child == NULL)
|
|
||||||
break; /* while */
|
|
||||||
if ((*child)->type == XML_TEXT_NODE
|
|
||||||
&& xmlIsBlankNode(*child)) {
|
|
||||||
*child = (*child)->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret = xmlValidateElementTypeExpr(ctxt, child, cont);
|
|
||||||
if (ret == 1)
|
|
||||||
cur = *child;
|
|
||||||
} while (ret == 1);
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
*child = cur;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ret == -1) return(-1);
|
|
||||||
|
|
||||||
return(xmlValidateFindNextElement(ctxt, child, cont));
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* ALLOW_UNDETERMINISTIC_MODELS */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlValidateSkipIgnorable:
|
* xmlValidateSkipIgnorable:
|
||||||
* @ctxt: the validation context
|
* @ctxt: the validation context
|
||||||
@ -3832,11 +3571,74 @@ analyze:
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSprintfElements:
|
||||||
|
* @buf: an output buffer
|
||||||
|
* @content: An element
|
||||||
|
* @glob: 1 if one must print the englobing parenthesis, 0 otherwise
|
||||||
|
*
|
||||||
|
* This will dump the list of elements to the buffer
|
||||||
|
* Intended just for the debug routine
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xmlSprintfElements(char *buf, xmlNodePtr node, int glob) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
|
||||||
|
if (node == NULL) return;
|
||||||
|
if (glob) strcat(buf, "(");
|
||||||
|
cur = node;
|
||||||
|
while (cur != NULL) {
|
||||||
|
switch (cur->type) {
|
||||||
|
case XML_ELEMENT_NODE:
|
||||||
|
strcat(buf, (char *) cur->name);
|
||||||
|
if (cur->next != NULL)
|
||||||
|
strcat(buf, " ");
|
||||||
|
break;
|
||||||
|
case XML_TEXT_NODE:
|
||||||
|
if (xmlIsBlankNode(cur))
|
||||||
|
break;
|
||||||
|
case XML_CDATA_SECTION_NODE:
|
||||||
|
case XML_ENTITY_REF_NODE:
|
||||||
|
strcat(buf, "CDATA");
|
||||||
|
if (cur->next != NULL)
|
||||||
|
strcat(buf, " ");
|
||||||
|
break;
|
||||||
|
case XML_ATTRIBUTE_NODE:
|
||||||
|
case XML_DOCUMENT_NODE:
|
||||||
|
#ifdef LIBXML_SGML_ENABLED
|
||||||
|
case XML_SGML_DOCUMENT_NODE:
|
||||||
|
#endif
|
||||||
|
case XML_HTML_DOCUMENT_NODE:
|
||||||
|
case XML_DOCUMENT_TYPE_NODE:
|
||||||
|
case XML_DOCUMENT_FRAG_NODE:
|
||||||
|
case XML_NOTATION_NODE:
|
||||||
|
case XML_NAMESPACE_DECL:
|
||||||
|
strcat(buf, "???");
|
||||||
|
if (cur->next != NULL)
|
||||||
|
strcat(buf, " ");
|
||||||
|
break;
|
||||||
|
case XML_ENTITY_NODE:
|
||||||
|
case XML_PI_NODE:
|
||||||
|
case XML_DTD_NODE:
|
||||||
|
case XML_COMMENT_NODE:
|
||||||
|
case XML_ELEMENT_DECL:
|
||||||
|
case XML_ATTRIBUTE_DECL:
|
||||||
|
case XML_ENTITY_DECL:
|
||||||
|
case XML_XINCLUDE_START:
|
||||||
|
case XML_XINCLUDE_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
if (glob) strcat(buf, ")");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlValidateElementContent:
|
* xmlValidateElementContent:
|
||||||
* @ctxt: the validation context
|
* @ctxt: the validation context
|
||||||
* @child: the child list
|
* @child: the child list
|
||||||
* @cont: pointer to the content declaration
|
* @cont: pointer to the content declaration
|
||||||
|
* @warn: emit the error message
|
||||||
*
|
*
|
||||||
* Try to validate the content model of an element
|
* Try to validate the content model of an element
|
||||||
*
|
*
|
||||||
@ -3845,9 +3647,9 @@ analyze:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
||||||
xmlElementContentPtr cont) {
|
xmlElementContentPtr cont, int warn) {
|
||||||
int ret;
|
int ret;
|
||||||
xmlNodePtr repl = NULL, last = NULL, tmp;
|
xmlNodePtr repl = NULL, last = NULL, cur, tmp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate the stack
|
* Allocate the stack
|
||||||
@ -3878,21 +3680,22 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
|||||||
* sufficient to run the validation process on it
|
* sufficient to run the validation process on it
|
||||||
*/
|
*/
|
||||||
DEBUG_VALID_MSG("Found an entity reference, linearizing");
|
DEBUG_VALID_MSG("Found an entity reference, linearizing");
|
||||||
while (child != NULL) {
|
cur = child;
|
||||||
switch (child->type) {
|
while (cur != NULL) {
|
||||||
|
switch (cur->type) {
|
||||||
case XML_ENTITY_REF_NODE:
|
case XML_ENTITY_REF_NODE:
|
||||||
/*
|
/*
|
||||||
* Push the current node to be able to roll back
|
* Push the current node to be able to roll back
|
||||||
* and process within the entity
|
* and process within the entity
|
||||||
*/
|
*/
|
||||||
if ((child->children != NULL) &&
|
if ((cur->children != NULL) &&
|
||||||
(child->children->children != NULL)) {
|
(cur->children->children != NULL)) {
|
||||||
nodeVPush(ctxt, child);
|
nodeVPush(ctxt, cur);
|
||||||
child = child->children->children;
|
cur = cur->children->children;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case XML_TEXT_NODE:
|
case XML_TEXT_NODE:
|
||||||
if (xmlIsBlankNode(child))
|
if (xmlIsBlankNode(cur))
|
||||||
break;
|
break;
|
||||||
case XML_ELEMENT_NODE:
|
case XML_ELEMENT_NODE:
|
||||||
/*
|
/*
|
||||||
@ -3907,9 +3710,9 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
tmp->type = child->type;
|
tmp->type = cur->type;
|
||||||
tmp->name = child->name;
|
tmp->name = cur->name;
|
||||||
tmp->ns = child->ns;
|
tmp->ns = cur->ns;
|
||||||
tmp->next = NULL;
|
tmp->next = NULL;
|
||||||
if (repl == NULL)
|
if (repl == NULL)
|
||||||
repl = last = tmp;
|
repl = last = tmp;
|
||||||
@ -3924,12 +3727,12 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
|||||||
/*
|
/*
|
||||||
* Switch to next element
|
* Switch to next element
|
||||||
*/
|
*/
|
||||||
child = child->next;
|
cur = cur->next;
|
||||||
while (child == NULL) {
|
while (cur == NULL) {
|
||||||
child = nodeVPop(ctxt);
|
cur = nodeVPop(ctxt);
|
||||||
if (child == NULL)
|
if (cur == NULL)
|
||||||
break;
|
break;
|
||||||
child = child->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3945,6 +3748,29 @@ xmlValidateElementContent(xmlValidCtxtPtr ctxt, xmlNodePtr child,
|
|||||||
STATE = 0;
|
STATE = 0;
|
||||||
ret = xmlValidateElementType(ctxt);
|
ret = xmlValidateElementType(ctxt);
|
||||||
}
|
}
|
||||||
|
if ((warn) && (ret != 1)) {
|
||||||
|
char expr[5000];
|
||||||
|
char list[5000];
|
||||||
|
|
||||||
|
expr[0] = 0;
|
||||||
|
xmlSprintfElementContent(expr, cont, 1);
|
||||||
|
list[0] = 0;
|
||||||
|
if (repl != NULL)
|
||||||
|
xmlSprintfElements(list, repl, 1);
|
||||||
|
else
|
||||||
|
xmlSprintfElements(list, child, 1);
|
||||||
|
|
||||||
|
if ((child->parent != NULL) && (child->parent->name != NULL)) {
|
||||||
|
VERROR(ctxt->userData,
|
||||||
|
"Element %s content doesn't follow the Dtd\nExpecting %s, got %s\n",
|
||||||
|
child->parent->name, expr, list);
|
||||||
|
} else {
|
||||||
|
VERROR(ctxt->userData,
|
||||||
|
"Element content doesn't follow the Dtd\nExpecting %s, got %s\n",
|
||||||
|
expr, list);
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -3957,11 +3783,18 @@ done:
|
|||||||
repl = tmp;
|
repl = tmp;
|
||||||
}
|
}
|
||||||
ctxt->vstateMax = 0;
|
ctxt->vstateMax = 0;
|
||||||
xmlFree(ctxt->vstateTab);
|
if (ctxt->vstateTab != NULL) {
|
||||||
|
xmlFree(ctxt->vstateTab);
|
||||||
|
ctxt->vstateTab = NULL;
|
||||||
|
}
|
||||||
|
ctxt->nodeMax = 0;
|
||||||
|
if (ctxt->nodeTab != NULL) {
|
||||||
|
xmlFree(ctxt->nodeTab);
|
||||||
|
ctxt->nodeTab = NULL;
|
||||||
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* ALLOW_UNDETERMINISTIC_MODELS */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlSprintfElementChilds:
|
* xmlSprintfElementChilds:
|
||||||
@ -4229,45 +4062,8 @@ child_ok:
|
|||||||
case XML_ELEMENT_TYPE_ELEMENT:
|
case XML_ELEMENT_TYPE_ELEMENT:
|
||||||
child = elem->children;
|
child = elem->children;
|
||||||
cont = elemDecl->content;
|
cont = elemDecl->content;
|
||||||
#ifdef ALLOW_UNDETERMINISTIC_MODELS
|
ret = xmlValidateElementContent(ctxt, child, cont, 1);
|
||||||
ret = xmlValidateElementContent(ctxt, child, cont);
|
|
||||||
if (ret != 1) {
|
|
||||||
char expr[1000];
|
|
||||||
char list[2000];
|
|
||||||
|
|
||||||
expr[0] = 0;
|
|
||||||
xmlSprintfElementContent(expr, cont, 1);
|
|
||||||
list[0] = 0;
|
|
||||||
xmlSprintfElementChilds(list, elem, 1);
|
|
||||||
|
|
||||||
VERROR(ctxt->userData,
|
|
||||||
"Element %s content doesn't follow the Dtd\nExpecting %s, got %s\n",
|
|
||||||
elem->name, expr, list);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ret = xmlValidateElementTypeElement(ctxt, &child, cont);
|
|
||||||
while ((child != NULL) && (child->type == XML_TEXT_NODE) &&
|
|
||||||
(xmlIsBlankNode(child))) {
|
|
||||||
child = child->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((ret == 0) || (child != NULL)) {
|
|
||||||
char expr[1000];
|
|
||||||
char list[2000];
|
|
||||||
|
|
||||||
expr[0] = 0;
|
|
||||||
xmlSprintfElementContent(expr, cont, 1);
|
|
||||||
list[0] = 0;
|
|
||||||
xmlSprintfElementChilds(list, elem, 1);
|
|
||||||
|
|
||||||
VERROR(ctxt->userData,
|
|
||||||
"Element %s content doesn't follow the Dtd\nExpecting %s, got %s\n",
|
|
||||||
elem->name, expr, list);
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [ VC: Required Attribute ] */
|
/* [ VC: Required Attribute ] */
|
||||||
@ -4293,7 +4089,8 @@ child_ok:
|
|||||||
if (nameSpace == NULL) {
|
if (nameSpace == NULL) {
|
||||||
if (qualified < 0)
|
if (qualified < 0)
|
||||||
qualified = 0;
|
qualified = 0;
|
||||||
} else if (!xmlStrEqual(nameSpace->prefix, attr->prefix)) {
|
} else if (!xmlStrEqual(nameSpace->prefix,
|
||||||
|
attr->prefix)) {
|
||||||
if (qualified < 1)
|
if (qualified < 1)
|
||||||
qualified = 1;
|
qualified = 1;
|
||||||
} else
|
} else
|
||||||
|
12
xmlIO.c
12
xmlIO.c
@ -1598,14 +1598,22 @@ xmlDefaultExternalEntityLoader(const char *URL, const char *ID,
|
|||||||
"xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
|
"xmlDefaultExternalEntityLoader(%s, xxx)\n", URL);
|
||||||
#endif
|
#endif
|
||||||
if (URL == NULL) {
|
if (URL == NULL) {
|
||||||
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
|
if ((ctxt->validate) && (ctxt->sax != NULL) &&
|
||||||
|
(ctxt->sax->error != NULL))
|
||||||
|
ctxt->sax->error(ctxt,
|
||||||
|
"failed to load external entity \"%s\"\n", ID);
|
||||||
|
else if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
|
||||||
ctxt->sax->warning(ctxt,
|
ctxt->sax->warning(ctxt,
|
||||||
"failed to load external entity \"%s\"\n", ID);
|
"failed to load external entity \"%s\"\n", ID);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
ret = xmlNewInputFromFile(ctxt, URL);
|
ret = xmlNewInputFromFile(ctxt, URL);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
|
if ((ctxt->validate) && (ctxt->sax != NULL) &&
|
||||||
|
(ctxt->sax->error != NULL))
|
||||||
|
ctxt->sax->error(ctxt,
|
||||||
|
"failed to load external entity \"%s\"\n", URL);
|
||||||
|
else if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
|
||||||
ctxt->sax->warning(ctxt,
|
ctxt->sax->warning(ctxt,
|
||||||
"failed to load external entity \"%s\"\n", URL);
|
"failed to load external entity \"%s\"\n", URL);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user