mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-29 11:41:22 +03:00
implemented streaming of RelaxNG (when possible) on top of the xmlReader
* relaxng.c xmlreader.c xmllint.c include/libxml/relaxng.h include/libxml/xmlreader.h: implemented streaming of RelaxNG (when possible) on top of the xmlReader interface, provided it as xmllint --stream --relaxng .rng .xml This seems to mostly work. * Makefile.am: updated to test RelaxNG streaming Daniel
This commit is contained in:
@ -1,3 +1,12 @@
|
|||||||
|
Wed Apr 16 01:28:15 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
|
* relaxng.c xmlreader.c xmllint.c include/libxml/relaxng.h
|
||||||
|
include/libxml/xmlreader.h: implemented streaming of
|
||||||
|
RelaxNG (when possible) on top of the xmlReader interface,
|
||||||
|
provided it as xmllint --stream --relaxng .rng .xml
|
||||||
|
This seems to mostly work.
|
||||||
|
* Makefile.am: updated to test RelaxNG streaming
|
||||||
|
|
||||||
Mon Apr 14 18:08:33 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
Mon Apr 14 18:08:33 CEST 2003 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
* relaxng.c include/libxml/relaxng.h: integrated the regexp
|
* relaxng.c include/libxml/relaxng.h: integrated the regexp
|
||||||
|
27
Makefile.am
27
Makefile.am
@ -733,6 +733,33 @@ Relaxtests: xmllint$(EXEEXT)
|
|||||||
rm res.$$name err.$$name ; \
|
rm res.$$name err.$$name ; \
|
||||||
fi ; fi ; \
|
fi ; fi ; \
|
||||||
done; done)
|
done; done)
|
||||||
|
@echo "##"
|
||||||
|
@echo "## Relax-NG streaming regression tests"
|
||||||
|
@echo "##"
|
||||||
|
-@(for i in $(srcdir)/test/relaxng/*.rng ; do \
|
||||||
|
name=`basename $$i | sed 's+\.rng++'`; \
|
||||||
|
for j in $(srcdir)/test/relaxng/"$$name"_*.xml ; do \
|
||||||
|
if [ -f $$j ] ; then \
|
||||||
|
xno=`basename $$j | sed 's+.*_\(.*\).xml+\1+'`; \
|
||||||
|
if [ ! -f $(srcdir)/result/relaxng/"$$name"_"$$xno" ]; \
|
||||||
|
then \
|
||||||
|
echo New test file "$$name"_"$$xno" ; \
|
||||||
|
$(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \
|
||||||
|
> $(srcdir)/result/relaxng/"$$name"_"$$xno" \
|
||||||
|
2> $(srcdir)/result/relaxng/"$$name"_"$$xno".err; \
|
||||||
|
else \
|
||||||
|
echo Testing "$$name"_"$$xno" ; \
|
||||||
|
$(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --stream --relaxng $$i $$j \
|
||||||
|
> res.$$name 2> err.$$name;\
|
||||||
|
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
|
||||||
|
diff $(srcdir)/result/relaxng/"$$name"_"$$xno" \
|
||||||
|
res.$$name;\
|
||||||
|
diff $(srcdir)/result/relaxng/"$$name"_"$$xno".err \
|
||||||
|
err.$$name | grep -v "error detected at";\
|
||||||
|
grep Unimplemented err.$$name; \
|
||||||
|
rm res.$$name err.$$name ; \
|
||||||
|
fi ; fi ; \
|
||||||
|
done; done)
|
||||||
|
|
||||||
dist-hook: libxml2.spec
|
dist-hook: libxml2.spec
|
||||||
-cp libxml2.spec $(distdir)
|
-cp libxml2.spec $(distdir)
|
||||||
|
@ -104,4 +104,19 @@ void xmlRelaxNGFreeValidCtxt (xmlRelaxNGValidCtxtPtr ctxt);
|
|||||||
int xmlRelaxNGValidateDoc (xmlRelaxNGValidCtxtPtr ctxt,
|
int xmlRelaxNGValidateDoc (xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
xmlDocPtr doc);
|
xmlDocPtr doc);
|
||||||
void xmlRelaxNGCleanupTypes (void);
|
void xmlRelaxNGCleanupTypes (void);
|
||||||
|
/*
|
||||||
|
* Interfaces for progressive validation when possible
|
||||||
|
*/
|
||||||
|
int xmlRelaxNGValidatePushElement (xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
xmlNodePtr elem);
|
||||||
|
int xmlRelaxNGValidatePushCData (xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
const xmlChar *data,
|
||||||
|
int len);
|
||||||
|
int xmlRelaxNGValidatePopElement (xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
xmlNodePtr elem);
|
||||||
|
int xmlRelaxNGValidateFullElement (xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
xmlDocPtr doc,
|
||||||
|
xmlNodePtr elem);
|
||||||
#endif /* __XML_RELAX_NG__ */
|
#endif /* __XML_RELAX_NG__ */
|
||||||
|
@ -109,6 +109,10 @@ xmlDocPtr xmlTextReaderCurrentDoc (xmlTextReaderPtr reader);
|
|||||||
xmlNodePtr xmlTextReaderExpand (xmlTextReaderPtr reader);
|
xmlNodePtr xmlTextReaderExpand (xmlTextReaderPtr reader);
|
||||||
int xmlTextReaderNext (xmlTextReaderPtr reader);
|
int xmlTextReaderNext (xmlTextReaderPtr reader);
|
||||||
int xmlTextReaderIsValid (xmlTextReaderPtr reader);
|
int xmlTextReaderIsValid (xmlTextReaderPtr reader);
|
||||||
|
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||||
|
int xmlTextReaderRelaxNGValidate (xmlTextReaderPtr reader,
|
||||||
|
const char *rng);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error handling extensions
|
* Error handling extensions
|
||||||
|
417
relaxng.c
417
relaxng.c
@ -57,8 +57,8 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
|
|||||||
/* #define DEBUG_INCLUDE */
|
/* #define DEBUG_INCLUDE */
|
||||||
/* #define DEBUG_ERROR 1 */
|
/* #define DEBUG_ERROR 1 */
|
||||||
/* #define DEBUG_COMPILE 1 */
|
/* #define DEBUG_COMPILE 1 */
|
||||||
|
/* #define DEBUG_PROGRESSIVE 1 */
|
||||||
|
|
||||||
#define UNBOUNDED (1 << 30)
|
|
||||||
#define MAX_ERROR 5
|
#define MAX_ERROR 5
|
||||||
|
|
||||||
#define TODO \
|
#define TODO \
|
||||||
@ -356,6 +356,17 @@ struct _xmlRelaxNGValidCtxt {
|
|||||||
int freeStatesNr;
|
int freeStatesNr;
|
||||||
int freeStatesMax;
|
int freeStatesMax;
|
||||||
xmlRelaxNGStatesPtr *freeStates; /* the pool of free state groups */
|
xmlRelaxNGStatesPtr *freeStates; /* the pool of free state groups */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is used for "progressive" validation
|
||||||
|
*/
|
||||||
|
xmlRegExecCtxtPtr elem; /* the current element regexp */
|
||||||
|
int elemNr; /* the number of element validated */
|
||||||
|
int elemMax; /* the max depth of elements */
|
||||||
|
xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
|
||||||
|
int pstate; /* progressive state */
|
||||||
|
xmlNodePtr pnode; /* the current node */
|
||||||
|
xmlRelaxNGDefinePtr pdef; /* the non-streamable definition */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7095,8 +7106,19 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
|
|||||||
/*
|
/*
|
||||||
* try to compile (parts of) the schemas
|
* try to compile (parts of) the schemas
|
||||||
*/
|
*/
|
||||||
if (ctxt->grammar != NULL)
|
if ((ctxt->grammar != NULL) && (ctxt->grammar->start != NULL)) {
|
||||||
|
if (ctxt->grammar->start->type != XML_RELAXNG_START) {
|
||||||
|
xmlRelaxNGDefinePtr def;
|
||||||
|
|
||||||
|
def = xmlRelaxNGNewDefine(ctxt, NULL);
|
||||||
|
if (def != NULL) {
|
||||||
|
def->type = XML_RELAXNG_START;
|
||||||
|
def->content = ctxt->grammar->start;
|
||||||
|
ctxt->grammar->start = def;
|
||||||
|
}
|
||||||
|
}
|
||||||
xmlRelaxNGTryCompile(ctxt, ctxt->grammar->start);
|
xmlRelaxNGTryCompile(ctxt, ctxt->grammar->start);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transfer the pointer for cleanup at the schema level.
|
* Transfer the pointer for cleanup at the schema level.
|
||||||
@ -7485,7 +7507,7 @@ xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
|
|||||||
ctxt->state->seq = NULL;
|
ctxt->state->seq = NULL;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
/*
|
/*
|
||||||
* TODO: get soem of the names needed to exit the current state of exec
|
* TODO: get some of the names needed to exit the current state of exec
|
||||||
*/
|
*/
|
||||||
VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
|
VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -7503,6 +7525,381 @@ xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
|
|||||||
* Progressive validation of when possible *
|
* Progressive validation of when possible *
|
||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
xmlRelaxNGDefinePtr defines);
|
||||||
|
static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGElemPush:
|
||||||
|
* @ctxt: the validation context
|
||||||
|
* @exec: the regexp runtime for the new content model
|
||||||
|
*
|
||||||
|
* Push a new regexp for the current node content model on the stack
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success and -1 in case of error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec) {
|
||||||
|
if (ctxt->elemTab == NULL) {
|
||||||
|
ctxt->elemMax = 10;
|
||||||
|
ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax *
|
||||||
|
sizeof(xmlRegExecCtxtPtr));
|
||||||
|
if (ctxt->elemTab == NULL) {
|
||||||
|
VALID_ERR(XML_RELAXNG_ERR_MEMORY);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ctxt->elemNr >= ctxt->elemMax) {
|
||||||
|
ctxt->elemMax *= 2;
|
||||||
|
ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab,
|
||||||
|
ctxt->elemMax * sizeof(xmlRegExecCtxtPtr));
|
||||||
|
if (ctxt->elemTab == NULL) {
|
||||||
|
VALID_ERR(XML_RELAXNG_ERR_MEMORY);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctxt->elemTab[ctxt->elemNr++] = exec;
|
||||||
|
ctxt->elem = exec;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGElemPop:
|
||||||
|
* @ctxt: the validation context
|
||||||
|
*
|
||||||
|
* Pop the regexp of the current node content model from the stack
|
||||||
|
*
|
||||||
|
* Returns the exec or NULL if empty
|
||||||
|
*/
|
||||||
|
static xmlRegExecCtxtPtr
|
||||||
|
xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt) {
|
||||||
|
xmlRegExecCtxtPtr ret;
|
||||||
|
|
||||||
|
if (ctxt->elemNr <= 0) return(NULL);
|
||||||
|
ctxt->elemNr--;
|
||||||
|
ret = ctxt->elemTab[ctxt->elemNr];
|
||||||
|
ctxt->elemTab[ctxt->elemNr] = NULL;
|
||||||
|
if (ctxt->elemNr > 0)
|
||||||
|
ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1];
|
||||||
|
else
|
||||||
|
ctxt->elem = NULL;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGValidateProgressiveCallback:
|
||||||
|
* @exec: the regular expression instance
|
||||||
|
* @token: the token which matched
|
||||||
|
* @transdata: callback data, the define for the subelement if available
|
||||||
|
@ @inputdata: callback data, the Relax NG validation context
|
||||||
|
*
|
||||||
|
* Handle the callback and if needed validate the element children.
|
||||||
|
* some of the in/out informations are passed via the context in @inputdata.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
|
||||||
|
const xmlChar *token,
|
||||||
|
void *transdata,
|
||||||
|
void *inputdata) {
|
||||||
|
xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
|
||||||
|
xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
|
||||||
|
xmlRelaxNGValidStatePtr state;
|
||||||
|
xmlNodePtr node = ctxt->pnode;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"Progressive callback for: '%s'\n", token);
|
||||||
|
#endif
|
||||||
|
if (ctxt == NULL) {
|
||||||
|
fprintf(stderr, "callback on %s missing context\n", token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctxt->pstate = 1;
|
||||||
|
if (define == NULL) {
|
||||||
|
if (token[0] == '#')
|
||||||
|
return;
|
||||||
|
fprintf(stderr, "callback on %s missing define\n", token);
|
||||||
|
if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
|
||||||
|
ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((ctxt == NULL) || (define == NULL)) {
|
||||||
|
fprintf(stderr, "callback on %s missing info\n", token);
|
||||||
|
if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
|
||||||
|
ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
return;
|
||||||
|
} else if (define->type != XML_RELAXNG_ELEMENT) {
|
||||||
|
fprintf(stderr, "callback on %s define is not element\n", token);
|
||||||
|
if (ctxt->errNo == XML_RELAXNG_OK)
|
||||||
|
ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node->type != XML_ELEMENT_NODE) {
|
||||||
|
VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
|
||||||
|
if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
|
||||||
|
xmlRelaxNGDumpValidError(ctxt);
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (define->contModel == NULL) {
|
||||||
|
/*
|
||||||
|
* this node cannot be validated in a streamable fashion
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"Element '%s' validation is not streamable\n", token);
|
||||||
|
#endif
|
||||||
|
ctxt->pstate = 0;
|
||||||
|
ctxt->pdef = define;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
exec = xmlRegNewExecCtxt(define->contModel,
|
||||||
|
xmlRelaxNGValidateProgressiveCallback,
|
||||||
|
ctxt);
|
||||||
|
if (exec == NULL) {
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xmlRelaxNGElemPush(ctxt, exec);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate the attributes part of the content.
|
||||||
|
*/
|
||||||
|
state = xmlRelaxNGNewValidState(ctxt, node);
|
||||||
|
if (state == NULL) {
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctxt->state = state;
|
||||||
|
if (define->attrs != NULL) {
|
||||||
|
ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
|
||||||
|
if (ret != 0) {
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctxt->state->seq = NULL;
|
||||||
|
ret = xmlRelaxNGValidateElementEnd(ctxt);
|
||||||
|
if (ret != 0) {
|
||||||
|
ctxt->pstate = -1;
|
||||||
|
}
|
||||||
|
xmlRelaxNGFreeValidState(ctxt, state);
|
||||||
|
ctxt->state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGValidatePushElement:
|
||||||
|
* @ctxt: the validation context
|
||||||
|
* @doc: a document instance
|
||||||
|
* @elem: an element instance
|
||||||
|
*
|
||||||
|
* Push a new element start on the RelaxNG validation stack.
|
||||||
|
*
|
||||||
|
* returns 1 if no validation problem was found or 0 if validating the
|
||||||
|
* element requires a full node, and -1 in case of error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||||
|
xmlNodePtr elem)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (elem == NULL))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name);
|
||||||
|
#endif
|
||||||
|
if (ctxt->elem == 0) {
|
||||||
|
xmlRelaxNGPtr schema;
|
||||||
|
xmlRelaxNGGrammarPtr grammar;
|
||||||
|
xmlRegExecCtxtPtr exec;
|
||||||
|
xmlRelaxNGDefinePtr define;
|
||||||
|
|
||||||
|
schema = ctxt->schema;
|
||||||
|
if (schema == NULL) {
|
||||||
|
VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
grammar = schema->topgrammar;
|
||||||
|
if ((grammar == NULL) || (grammar->start == NULL)) {
|
||||||
|
VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
define = grammar->start;
|
||||||
|
if (define->contModel == NULL) {
|
||||||
|
ctxt->pdef = define;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
exec = xmlRegNewExecCtxt(define->contModel,
|
||||||
|
xmlRelaxNGValidateProgressiveCallback,
|
||||||
|
ctxt);
|
||||||
|
if (exec == NULL) {
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
xmlRelaxNGElemPush(ctxt, exec);
|
||||||
|
}
|
||||||
|
ctxt->pnode = elem;
|
||||||
|
ctxt->pstate = 0;
|
||||||
|
if (elem->ns != NULL) {
|
||||||
|
ret =
|
||||||
|
xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href,
|
||||||
|
ctxt);
|
||||||
|
} else {
|
||||||
|
ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name);
|
||||||
|
} else {
|
||||||
|
if (ctxt->pstate == 0)
|
||||||
|
ret = 0;
|
||||||
|
else if (ctxt->pstate < 0)
|
||||||
|
ret = -1;
|
||||||
|
else
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
if (ret < 0)
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n",
|
||||||
|
elem->name);
|
||||||
|
#endif
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGValidatePushCData:
|
||||||
|
* @ctxt: the RelaxNG validation context
|
||||||
|
* @data: some character data read
|
||||||
|
* @len: the lenght of the data
|
||||||
|
*
|
||||||
|
* check the CData parsed for validation in the current stack
|
||||||
|
*
|
||||||
|
* returns 1 if no validation problem was found or -1 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
const xmlChar * data, int len)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (*data != 0) {
|
||||||
|
if (!IS_BLANK(*data))
|
||||||
|
break;
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
if (*data == 0)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);
|
||||||
|
if (ret < 0) {
|
||||||
|
VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, " TODO ");
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "CDATA failed\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGValidatePopElement:
|
||||||
|
* @ctxt: the RelaxNG validation context
|
||||||
|
* @doc: a document instance
|
||||||
|
* @elem: an element instance
|
||||||
|
*
|
||||||
|
* Pop the element end from the RelaxNG validation stack.
|
||||||
|
*
|
||||||
|
* returns 1 if no validation problem was found or 0 otherwise
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
|
||||||
|
xmlDocPtr doc ATTRIBUTE_UNUSED,
|
||||||
|
xmlNodePtr elem) {
|
||||||
|
int ret;
|
||||||
|
xmlRegExecCtxtPtr exec;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL)) return(-1);
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* verify that we reached a terminal state of the content model.
|
||||||
|
*/
|
||||||
|
exec = xmlRelaxNGElemPop(ctxt);
|
||||||
|
ret = xmlRegExecPushString(exec, NULL, NULL);
|
||||||
|
if (ret == 0) {
|
||||||
|
/*
|
||||||
|
* TODO: get some of the names needed to exit the current state of exec
|
||||||
|
*/
|
||||||
|
VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
|
||||||
|
ret = -1;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
xmlRegFreeExecCtxt(exec);
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
if (ret < 0)
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n",
|
||||||
|
elem->name);
|
||||||
|
#endif
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlRelaxNGValidateFullElement:
|
||||||
|
* @ctxt: the validation context
|
||||||
|
* @doc: a document instance
|
||||||
|
* @elem: an element instance
|
||||||
|
*
|
||||||
|
* Validate a full subtree when xmlRelaxNGValidatePushElement() returned
|
||||||
|
* 0 and the content of the node has been expanded.
|
||||||
|
*
|
||||||
|
* returns 1 if no validation problem was found or -1 in case of error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||||
|
xmlNodePtr elem) {
|
||||||
|
int ret;
|
||||||
|
xmlRelaxNGValidStatePtr state;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL)) return(-1);
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name);
|
||||||
|
#endif
|
||||||
|
state = xmlRelaxNGNewValidState(ctxt, elem->parent);
|
||||||
|
if (state == NULL) {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
state->seq = elem;
|
||||||
|
ctxt->state = state;
|
||||||
|
ctxt->errNo = XML_RELAXNG_OK;
|
||||||
|
ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef);
|
||||||
|
if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK)) ret = -1;
|
||||||
|
else ret = 1;
|
||||||
|
xmlRelaxNGFreeValidState(ctxt, state);
|
||||||
|
ctxt->state = NULL;
|
||||||
|
#ifdef DEBUG_PROGRESSIVE
|
||||||
|
if (ret < 0)
|
||||||
|
xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n",
|
||||||
|
elem->name);
|
||||||
|
#endif
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* Generic interpreted validation implementation *
|
* Generic interpreted validation implementation *
|
||||||
@ -9158,11 +9555,10 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
|
|||||||
case XML_RELAXNG_ATTRIBUTE:
|
case XML_RELAXNG_ATTRIBUTE:
|
||||||
ret = xmlRelaxNGValidateAttribute(ctxt, define);
|
ret = xmlRelaxNGValidateAttribute(ctxt, define);
|
||||||
break;
|
break;
|
||||||
|
case XML_RELAXNG_START:
|
||||||
case XML_RELAXNG_NOOP:
|
case XML_RELAXNG_NOOP:
|
||||||
case XML_RELAXNG_REF:
|
case XML_RELAXNG_REF:
|
||||||
case XML_RELAXNG_EXTERNALREF:
|
case XML_RELAXNG_EXTERNALREF:
|
||||||
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
|
|
||||||
break;
|
|
||||||
case XML_RELAXNG_PARENTREF:
|
case XML_RELAXNG_PARENTREF:
|
||||||
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
|
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
|
||||||
break;
|
break;
|
||||||
@ -9308,7 +9704,6 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
|
|||||||
xmlFree(content);
|
xmlFree(content);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XML_RELAXNG_START:
|
|
||||||
case XML_RELAXNG_EXCEPT:
|
case XML_RELAXNG_EXCEPT:
|
||||||
case XML_RELAXNG_PARAM:
|
case XML_RELAXNG_PARAM:
|
||||||
TODO ret = -1;
|
TODO ret = -1;
|
||||||
@ -9617,6 +10012,16 @@ xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt) {
|
|||||||
}
|
}
|
||||||
if (ctxt->errTab != NULL)
|
if (ctxt->errTab != NULL)
|
||||||
xmlFree(ctxt->errTab);
|
xmlFree(ctxt->errTab);
|
||||||
|
if (ctxt->elemTab != NULL) {
|
||||||
|
xmlRegExecCtxtPtr exec;
|
||||||
|
|
||||||
|
exec = xmlRelaxNGElemPop(ctxt);
|
||||||
|
while (exec != NULL) {
|
||||||
|
xmlRegFreeExecCtxt(exec);
|
||||||
|
exec = xmlRelaxNGElemPop(ctxt);
|
||||||
|
}
|
||||||
|
xmlFree(ctxt->elemTab);
|
||||||
|
}
|
||||||
xmlFree(ctxt);
|
xmlFree(ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
valid.c
33
valid.c
@ -250,39 +250,6 @@ nodeVPop(xmlValidCtxtPtr ctxt)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/**
|
|
||||||
* xmlFreeValidCtxt:
|
|
||||||
* @ctxt: a validation context
|
|
||||||
*
|
|
||||||
* Free the memory allocated for a validation context
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
xmlFreeValidCtxt(xmlValidCtxtPtr ctxt) {
|
|
||||||
if (ctxt == NULL)
|
|
||||||
return;
|
|
||||||
#ifdef LIBXML_REGEXP_ENABLED
|
|
||||||
while (ctxt->vstateNr >= 0)
|
|
||||||
vstateVPop(ctxt);
|
|
||||||
if (ctxt->vstateNr <= 1) return(-1);
|
|
||||||
ctxt->vstateNr--;
|
|
||||||
elemDecl = ctxt->vstateTab[ctxt->vstateNr].elemDecl;
|
|
||||||
ctxt->vstateTab[ctxt->vstateNr].elemDecl = NULL;
|
|
||||||
ctxt->vstateTab[ctxt->vstateNr].node = NULL;
|
|
||||||
if ((elemDecl != NULL) && (elemDecl->etype == XML_ELEMENT_TYPE_ELEMENT)) {
|
|
||||||
xmlRegFreeExecCtxt(ctxt->vstateTab[ctxt->vstateNr].exec);
|
|
||||||
}
|
|
||||||
ctxt->vstateTab[ctxt->vstateNr].exec = NULL;
|
|
||||||
if (ctxt->vstateNr >= 1)
|
|
||||||
ctxt->vstate = &ctxt->vstateTab[ctxt->vstateNr - 1];
|
|
||||||
else
|
|
||||||
ctxt->vstate = NULL;
|
|
||||||
return(ctxt->vstateNr);
|
|
||||||
#else /* ! LIBXML_REGEXP_ENABLED */
|
|
||||||
#endif /* LIBXML_REGEXP_ENABLED */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_VALID_ALGO
|
#ifdef DEBUG_VALID_ALGO
|
||||||
static void
|
static void
|
||||||
xmlValidPrintNode(xmlNodePtr cur) {
|
xmlValidPrintNode(xmlNodePtr cur) {
|
||||||
|
10
xmllint.c
10
xmllint.c
@ -624,6 +624,8 @@ static void streamFile(char *filename) {
|
|||||||
if (reader != NULL) {
|
if (reader != NULL) {
|
||||||
if (valid)
|
if (valid)
|
||||||
xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
|
xmlTextReaderSetParserProp(reader, XML_PARSER_VALIDATE, 1);
|
||||||
|
if (relaxng != NULL)
|
||||||
|
xmlTextReaderRelaxNGValidate(reader, relaxng);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process all nodes in sequence
|
* Process all nodes in sequence
|
||||||
@ -642,6 +644,14 @@ static void streamFile(char *filename) {
|
|||||||
progresult = 3;
|
progresult = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (relaxng != NULL) {
|
||||||
|
if (xmlTextReaderIsValid(reader) != 1) {
|
||||||
|
printf("%s fails to validate\n", filename);
|
||||||
|
progresult = 3;
|
||||||
|
} else {
|
||||||
|
printf("%s validates\n", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Done, cleanup and status
|
* Done, cleanup and status
|
||||||
*/
|
*/
|
||||||
|
244
xmlreader.c
244
xmlreader.c
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* TODOs:
|
* TODOs:
|
||||||
* - provide an API to expand part of the tree
|
|
||||||
* - provide an API to preserve part of the tree
|
* - provide an API to preserve part of the tree
|
||||||
* - Streaming XInclude support
|
* - Streaming XInclude support
|
||||||
* - validation against a provided DTD
|
* - validation against a provided DTD
|
||||||
@ -36,6 +35,7 @@
|
|||||||
#include <libxml/xmlmemory.h>
|
#include <libxml/xmlmemory.h>
|
||||||
#include <libxml/xmlIO.h>
|
#include <libxml/xmlIO.h>
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
#include <libxml/relaxng.h>
|
||||||
|
|
||||||
/* #define DEBUG_CALLBACKS */
|
/* #define DEBUG_CALLBACKS */
|
||||||
/* #define DEBUG_READER */
|
/* #define DEBUG_READER */
|
||||||
@ -85,8 +85,15 @@ typedef enum {
|
|||||||
XML_TEXTREADER_DONE= 5
|
XML_TEXTREADER_DONE= 5
|
||||||
} xmlTextReaderState;
|
} xmlTextReaderState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
XML_TEXTREADER_NOT_VALIDATE = 0,
|
||||||
|
XML_TEXTREADER_VALIDATE_DTD = 1,
|
||||||
|
XML_TEXTREADER_VALIDATE_RNG = 2
|
||||||
|
} xmlTextReaderValidate;
|
||||||
|
|
||||||
struct _xmlTextReader {
|
struct _xmlTextReader {
|
||||||
int mode; /* the parsing mode */
|
int mode; /* the parsing mode */
|
||||||
|
xmlTextReaderValidate validate;/* is there any validation */
|
||||||
int allocs; /* what structure were deallocated */
|
int allocs; /* what structure were deallocated */
|
||||||
xmlTextReaderState state;
|
xmlTextReaderState state;
|
||||||
xmlParserCtxtPtr ctxt; /* the parser context */
|
xmlParserCtxtPtr ctxt; /* the parser context */
|
||||||
@ -112,6 +119,14 @@ struct _xmlTextReader {
|
|||||||
/* error handling */
|
/* error handling */
|
||||||
xmlTextReaderErrorFunc errorFunc; /* callback function */
|
xmlTextReaderErrorFunc errorFunc; /* callback function */
|
||||||
void *errorFuncArg; /* callback function user argument */
|
void *errorFuncArg; /* callback function user argument */
|
||||||
|
|
||||||
|
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||||
|
/* Handling of RelaxNG validation */
|
||||||
|
xmlRelaxNGPtr rngSchemas; /* The Relax NG schemas */
|
||||||
|
xmlRelaxNGValidCtxtPtr rngValidCtxt; /* The Relax NG validation context */
|
||||||
|
int rngValidErrors; /* The number of errors detected */
|
||||||
|
xmlNodePtr rngFullNode; /* the node if RNG not progressive */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *xmlTextReaderIsEmpty = "This element is empty";
|
static const char *xmlTextReaderIsEmpty = "This element is empty";
|
||||||
@ -425,22 +440,84 @@ xmlTextReaderValidatePush(xmlTextReaderPtr reader) {
|
|||||||
#ifdef LIBXML_REGEXP_ENABLED
|
#ifdef LIBXML_REGEXP_ENABLED
|
||||||
xmlNodePtr node = reader->node;
|
xmlNodePtr node = reader->node;
|
||||||
|
|
||||||
if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
|
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
|
||||||
reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
|
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
|
||||||
reader->ctxt->myDoc, node, node->name);
|
if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
|
||||||
} else {
|
reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
|
||||||
xmlChar *qname;
|
reader->ctxt->myDoc, node, node->name);
|
||||||
|
} else {
|
||||||
|
/* TODO use the BuildQName interface */
|
||||||
|
xmlChar *qname;
|
||||||
|
|
||||||
qname = xmlStrdup(node->ns->prefix);
|
qname = xmlStrdup(node->ns->prefix);
|
||||||
qname = xmlStrcat(qname, BAD_CAST ":");
|
qname = xmlStrcat(qname, BAD_CAST ":");
|
||||||
qname = xmlStrcat(qname, node->name);
|
qname = xmlStrcat(qname, node->name);
|
||||||
reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
|
reader->ctxt->valid &= xmlValidatePushElement(&reader->ctxt->vctxt,
|
||||||
reader->ctxt->myDoc, node, qname);
|
reader->ctxt->myDoc, node, qname);
|
||||||
if (qname != NULL)
|
if (qname != NULL)
|
||||||
xmlFree(qname);
|
xmlFree(qname);
|
||||||
|
}
|
||||||
|
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||||
|
} else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
|
||||||
|
(reader->rngValidCtxt != NULL)) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (reader->rngFullNode != NULL) return;
|
||||||
|
ret = xmlRelaxNGValidatePushElement(reader->rngValidCtxt,
|
||||||
|
reader->ctxt->myDoc,
|
||||||
|
node);
|
||||||
|
if (ret == 0) {
|
||||||
|
/*
|
||||||
|
* this element requires a full tree
|
||||||
|
*/
|
||||||
|
node = xmlTextReaderExpand(reader);
|
||||||
|
if (node == NULL) {
|
||||||
|
printf("Expand failed !\n");
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
ret = xmlRelaxNGValidateFullElement(reader->rngValidCtxt,
|
||||||
|
reader->ctxt->myDoc,
|
||||||
|
node);
|
||||||
|
reader->rngFullNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret != 1)
|
||||||
|
reader->rngValidErrors++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* LIBXML_REGEXP_ENABLED */
|
#endif /* LIBXML_REGEXP_ENABLED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlTextReaderValidateCData:
|
||||||
|
* @reader: the xmlTextReaderPtr used
|
||||||
|
* @data: pointer to the CData
|
||||||
|
* @len: lenght of the CData block in bytes.
|
||||||
|
*
|
||||||
|
* Push some CData for validation
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
xmlTextReaderValidateCData(xmlTextReaderPtr reader,
|
||||||
|
const xmlChar *data, int len) {
|
||||||
|
#ifdef LIBXML_REGEXP_ENABLED
|
||||||
|
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
|
||||||
|
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
|
||||||
|
reader->ctxt->valid &= xmlValidatePushCData(&reader->ctxt->vctxt,
|
||||||
|
data, len);
|
||||||
|
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||||
|
} else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
|
||||||
|
(reader->rngValidCtxt != NULL)) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (reader->rngFullNode != NULL) return;
|
||||||
|
ret = xmlRelaxNGValidatePushCData(reader->rngValidCtxt, data, len);
|
||||||
|
if (ret != 1)
|
||||||
|
reader->rngValidErrors++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* LIBXML_REGEXP_ENABLED */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlTextReaderValidatePop:
|
* xmlTextReaderValidatePop:
|
||||||
* @reader: the xmlTextReaderPtr used
|
* @reader: the xmlTextReaderPtr used
|
||||||
@ -452,19 +529,39 @@ xmlTextReaderValidatePop(xmlTextReaderPtr reader) {
|
|||||||
#ifdef LIBXML_REGEXP_ENABLED
|
#ifdef LIBXML_REGEXP_ENABLED
|
||||||
xmlNodePtr node = reader->node;
|
xmlNodePtr node = reader->node;
|
||||||
|
|
||||||
if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
|
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
|
||||||
reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
|
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
|
||||||
reader->ctxt->myDoc, node, node->name);
|
if ((node->ns == NULL) || (node->ns->prefix == NULL)) {
|
||||||
} else {
|
reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
|
||||||
xmlChar *qname;
|
reader->ctxt->myDoc, node, node->name);
|
||||||
|
} else {
|
||||||
|
/* TODO use the BuildQName interface */
|
||||||
|
xmlChar *qname;
|
||||||
|
|
||||||
qname = xmlStrdup(node->ns->prefix);
|
qname = xmlStrdup(node->ns->prefix);
|
||||||
qname = xmlStrcat(qname, BAD_CAST ":");
|
qname = xmlStrcat(qname, BAD_CAST ":");
|
||||||
qname = xmlStrcat(qname, node->name);
|
qname = xmlStrcat(qname, node->name);
|
||||||
reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
|
reader->ctxt->valid &= xmlValidatePopElement(&reader->ctxt->vctxt,
|
||||||
reader->ctxt->myDoc, node, qname);
|
reader->ctxt->myDoc, node, qname);
|
||||||
if (qname != NULL)
|
if (qname != NULL)
|
||||||
xmlFree(qname);
|
xmlFree(qname);
|
||||||
|
}
|
||||||
|
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||||
|
} else if ((reader->validate == XML_TEXTREADER_VALIDATE_RNG) &&
|
||||||
|
(reader->rngValidCtxt != NULL)) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (reader->rngFullNode != NULL) {
|
||||||
|
if (node == reader->rngFullNode)
|
||||||
|
reader->rngFullNode = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = xmlRelaxNGValidatePopElement(reader->rngValidCtxt,
|
||||||
|
reader->ctxt->myDoc,
|
||||||
|
node);
|
||||||
|
if (ret != 1)
|
||||||
|
reader->rngValidErrors++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* LIBXML_REGEXP_ENABLED */
|
#endif /* LIBXML_REGEXP_ENABLED */
|
||||||
}
|
}
|
||||||
@ -514,8 +611,8 @@ xmlTextReaderValidateEntity(xmlTextReaderPtr reader) {
|
|||||||
xmlTextReaderValidatePush(reader);
|
xmlTextReaderValidatePush(reader);
|
||||||
} else if ((node->type == XML_TEXT_NODE) ||
|
} else if ((node->type == XML_TEXT_NODE) ||
|
||||||
(node->type == XML_CDATA_SECTION_NODE)) {
|
(node->type == XML_CDATA_SECTION_NODE)) {
|
||||||
ctxt->valid &= xmlValidatePushCData(&ctxt->vctxt,
|
xmlTextReaderValidateCData(reader, node->content,
|
||||||
node->content, xmlStrlen(node->content));
|
xmlStrlen(node->content));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -745,7 +842,7 @@ get_next_node:
|
|||||||
reader->state = XML_TEXTREADER_END;
|
reader->state = XML_TEXTREADER_END;
|
||||||
goto node_found;
|
goto node_found;
|
||||||
}
|
}
|
||||||
if ((reader->ctxt->validate) &&
|
if ((reader->validate) &&
|
||||||
(reader->node->type == XML_ELEMENT_NODE))
|
(reader->node->type == XML_ELEMENT_NODE))
|
||||||
xmlTextReaderValidatePop(reader);
|
xmlTextReaderValidatePop(reader);
|
||||||
reader->node = reader->node->next;
|
reader->node = reader->node->next;
|
||||||
@ -770,7 +867,7 @@ get_next_node:
|
|||||||
reader->state = XML_TEXTREADER_END;
|
reader->state = XML_TEXTREADER_END;
|
||||||
goto node_found;
|
goto node_found;
|
||||||
}
|
}
|
||||||
if ((reader->ctxt->validate) && (reader->node->type == XML_ELEMENT_NODE))
|
if ((reader->validate) && (reader->node->type == XML_ELEMENT_NODE))
|
||||||
xmlTextReaderValidatePop(reader);
|
xmlTextReaderValidatePop(reader);
|
||||||
reader->node = reader->node->parent;
|
reader->node = reader->node->parent;
|
||||||
if ((reader->node == NULL) ||
|
if ((reader->node == NULL) ||
|
||||||
@ -826,7 +923,7 @@ node_found:
|
|||||||
}
|
}
|
||||||
} else if ((reader->node != NULL) &&
|
} else if ((reader->node != NULL) &&
|
||||||
(reader->node->type == XML_ENTITY_REF_NODE) &&
|
(reader->node->type == XML_ENTITY_REF_NODE) &&
|
||||||
(reader->ctxt != NULL) && (reader->ctxt->validate == 1)) {
|
(reader->ctxt != NULL) && (reader->validate)) {
|
||||||
xmlTextReaderValidateEntity(reader);
|
xmlTextReaderValidateEntity(reader);
|
||||||
}
|
}
|
||||||
if ((reader->node != NULL) &&
|
if ((reader->node != NULL) &&
|
||||||
@ -837,9 +934,8 @@ node_found:
|
|||||||
goto get_next_node;
|
goto get_next_node;
|
||||||
}
|
}
|
||||||
#ifdef LIBXML_REGEXP_ENABLED
|
#ifdef LIBXML_REGEXP_ENABLED
|
||||||
if ((reader->ctxt->validate) && (reader->node != NULL)) {
|
if ((reader->validate) && (reader->node != NULL)) {
|
||||||
xmlNodePtr node = reader->node;
|
xmlNodePtr node = reader->node;
|
||||||
xmlParserCtxtPtr ctxt = reader->ctxt;
|
|
||||||
|
|
||||||
if ((node->type == XML_ELEMENT_NODE) &&
|
if ((node->type == XML_ELEMENT_NODE) &&
|
||||||
((reader->state != XML_TEXTREADER_END) &&
|
((reader->state != XML_TEXTREADER_END) &&
|
||||||
@ -847,8 +943,8 @@ node_found:
|
|||||||
xmlTextReaderValidatePush(reader);
|
xmlTextReaderValidatePush(reader);
|
||||||
} else if ((node->type == XML_TEXT_NODE) ||
|
} else if ((node->type == XML_TEXT_NODE) ||
|
||||||
(node->type == XML_CDATA_SECTION_NODE)) {
|
(node->type == XML_CDATA_SECTION_NODE)) {
|
||||||
ctxt->valid &= xmlValidatePushCData(&ctxt->vctxt,
|
xmlTextReaderValidateCData(reader, node->content,
|
||||||
node->content, xmlStrlen(node->content));
|
xmlStrlen(node->content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* LIBXML_REGEXP_ENABLED */
|
#endif /* LIBXML_REGEXP_ENABLED */
|
||||||
@ -1140,6 +1236,14 @@ void
|
|||||||
xmlFreeTextReader(xmlTextReaderPtr reader) {
|
xmlFreeTextReader(xmlTextReaderPtr reader) {
|
||||||
if (reader == NULL)
|
if (reader == NULL)
|
||||||
return;
|
return;
|
||||||
|
if (reader->rngSchemas != NULL) {
|
||||||
|
xmlRelaxNGFree(reader->rngSchemas);
|
||||||
|
reader->rngSchemas = NULL;
|
||||||
|
}
|
||||||
|
if (reader->rngValidCtxt != NULL) {
|
||||||
|
xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
|
||||||
|
reader->rngValidCtxt = NULL;
|
||||||
|
}
|
||||||
if (reader->ctxt != NULL) {
|
if (reader->ctxt != NULL) {
|
||||||
if (reader->ctxt->myDoc != NULL) {
|
if (reader->ctxt->myDoc != NULL) {
|
||||||
xmlFreeDoc(reader->ctxt->myDoc);
|
xmlFreeDoc(reader->ctxt->myDoc);
|
||||||
@ -2308,6 +2412,7 @@ xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
|
|||||||
case XML_PARSER_VALIDATE:
|
case XML_PARSER_VALIDATE:
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
ctxt->validate = 1;
|
ctxt->validate = 1;
|
||||||
|
reader->validate = XML_TEXTREADER_VALIDATE_DTD;
|
||||||
} else {
|
} else {
|
||||||
ctxt->validate = 0;
|
ctxt->validate = 0;
|
||||||
}
|
}
|
||||||
@ -2351,7 +2456,7 @@ xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
|
|||||||
return(1);
|
return(1);
|
||||||
return(0);
|
return(0);
|
||||||
case XML_PARSER_VALIDATE:
|
case XML_PARSER_VALIDATE:
|
||||||
return(ctxt->validate);
|
return(reader->validate);
|
||||||
case XML_PARSER_SUBST_ENTITIES:
|
case XML_PARSER_SUBST_ENTITIES:
|
||||||
return(ctxt->replaceEntities);
|
return(ctxt->replaceEntities);
|
||||||
}
|
}
|
||||||
@ -2396,6 +2501,64 @@ xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) {
|
|||||||
return(reader->ctxt->myDoc);
|
return(reader->ctxt->myDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlTextReaderRelaxNGValidate:
|
||||||
|
* @reader: the xmlTextReaderPtr used
|
||||||
|
* @rng: the path to a RelaxNG schema or NULL
|
||||||
|
*
|
||||||
|
* Use RelaxNG to validate the document as it is processed.
|
||||||
|
* Activation is only possible before the first Read().
|
||||||
|
* if @rng is NULL, then RelaxNG validation is desactivated.
|
||||||
|
*
|
||||||
|
* Returns 0 in case the RelaxNG validation could be (des)activated and
|
||||||
|
* -1 in case of error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
|
||||||
|
xmlRelaxNGParserCtxtPtr ctxt;
|
||||||
|
|
||||||
|
if (reader == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (rng == NULL) {
|
||||||
|
if (reader->rngSchemas != NULL) {
|
||||||
|
xmlRelaxNGFree(reader->rngSchemas);
|
||||||
|
reader->rngSchemas = NULL;
|
||||||
|
}
|
||||||
|
if (reader->rngValidCtxt != NULL) {
|
||||||
|
xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
|
||||||
|
reader->rngValidCtxt = NULL;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
|
||||||
|
return(-1);
|
||||||
|
ctxt = xmlRelaxNGNewParserCtxt(rng);
|
||||||
|
if (reader->errorFunc != NULL) {
|
||||||
|
xmlRelaxNGSetParserErrors(ctxt,
|
||||||
|
(xmlRelaxNGValidityErrorFunc) reader->errorFunc,
|
||||||
|
(xmlRelaxNGValidityWarningFunc) reader->errorFunc,
|
||||||
|
reader->errorFuncArg);
|
||||||
|
}
|
||||||
|
reader->rngSchemas = xmlRelaxNGParse(ctxt);
|
||||||
|
xmlRelaxNGFreeParserCtxt(ctxt);
|
||||||
|
if (reader->rngSchemas == NULL)
|
||||||
|
return(-1);
|
||||||
|
reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
|
||||||
|
if (reader->rngValidCtxt == NULL)
|
||||||
|
return(-1);
|
||||||
|
if (reader->errorFunc != NULL) {
|
||||||
|
xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
|
||||||
|
(xmlRelaxNGValidityErrorFunc)reader->errorFunc,
|
||||||
|
(xmlRelaxNGValidityWarningFunc) reader->errorFunc,
|
||||||
|
reader->errorFuncArg);
|
||||||
|
}
|
||||||
|
reader->rngValidErrors = 0;
|
||||||
|
reader->rngFullNode = NULL;
|
||||||
|
reader->validate = XML_TEXTREADER_VALIDATE_RNG;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* Error Handling Extensions *
|
* Error Handling Extensions *
|
||||||
@ -2621,8 +2784,15 @@ xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader,
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmlTextReaderIsValid(xmlTextReaderPtr reader) {
|
xmlTextReaderIsValid(xmlTextReaderPtr reader) {
|
||||||
if ((reader == NULL) || (reader->ctxt == NULL)) return(-1);
|
if (reader == NULL) return(-1);
|
||||||
return(reader->ctxt->valid);
|
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||||
|
if (reader->validate == XML_TEXTREADER_VALIDATE_RNG)
|
||||||
|
return(reader->rngValidErrors == 0);
|
||||||
|
#endif
|
||||||
|
if ((reader->validate == XML_TEXTREADER_VALIDATE_DTD) &&
|
||||||
|
(reader->ctxt != NULL))
|
||||||
|
return(reader->ctxt->valid);
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user