2003-01-23 18:29:16 +00:00
/*
* relaxng . c : implementation of the Relax - NG handling and validity checking
*
* See Copyright for the status of this software .
*
* Daniel Veillard < veillard @ redhat . com >
*/
2003-01-29 21:07:52 +00:00
/**
* TODO :
2003-02-13 11:02:08 +00:00
* - add support for DTD compatibility spec
* http : //www.oasis-open.org/committees/relax-ng/compatibility-20011203.html
2003-04-17 12:55:35 +00:00
* - report better mem allocations pbms at runtime and abort immediately .
2003-01-29 21:07:52 +00:00
*/
2003-01-23 18:29:16 +00:00
# define IN_LIBXML
# include "libxml.h"
# ifdef LIBXML_SCHEMAS_ENABLED
# include <string.h>
# include <stdio.h>
2017-10-09 13:37:42 +02:00
# include <stddef.h>
2003-01-23 18:29:16 +00:00
# include <libxml/xmlmemory.h>
# include <libxml/parser.h>
# include <libxml/parserInternals.h>
# include <libxml/hash.h>
# include <libxml/uri.h>
# include <libxml/relaxng.h>
# include <libxml/xmlschemastypes.h>
# include <libxml/xmlautomata.h>
# include <libxml/xmlregexp.h>
2003-01-27 12:35:42 +00:00
# include <libxml/xmlschemastypes.h>
2003-01-23 18:29:16 +00:00
2022-08-26 01:22:33 +02:00
# include "private/error.h"
# include "private/regexp.h"
# include "private/string.h"
2003-01-23 18:29:16 +00:00
/*
* The Relax - NG namespace
*/
static const xmlChar * xmlRelaxNGNs = ( const xmlChar * )
" http://relaxng.org/ns/structure/1.0 " ;
2012-08-13 12:40:53 +08:00
# define IS_RELAXNG(node, typ) \
2003-01-23 18:29:16 +00:00
( ( node ! = NULL ) & & ( node - > ns ! = NULL ) & & \
2012-08-13 12:40:53 +08:00
( node - > type = = XML_ELEMENT_NODE ) & & \
( xmlStrEqual ( node - > name , ( const xmlChar * ) typ ) ) & & \
2003-01-23 18:29:16 +00:00
( xmlStrEqual ( node - > ns - > href , xmlRelaxNGNs ) ) )
2008-06-25 04:11:24 +00:00
#if 0
2006-02-19 15:27:17 +00:00
# define DEBUG 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_GRAMMAR 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_CONTENT 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_TYPE 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_VALID 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_INTERLEAVE 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_LIST 1
2003-10-07 11:33:24 +00:00
2012-09-11 13:26:36 +08:00
# define DEBUG_INCLUDE 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_ERROR 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_COMPILE 1
2003-10-07 11:33:24 +00:00
2006-02-19 15:27:17 +00:00
# define DEBUG_PROGRESSIVE 1
# endif
2003-01-23 18:29:16 +00:00
2003-03-31 16:38:16 +00:00
# define MAX_ERROR 5
2012-09-11 13:26:36 +08:00
# define TODO \
2003-01-23 18:29:16 +00:00
xmlGenericError ( xmlGenericErrorContext , \
" Unimplemented block at %s:%d \n " , \
__FILE__ , __LINE__ ) ;
typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema ;
typedef xmlRelaxNGSchema * xmlRelaxNGSchemaPtr ;
typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine ;
typedef xmlRelaxNGDefine * xmlRelaxNGDefinePtr ;
2003-01-29 21:07:52 +00:00
typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument ;
typedef xmlRelaxNGDocument * xmlRelaxNGDocumentPtr ;
2003-02-01 17:43:10 +00:00
typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude ;
typedef xmlRelaxNGInclude * xmlRelaxNGIncludePtr ;
2003-01-23 18:29:16 +00:00
typedef enum {
2003-10-07 11:33:24 +00:00
XML_RELAXNG_COMBINE_UNDEFINED = 0 , /* undefined */
XML_RELAXNG_COMBINE_CHOICE , /* choice */
XML_RELAXNG_COMBINE_INTERLEAVE /* interleave */
2003-01-23 18:29:16 +00:00
} xmlRelaxNGCombine ;
2003-02-21 15:40:34 +00:00
typedef enum {
XML_RELAXNG_CONTENT_ERROR = - 1 ,
XML_RELAXNG_CONTENT_EMPTY = 0 ,
XML_RELAXNG_CONTENT_SIMPLE ,
XML_RELAXNG_CONTENT_COMPLEX
} xmlRelaxNGContentType ;
2003-01-23 18:29:16 +00:00
typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar ;
typedef xmlRelaxNGGrammar * xmlRelaxNGGrammarPtr ;
struct _xmlRelaxNGGrammar {
2003-10-07 11:33:24 +00:00
xmlRelaxNGGrammarPtr parent ; /* the parent grammar if any */
xmlRelaxNGGrammarPtr children ; /* the children grammar if any */
xmlRelaxNGGrammarPtr next ; /* the next grammar if any */
xmlRelaxNGDefinePtr start ; /* <start> content */
xmlRelaxNGCombine combine ; /* the default combine value */
xmlRelaxNGDefinePtr startList ; /* list of <start> definitions */
xmlHashTablePtr defs ; /* define* */
xmlHashTablePtr refs ; /* references */
2003-01-23 18:29:16 +00:00
} ;
typedef enum {
2003-10-07 11:33:24 +00:00
XML_RELAXNG_NOOP = - 1 , /* a no operation from simplification */
XML_RELAXNG_EMPTY = 0 , /* an empty pattern */
2003-01-23 18:29:16 +00:00
XML_RELAXNG_NOT_ALLOWED , /* not allowed top */
2003-10-07 11:33:24 +00:00
XML_RELAXNG_EXCEPT , /* except present in nameclass defs */
XML_RELAXNG_TEXT , /* textual content */
XML_RELAXNG_ELEMENT , /* an element */
2019-09-30 17:04:54 +02:00
XML_RELAXNG_DATATYPE , /* external data type definition */
XML_RELAXNG_PARAM , /* external data type parameter */
XML_RELAXNG_VALUE , /* value from an external data type definition */
2003-10-07 11:33:24 +00:00
XML_RELAXNG_LIST , /* a list of patterns */
2019-09-30 17:04:54 +02:00
XML_RELAXNG_ATTRIBUTE , /* an attribute following a pattern */
2003-10-07 11:33:24 +00:00
XML_RELAXNG_DEF , /* a definition */
XML_RELAXNG_REF , /* reference to a definition */
XML_RELAXNG_EXTERNALREF , /* reference to an external def */
XML_RELAXNG_PARENTREF , /* reference to a def in the parent grammar */
XML_RELAXNG_OPTIONAL , /* optional patterns */
XML_RELAXNG_ZEROORMORE , /* zero or more non empty patterns */
XML_RELAXNG_ONEORMORE , /* one or more non empty patterns */
XML_RELAXNG_CHOICE , /* a choice between non empty patterns */
XML_RELAXNG_GROUP , /* a pair/group of non empty patterns */
XML_RELAXNG_INTERLEAVE , /* interleaving choice of non-empty patterns */
XML_RELAXNG_START /* Used to keep track of starts on grammars */
2003-01-23 18:29:16 +00:00
} xmlRelaxNGType ;
2003-04-13 19:53:42 +00:00
# define IS_NULLABLE (1 << 0)
# define IS_NOT_NULLABLE (1 << 1)
# define IS_INDETERMINIST (1 << 2)
# define IS_MIXED (1 << 3)
# define IS_TRIABLE (1 << 4)
# define IS_PROCESSED (1 << 5)
# define IS_COMPILABLE (1 << 6)
# define IS_NOT_COMPILABLE (1 << 7)
2009-09-24 11:31:48 +02:00
# define IS_EXTERNAL_REF (1 << 8)
2003-03-15 21:30:25 +00:00
2003-01-23 18:29:16 +00:00
struct _xmlRelaxNGDefine {
2003-10-07 11:33:24 +00:00
xmlRelaxNGType type ; /* the type of definition */
xmlNodePtr node ; /* the node in the source */
xmlChar * name ; /* the element local name if present */
xmlChar * ns ; /* the namespace local name if present */
xmlChar * value ; /* value when available */
void * data ; /* data lib or specific pointer */
xmlRelaxNGDefinePtr content ; /* the expected content */
xmlRelaxNGDefinePtr parent ; /* the parent definition, if any */
xmlRelaxNGDefinePtr next ; /* list within grouping sequences */
xmlRelaxNGDefinePtr attrs ; /* list of attributes for elements */
xmlRelaxNGDefinePtr nameClass ; /* the nameClass definition if any */
xmlRelaxNGDefinePtr nextHash ; /* next define in defs/refs hash tables */
short depth ; /* used for the cycle detection */
short dflags ; /* define related flags */
xmlRegexpPtr contModel ; /* a compiled content model if available */
2003-01-23 18:29:16 +00:00
} ;
/**
* _xmlRelaxNG :
*
* A RelaxNGs definition
*/
struct _xmlRelaxNG {
2003-10-07 11:33:24 +00:00
void * _private ; /* unused by the library for users or bindings */
2003-01-23 18:29:16 +00:00
xmlRelaxNGGrammarPtr topgrammar ;
xmlDocPtr doc ;
2003-10-07 11:33:24 +00:00
int idref ; /* requires idref checking */
2003-03-18 00:31:04 +00:00
2003-10-07 11:33:24 +00:00
xmlHashTablePtr defs ; /* define */
xmlHashTablePtr refs ; /* references */
xmlRelaxNGDocumentPtr documents ; /* all the documents loaded */
xmlRelaxNGIncludePtr includes ; /* all the includes loaded */
int defNr ; /* number of defines used */
xmlRelaxNGDefinePtr * defTab ; /* pointer to the allocated definitions */
2003-03-18 00:31:04 +00:00
2003-01-23 18:29:16 +00:00
} ;
2003-02-20 15:03:22 +00:00
# define XML_RELAXNG_IN_ATTRIBUTE (1 << 0)
# define XML_RELAXNG_IN_ONEORMORE (1 << 1)
# define XML_RELAXNG_IN_LIST (1 << 2)
# define XML_RELAXNG_IN_DATAEXCEPT (1 << 3)
# define XML_RELAXNG_IN_START (1 << 4)
# define XML_RELAXNG_IN_OOMGROUP (1 << 5)
# define XML_RELAXNG_IN_OOMINTERLEAVE (1 << 6)
# define XML_RELAXNG_IN_EXTERNALREF (1 << 7)
2003-02-21 17:14:10 +00:00
# define XML_RELAXNG_IN_ANYEXCEPT (1 << 8)
# define XML_RELAXNG_IN_NSEXCEPT (1 << 9)
2003-01-23 18:29:16 +00:00
struct _xmlRelaxNGParserCtxt {
2003-10-07 11:33:24 +00:00
void * userData ; /* user specific data block */
xmlRelaxNGValidityErrorFunc error ; /* the callback in case of errors */
xmlRelaxNGValidityWarningFunc warning ; /* the callback in case of warning */
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc serror ;
2003-03-07 18:32:59 +00:00
xmlRelaxNGValidErr err ;
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
xmlRelaxNGPtr schema ; /* The schema in use */
xmlRelaxNGGrammarPtr grammar ; /* the current grammar */
xmlRelaxNGGrammarPtr parentgrammar ; /* the parent grammar */
int flags ; /* parser flags */
int nbErrors ; /* number of errors at parse time */
int nbWarnings ; /* number of warnings at parse time */
const xmlChar * define ; /* the current define scope */
xmlRelaxNGDefinePtr def ; /* the current define */
2003-01-28 20:58:15 +00:00
2003-10-07 11:33:24 +00:00
int nbInterleaves ;
xmlHashTablePtr interleaves ; /* keep track of all the interleaves */
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
xmlRelaxNGDocumentPtr documents ; /* all the documents loaded */
xmlRelaxNGIncludePtr includes ; /* all the includes loaded */
xmlChar * URL ;
xmlDocPtr document ;
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
int defNr ; /* number of defines used */
2019-09-30 17:04:54 +02:00
int defMax ; /* number of defines allocated */
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr * defTab ; /* pointer to the allocated definitions */
2003-02-03 23:22:49 +00:00
2003-10-07 11:33:24 +00:00
const char * buffer ;
int size ;
2003-01-23 18:29:16 +00:00
2003-01-29 21:07:52 +00:00
/* the document stack */
2003-10-07 11:33:24 +00:00
xmlRelaxNGDocumentPtr doc ; /* Current parsed external ref */
int docNr ; /* Depth of the parsing stack */
int docMax ; /* Max depth of the parsing stack */
xmlRelaxNGDocumentPtr * docTab ; /* array of docs */
2003-02-01 17:43:10 +00:00
/* the include stack */
2003-10-07 11:33:24 +00:00
xmlRelaxNGIncludePtr inc ; /* Current parsed include */
int incNr ; /* Depth of the include parsing stack */
int incMax ; /* Max depth of the parsing stack */
xmlRelaxNGIncludePtr * incTab ; /* array of incs */
2003-03-18 00:31:04 +00:00
2003-10-07 11:33:24 +00:00
int idref ; /* requires idref checking */
2003-04-13 19:53:42 +00:00
/* used to compile content models */
2003-10-07 11:33:24 +00:00
xmlAutomataPtr am ; /* the automata */
xmlAutomataStatePtr state ; /* used to build the automata */
2004-01-25 19:54:59 +00:00
int crng ; /* compact syntax and other flags */
2004-11-08 10:52:06 +00:00
int freedoc ; /* need to free the document */
2003-01-23 18:29:16 +00:00
} ;
# define FLAGS_IGNORABLE 1
# define FLAGS_NEGATIVE 2
2003-03-19 21:02:29 +00:00
# define FLAGS_MIXED_CONTENT 4
2005-09-04 13:50:03 +00:00
# define FLAGS_NOERROR 8
2003-01-23 18:29:16 +00:00
2003-01-28 20:58:15 +00:00
/**
* xmlRelaxNGInterleaveGroup :
*
* A RelaxNGs partition set associated to lists of definitions
*/
typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup ;
typedef xmlRelaxNGInterleaveGroup * xmlRelaxNGInterleaveGroupPtr ;
struct _xmlRelaxNGInterleaveGroup {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr rule ; /* the rule to satisfy */
xmlRelaxNGDefinePtr * defs ; /* the array of element definitions */
xmlRelaxNGDefinePtr * attrs ; /* the array of attributes definitions */
2003-01-28 20:58:15 +00:00
} ;
2003-03-21 01:24:45 +00:00
# define IS_DETERMINIST 1
# define IS_NEEDCHECK 2
2003-10-07 11:33:24 +00:00
2003-01-28 20:58:15 +00:00
/**
* xmlRelaxNGPartitions :
*
* A RelaxNGs partition associated to an interleave group
*/
typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition ;
typedef xmlRelaxNGPartition * xmlRelaxNGPartitionPtr ;
struct _xmlRelaxNGPartition {
2003-10-07 11:33:24 +00:00
int nbgroups ; /* number of groups in the partitions */
xmlHashTablePtr triage ; /* hash table used to direct nodes to the
* right group when possible */
int flags ; /* determinist ? */
2003-01-28 20:58:15 +00:00
xmlRelaxNGInterleaveGroupPtr * groups ;
} ;
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGValidState :
*
* A RelaxNGs validation state
*/
# define MAX_ATTR 20
typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState ;
typedef xmlRelaxNGValidState * xmlRelaxNGValidStatePtr ;
struct _xmlRelaxNGValidState {
2003-10-07 11:33:24 +00:00
xmlNodePtr node ; /* the current node */
xmlNodePtr seq ; /* the sequence of children left to validate */
int nbAttrs ; /* the number of attributes */
int maxAttrs ; /* the size of attrs */
int nbAttrLeft ; /* the number of attributes left to validate */
xmlChar * value ; /* the value when operating on string */
xmlChar * endvalue ; /* the end value when operating on string */
xmlAttrPtr * attrs ; /* the array of attributes */
2003-01-23 18:29:16 +00:00
} ;
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGStates :
*
* A RelaxNGs container for validation state
*/
typedef struct _xmlRelaxNGStates xmlRelaxNGStates ;
typedef xmlRelaxNGStates * xmlRelaxNGStatesPtr ;
struct _xmlRelaxNGStates {
2003-10-07 11:33:24 +00:00
int nbState ; /* the number of states */
int maxState ; /* the size of the array */
2003-03-16 17:52:32 +00:00
xmlRelaxNGValidStatePtr * tabState ;
} ;
2003-03-18 00:31:04 +00:00
# define ERROR_IS_DUP 1
2003-10-07 11:33:24 +00:00
2003-03-07 18:32:59 +00:00
/**
* xmlRelaxNGValidError :
*
* A RelaxNGs validation error
*/
typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError ;
typedef xmlRelaxNGValidError * xmlRelaxNGValidErrorPtr ;
struct _xmlRelaxNGValidError {
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidErr err ; /* the error number */
int flags ; /* flags */
xmlNodePtr node ; /* the current node */
xmlNodePtr seq ; /* the current child */
const xmlChar * arg1 ; /* first arg */
const xmlChar * arg2 ; /* second arg */
2003-03-07 18:32:59 +00:00
} ;
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGValidCtxt :
*
* A RelaxNGs validation context
*/
struct _xmlRelaxNGValidCtxt {
2003-10-07 11:33:24 +00:00
void * userData ; /* user specific data block */
xmlRelaxNGValidityErrorFunc error ; /* the callback in case of errors */
xmlRelaxNGValidityWarningFunc warning ; /* the callback in case of warning */
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc serror ;
2003-10-07 11:33:24 +00:00
int nbErrors ; /* number of errors in validation */
xmlRelaxNGPtr schema ; /* The schema in use */
xmlDocPtr doc ; /* the document being validated */
int flags ; /* validation flags */
int depth ; /* validation depth */
int idref ; /* requires idref checking */
int errNo ; /* the first error found */
2003-03-07 18:32:59 +00:00
/*
* Errors accumulated in branches may have to be stacked to be
* provided back when it ' s sure they affect validation .
*/
xmlRelaxNGValidErrorPtr err ; /* Last error */
2003-10-07 11:33:24 +00:00
int errNr ; /* Depth of the error stack */
int errMax ; /* Max depth of the error stack */
xmlRelaxNGValidErrorPtr errTab ; /* stack of errors */
2003-03-15 21:30:25 +00:00
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr state ; /* the current validation state */
xmlRelaxNGStatesPtr states ; /* the accumulated state list */
2003-03-19 10:36:09 +00:00
2003-10-07 11:33:24 +00:00
xmlRelaxNGStatesPtr freeState ; /* the pool of free valid states */
int freeStatesNr ;
int freeStatesMax ;
xmlRelaxNGStatesPtr * freeStates ; /* the pool of free state groups */
2003-04-15 23:32:22 +00:00
/*
* This is used for " progressive " validation
*/
2003-10-07 11:33:24 +00:00
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 */
int perr ; /* signal error in content model
* outside the regexp */
2003-01-23 18:29:16 +00:00
} ;
2003-02-01 17:43:10 +00:00
/**
* xmlRelaxNGInclude :
*
* Structure associated to a RelaxNGs document element
*/
struct _xmlRelaxNGInclude {
2003-10-07 11:33:24 +00:00
xmlRelaxNGIncludePtr next ; /* keep a chain of includes */
xmlChar * href ; /* the normalized href value */
xmlDocPtr doc ; /* the associated XML document */
xmlRelaxNGDefinePtr content ; /* the definitions */
xmlRelaxNGPtr schema ; /* the schema */
2003-02-01 17:43:10 +00:00
} ;
2003-01-29 21:07:52 +00:00
/**
* xmlRelaxNGDocument :
*
* Structure associated to a RelaxNGs document element
*/
struct _xmlRelaxNGDocument {
2003-02-26 14:48:48 +00:00
xmlRelaxNGDocumentPtr next ; /* keep a chain of documents */
2003-10-07 11:33:24 +00:00
xmlChar * href ; /* the normalized href value */
xmlDocPtr doc ; /* the associated XML document */
xmlRelaxNGDefinePtr content ; /* the definitions */
xmlRelaxNGPtr schema ; /* the schema */
2009-08-14 18:52:10 +02:00
int externalRef ; /* 1 if an external ref */
2003-01-29 21:07:52 +00:00
} ;
2003-02-24 17:17:58 +00:00
2003-10-07 11:33:24 +00:00
/************************************************************************
* *
2012-09-11 13:26:36 +08:00
* Some factorized error routines *
2003-10-07 11:33:24 +00:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlRngPErrMemory :
* @ ctxt : an Relax - NG parser context
2020-03-08 17:19:42 +01:00
* @ extra : extra information
2003-10-07 11:33:24 +00:00
*
* Handle a redefinition of attribute error
*/
static void
xmlRngPErrMemory ( xmlRelaxNGParserCtxtPtr ctxt , const char * extra )
{
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-07 11:33:24 +00:00
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
2005-09-04 13:50:03 +00:00
if ( ctxt - > serror ! = NULL )
schannel = ctxt - > serror ;
else
channel = ctxt - > error ;
2003-10-07 11:33:24 +00:00
data = ctxt - > userData ;
ctxt - > nbErrors + + ;
}
if ( extra )
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data ,
2003-10-07 11:33:24 +00:00
NULL , NULL , XML_FROM_RELAXNGP ,
XML_ERR_NO_MEMORY , XML_ERR_FATAL , NULL , 0 , extra ,
NULL , NULL , 0 , 0 ,
" Memory allocation failed : %s \n " , extra ) ;
else
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data ,
2003-10-07 11:33:24 +00:00
NULL , NULL , XML_FROM_RELAXNGP ,
XML_ERR_NO_MEMORY , XML_ERR_FATAL , NULL , 0 , NULL ,
NULL , NULL , 0 , 0 , " Memory allocation failed \n " ) ;
}
/**
* xmlRngVErrMemory :
* @ ctxt : a Relax - NG validation context
2020-03-08 17:19:42 +01:00
* @ extra : extra information
2003-10-07 11:33:24 +00:00
*
* Handle a redefinition of attribute error
*/
static void
xmlRngVErrMemory ( xmlRelaxNGValidCtxtPtr ctxt , const char * extra )
{
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-07 11:33:24 +00:00
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
2005-09-04 13:50:03 +00:00
if ( ctxt - > serror ! = NULL )
schannel = ctxt - > serror ;
else
channel = ctxt - > error ;
2003-10-07 11:33:24 +00:00
data = ctxt - > userData ;
ctxt - > nbErrors + + ;
}
if ( extra )
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data ,
2003-10-07 11:33:24 +00:00
NULL , NULL , XML_FROM_RELAXNGV ,
XML_ERR_NO_MEMORY , XML_ERR_FATAL , NULL , 0 , extra ,
NULL , NULL , 0 , 0 ,
" Memory allocation failed : %s \n " , extra ) ;
else
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data ,
2003-10-07 11:33:24 +00:00
NULL , NULL , XML_FROM_RELAXNGV ,
XML_ERR_NO_MEMORY , XML_ERR_FATAL , NULL , 0 , NULL ,
NULL , NULL , 0 , 0 , " Memory allocation failed \n " ) ;
}
/**
* xmlRngPErr :
* @ ctxt : a Relax - NG parser context
* @ node : the node raising the error
* @ error : the error code
* @ msg : message
* @ str1 : extra info
* @ str2 : extra info
*
* Handle a Relax NG Parsing error
*/
2016-05-13 15:13:17 +08:00
static void LIBXML_ATTR_FORMAT ( 4 , 0 )
2003-10-07 11:33:24 +00:00
xmlRngPErr ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node , int error ,
const char * msg , const xmlChar * str1 , const xmlChar * str2 )
{
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-07 11:33:24 +00:00
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
2005-09-04 13:50:03 +00:00
if ( ctxt - > serror ! = NULL )
schannel = ctxt - > serror ;
else
channel = ctxt - > error ;
2003-10-07 11:33:24 +00:00
data = ctxt - > userData ;
ctxt - > nbErrors + + ;
}
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data ,
2003-10-07 11:33:24 +00:00
NULL , node , XML_FROM_RELAXNGP ,
error , XML_ERR_ERROR , NULL , 0 ,
( const char * ) str1 , ( const char * ) str2 , NULL , 0 , 0 ,
msg , str1 , str2 ) ;
}
/**
* xmlRngVErr :
* @ ctxt : a Relax - NG validation context
* @ node : the node raising the error
* @ error : the error code
* @ msg : message
* @ str1 : extra info
* @ str2 : extra info
*
* Handle a Relax NG Validation error
*/
2016-05-13 15:13:17 +08:00
static void LIBXML_ATTR_FORMAT ( 4 , 0 )
2003-10-07 11:33:24 +00:00
xmlRngVErr ( xmlRelaxNGValidCtxtPtr ctxt , xmlNodePtr node , int error ,
const char * msg , const xmlChar * str1 , const xmlChar * str2 )
{
2003-10-10 14:10:40 +00:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-07 11:33:24 +00:00
xmlGenericErrorFunc channel = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
2005-09-04 13:50:03 +00:00
if ( ctxt - > serror ! = NULL )
schannel = ctxt - > serror ;
else
channel = ctxt - > error ;
2003-10-07 11:33:24 +00:00
data = ctxt - > userData ;
ctxt - > nbErrors + + ;
}
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( schannel , channel , data ,
2003-10-07 11:33:24 +00:00
NULL , node , XML_FROM_RELAXNGV ,
error , XML_ERR_ERROR , NULL , 0 ,
( const char * ) str1 , ( const char * ) str2 , NULL , 0 , 0 ,
msg , str1 , str2 ) ;
}
2003-01-25 18:01:32 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Preliminary type checking interfaces *
* *
2003-01-25 18:01:32 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGTypeHave :
* @ data : data needed for the library
* @ type : the type name
* @ value : the value to check
*
* Function provided by a type library to check if a type is exported
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
2003-10-07 11:33:24 +00:00
typedef int ( * xmlRelaxNGTypeHave ) ( void * data , const xmlChar * type ) ;
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGTypeCheck :
* @ data : data needed for the library
* @ type : the type name
* @ value : the value to check
2003-02-27 17:42:22 +00:00
* @ result : place to store the result if needed
2003-01-25 18:01:32 +00:00
*
* Function provided by a type library to check if a value match a type
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
2003-10-07 11:33:24 +00:00
typedef int ( * xmlRelaxNGTypeCheck ) ( void * data , const xmlChar * type ,
const xmlChar * value , void * * result ,
xmlNodePtr node ) ;
2003-02-27 17:42:22 +00:00
/**
* xmlRelaxNGFacetCheck :
* @ data : data needed for the library
* @ type : the type name
* @ facet : the facet name
* @ val : the facet value
* @ strval : the string value
* @ value : the value to check
*
* Function provided by a type library to check a value facet
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
2003-10-07 11:33:24 +00:00
typedef int ( * xmlRelaxNGFacetCheck ) ( void * data , const xmlChar * type ,
const xmlChar * facet ,
const xmlChar * val ,
const xmlChar * strval , void * value ) ;
2003-02-27 17:42:22 +00:00
/**
* xmlRelaxNGTypeFree :
* @ data : data needed for the library
* @ result : the value to free
*
* Function provided by a type library to free a returned result
*/
typedef void ( * xmlRelaxNGTypeFree ) ( void * data , void * result ) ;
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGTypeCompare :
* @ data : data needed for the library
* @ type : the type name
* @ value1 : the first value
* @ value2 : the second value
*
* Function provided by a type library to compare two values accordingly
* to a type .
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
2003-10-07 11:33:24 +00:00
typedef int ( * xmlRelaxNGTypeCompare ) ( void * data , const xmlChar * type ,
const xmlChar * value1 ,
xmlNodePtr ctxt1 ,
void * comp1 ,
const xmlChar * value2 ,
xmlNodePtr ctxt2 ) ;
2003-01-25 18:01:32 +00:00
typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary ;
typedef xmlRelaxNGTypeLibrary * xmlRelaxNGTypeLibraryPtr ;
struct _xmlRelaxNGTypeLibrary {
2003-10-07 11:33:24 +00:00
const xmlChar * namespace ; /* the datatypeLibrary value */
void * data ; /* data needed for the library */
xmlRelaxNGTypeHave have ; /* the export function */
xmlRelaxNGTypeCheck check ; /* the checking function */
xmlRelaxNGTypeCompare comp ; /* the compare function */
xmlRelaxNGFacetCheck facet ; /* the facet check function */
xmlRelaxNGTypeFree freef ; /* the freeing function */
2003-01-25 18:01:32 +00:00
} ;
2003-01-23 18:29:16 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Allocation functions *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void xmlRelaxNGFreeGrammar ( xmlRelaxNGGrammarPtr grammar ) ;
static void xmlRelaxNGFreeDefine ( xmlRelaxNGDefinePtr define ) ;
2003-10-07 11:33:24 +00:00
static void xmlRelaxNGNormExtSpace ( xmlChar * value ) ;
2003-02-26 14:48:48 +00:00
static void xmlRelaxNGFreeInnerSchema ( xmlRelaxNGPtr schema ) ;
2003-10-07 11:33:24 +00:00
static int xmlRelaxNGEqualValidState ( xmlRelaxNGValidCtxtPtr ctxt
ATTRIBUTE_UNUSED ,
xmlRelaxNGValidStatePtr state1 ,
xmlRelaxNGValidStatePtr state2 ) ;
2003-03-19 10:36:09 +00:00
static void xmlRelaxNGFreeValidState ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr state ) ;
2003-01-23 18:29:16 +00:00
2003-01-29 21:07:52 +00:00
/**
* xmlRelaxNGFreeDocument :
* @ docu : a document structure
*
* Deallocate a RelaxNG document structure .
*/
static void
xmlRelaxNGFreeDocument ( xmlRelaxNGDocumentPtr docu )
{
if ( docu = = NULL )
return ;
if ( docu - > href ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( docu - > href ) ;
2003-01-29 21:07:52 +00:00
if ( docu - > doc ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFreeDoc ( docu - > doc ) ;
2003-01-29 21:07:52 +00:00
if ( docu - > schema ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeInnerSchema ( docu - > schema ) ;
2003-01-29 21:07:52 +00:00
xmlFree ( docu ) ;
}
2003-02-26 14:48:48 +00:00
/**
* xmlRelaxNGFreeDocumentList :
* @ docu : a list of document structure
*
* Deallocate a RelaxNG document structures .
*/
static void
xmlRelaxNGFreeDocumentList ( xmlRelaxNGDocumentPtr docu )
{
xmlRelaxNGDocumentPtr next ;
2003-10-07 11:33:24 +00:00
2003-02-26 14:48:48 +00:00
while ( docu ! = NULL ) {
2003-10-07 11:33:24 +00:00
next = docu - > next ;
xmlRelaxNGFreeDocument ( docu ) ;
docu = next ;
2003-02-26 14:48:48 +00:00
}
}
2003-02-01 17:43:10 +00:00
/**
* xmlRelaxNGFreeInclude :
* @ incl : a include structure
*
* Deallocate a RelaxNG include structure .
*/
static void
xmlRelaxNGFreeInclude ( xmlRelaxNGIncludePtr incl )
{
if ( incl = = NULL )
return ;
if ( incl - > href ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( incl - > href ) ;
2003-02-01 17:43:10 +00:00
if ( incl - > doc ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFreeDoc ( incl - > doc ) ;
2003-02-01 17:43:10 +00:00
if ( incl - > schema ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFree ( incl - > schema ) ;
2003-02-01 17:43:10 +00:00
xmlFree ( incl ) ;
}
2003-02-26 14:48:48 +00:00
/**
* xmlRelaxNGFreeIncludeList :
* @ incl : a include structure list
*
* Deallocate a RelaxNG include structure .
*/
static void
xmlRelaxNGFreeIncludeList ( xmlRelaxNGIncludePtr incl )
{
xmlRelaxNGIncludePtr next ;
2003-10-07 11:33:24 +00:00
2003-02-26 14:48:48 +00:00
while ( incl ! = NULL ) {
2003-10-07 11:33:24 +00:00
next = incl - > next ;
xmlRelaxNGFreeInclude ( incl ) ;
incl = next ;
2003-02-26 14:48:48 +00:00
}
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGNewRelaxNG :
* @ ctxt : a Relax - NG validation context ( optional )
*
* Allocate a new RelaxNG structure .
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlRelaxNGPtr
xmlRelaxNGNewRelaxNG ( xmlRelaxNGParserCtxtPtr ctxt )
{
xmlRelaxNGPtr ret ;
ret = ( xmlRelaxNGPtr ) xmlMalloc ( sizeof ( xmlRelaxNG ) ) ;
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , NULL ) ;
2003-01-23 18:29:16 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNG ) ) ;
return ( ret ) ;
}
2003-02-26 14:48:48 +00:00
/**
* xmlRelaxNGFreeInnerSchema :
* @ schema : a schema structure
*
* Deallocate a RelaxNG schema structure .
*/
static void
xmlRelaxNGFreeInnerSchema ( xmlRelaxNGPtr schema )
{
if ( schema = = NULL )
return ;
if ( schema - > doc ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFreeDoc ( schema - > doc ) ;
2003-02-26 14:48:48 +00:00
if ( schema - > defTab ! = NULL ) {
2003-10-07 11:33:24 +00:00
int i ;
2003-02-26 14:48:48 +00:00
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < schema - > defNr ; i + + )
xmlRelaxNGFreeDefine ( schema - > defTab [ i ] ) ;
xmlFree ( schema - > defTab ) ;
2003-02-26 14:48:48 +00:00
}
xmlFree ( schema ) ;
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGFree :
* @ schema : a schema structure
*
* Deallocate a RelaxNG structure .
*/
void
xmlRelaxNGFree ( xmlRelaxNGPtr schema )
{
if ( schema = = NULL )
return ;
if ( schema - > topgrammar ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeGrammar ( schema - > topgrammar ) ;
2003-01-23 18:29:16 +00:00
if ( schema - > doc ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFreeDoc ( schema - > doc ) ;
2003-01-29 21:07:52 +00:00
if ( schema - > documents ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeDocumentList ( schema - > documents ) ;
2003-02-01 17:43:10 +00:00
if ( schema - > includes ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeIncludeList ( schema - > includes ) ;
2003-02-03 23:22:49 +00:00
if ( schema - > defTab ! = NULL ) {
2003-10-07 11:33:24 +00:00
int i ;
2003-02-03 23:22:49 +00:00
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < schema - > defNr ; i + + )
xmlRelaxNGFreeDefine ( schema - > defTab [ i ] ) ;
xmlFree ( schema - > defTab ) ;
2003-02-03 23:22:49 +00:00
}
2003-01-23 18:29:16 +00:00
xmlFree ( schema ) ;
}
/**
* xmlRelaxNGNewGrammar :
* @ ctxt : a Relax - NG validation context ( optional )
*
* Allocate a new RelaxNG grammar .
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlRelaxNGGrammarPtr
xmlRelaxNGNewGrammar ( xmlRelaxNGParserCtxtPtr ctxt )
{
xmlRelaxNGGrammarPtr ret ;
ret = ( xmlRelaxNGGrammarPtr ) xmlMalloc ( sizeof ( xmlRelaxNGGrammar ) ) ;
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , NULL ) ;
2003-01-23 18:29:16 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGGrammar ) ) ;
return ( ret ) ;
}
/**
* xmlRelaxNGFreeGrammar :
* @ grammar : a grammar structure
*
* Deallocate a RelaxNG grammar structure .
*/
static void
xmlRelaxNGFreeGrammar ( xmlRelaxNGGrammarPtr grammar )
{
if ( grammar = = NULL )
return ;
2003-02-26 14:48:48 +00:00
if ( grammar - > children ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeGrammar ( grammar - > children ) ;
2003-02-26 14:48:48 +00:00
}
2003-02-03 23:22:49 +00:00
if ( grammar - > next ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeGrammar ( grammar - > next ) ;
2003-02-03 23:22:49 +00:00
}
2003-01-23 18:29:16 +00:00
if ( grammar - > refs ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlHashFree ( grammar - > refs , NULL ) ;
2003-01-23 18:29:16 +00:00
}
if ( grammar - > defs ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlHashFree ( grammar - > defs , NULL ) ;
2003-01-23 18:29:16 +00:00
}
xmlFree ( grammar ) ;
}
/**
* xmlRelaxNGNewDefine :
* @ ctxt : a Relax - NG validation context
* @ node : the node in the input document .
*
* Allocate a new RelaxNG define .
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlRelaxNGDefinePtr
2003-03-16 17:52:32 +00:00
xmlRelaxNGNewDefine ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
2003-01-23 18:29:16 +00:00
{
xmlRelaxNGDefinePtr ret ;
2003-02-03 23:22:49 +00:00
if ( ctxt - > defMax = = 0 ) {
2003-10-07 11:33:24 +00:00
ctxt - > defMax = 16 ;
ctxt - > defNr = 0 ;
ctxt - > defTab = ( xmlRelaxNGDefinePtr * )
xmlMalloc ( ctxt - > defMax * sizeof ( xmlRelaxNGDefinePtr ) ) ;
if ( ctxt - > defTab = = NULL ) {
xmlRngPErrMemory ( ctxt , " allocating define \n " ) ;
return ( NULL ) ;
}
2003-02-03 23:22:49 +00:00
} else if ( ctxt - > defMax < = ctxt - > defNr ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr * tmp ;
ctxt - > defMax * = 2 ;
tmp = ( xmlRelaxNGDefinePtr * ) xmlRealloc ( ctxt - > defTab ,
ctxt - > defMax *
sizeof
( xmlRelaxNGDefinePtr ) ) ;
if ( tmp = = NULL ) {
xmlRngPErrMemory ( ctxt , " allocating define \n " ) ;
return ( NULL ) ;
}
ctxt - > defTab = tmp ;
2003-02-03 23:22:49 +00:00
}
2003-01-23 18:29:16 +00:00
ret = ( xmlRelaxNGDefinePtr ) xmlMalloc ( sizeof ( xmlRelaxNGDefine ) ) ;
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " allocating define \n " ) ;
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
}
memset ( ret , 0 , sizeof ( xmlRelaxNGDefine ) ) ;
2003-02-03 23:22:49 +00:00
ctxt - > defTab [ ctxt - > defNr + + ] = ret ;
2003-01-23 18:29:16 +00:00
ret - > node = node ;
2003-02-18 21:12:46 +00:00
ret - > depth = - 1 ;
2003-01-23 18:29:16 +00:00
return ( ret ) ;
}
2003-01-28 20:58:15 +00:00
/**
* xmlRelaxNGFreePartition :
* @ partitions : a partition set structure
*
* Deallocate RelaxNG partition set structures .
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreePartition ( xmlRelaxNGPartitionPtr partitions )
{
2003-01-28 20:58:15 +00:00
xmlRelaxNGInterleaveGroupPtr group ;
int j ;
if ( partitions ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( partitions - > groups ! = NULL ) {
for ( j = 0 ; j < partitions - > nbgroups ; j + + ) {
group = partitions - > groups [ j ] ;
if ( group ! = NULL ) {
if ( group - > defs ! = NULL )
xmlFree ( group - > defs ) ;
if ( group - > attrs ! = NULL )
xmlFree ( group - > attrs ) ;
xmlFree ( group ) ;
}
}
xmlFree ( partitions - > groups ) ;
}
if ( partitions - > triage ! = NULL ) {
xmlHashFree ( partitions - > triage , NULL ) ;
}
xmlFree ( partitions ) ;
2003-01-28 20:58:15 +00:00
}
}
2003-10-07 11:33:24 +00:00
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGFreeDefine :
* @ define : a define structure
*
* Deallocate a RelaxNG define structure .
*/
static void
xmlRelaxNGFreeDefine ( xmlRelaxNGDefinePtr define )
{
if ( define = = NULL )
return ;
2003-10-07 11:33:24 +00:00
if ( ( define - > type = = XML_RELAXNG_VALUE ) & & ( define - > attrs ! = NULL ) ) {
xmlRelaxNGTypeLibraryPtr lib ;
2003-03-30 21:10:09 +00:00
2003-10-07 11:33:24 +00:00
lib = ( xmlRelaxNGTypeLibraryPtr ) define - > data ;
if ( ( lib ! = NULL ) & & ( lib - > freef ! = NULL ) )
lib - > freef ( lib - > data , ( void * ) define - > attrs ) ;
2003-03-30 21:10:09 +00:00
}
2003-10-07 11:33:24 +00:00
if ( ( define - > data ! = NULL ) & & ( define - > type = = XML_RELAXNG_INTERLEAVE ) )
xmlRelaxNGFreePartition ( ( xmlRelaxNGPartitionPtr ) define - > data ) ;
if ( ( define - > data ! = NULL ) & & ( define - > type = = XML_RELAXNG_CHOICE ) )
xmlHashFree ( ( xmlHashTablePtr ) define - > data , NULL ) ;
2003-01-23 18:29:16 +00:00
if ( define - > name ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( define - > name ) ;
2003-01-23 18:29:16 +00:00
if ( define - > ns ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( define - > ns ) ;
2003-01-26 00:52:04 +00:00
if ( define - > value ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( define - > value ) ;
2003-04-13 19:53:42 +00:00
if ( define - > contModel ! = NULL )
xmlRegFreeRegexp ( define - > contModel ) ;
2003-01-23 18:29:16 +00:00
xmlFree ( define ) ;
}
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGNewStates :
* @ ctxt : a Relax - NG validation context
* @ size : the default size for the container
*
* Allocate a new RelaxNG validation state container
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlRelaxNGStatesPtr
xmlRelaxNGNewStates ( xmlRelaxNGValidCtxtPtr ctxt , int size )
{
xmlRelaxNGStatesPtr ret ;
2003-03-19 10:36:09 +00:00
if ( ( ctxt ! = NULL ) & &
2009-08-14 16:16:31 +02:00
( ctxt - > freeStates ! = NULL ) & & ( ctxt - > freeStatesNr > 0 ) ) {
2003-10-07 11:33:24 +00:00
ctxt - > freeStatesNr - - ;
ret = ctxt - > freeStates [ ctxt - > freeStatesNr ] ;
ret - > nbState = 0 ;
return ( ret ) ;
2003-03-19 10:36:09 +00:00
}
2003-10-07 11:33:24 +00:00
if ( size < 16 )
size = 16 ;
2003-03-16 17:52:32 +00:00
ret = ( xmlRelaxNGStatesPtr ) xmlMalloc ( sizeof ( xmlRelaxNGStates ) +
2003-10-07 11:33:24 +00:00
( size -
1 ) *
sizeof ( xmlRelaxNGValidStatePtr ) ) ;
2003-03-16 17:52:32 +00:00
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
2003-03-16 17:52:32 +00:00
return ( NULL ) ;
}
ret - > nbState = 0 ;
ret - > maxState = size ;
2003-10-07 11:33:24 +00:00
ret - > tabState = ( xmlRelaxNGValidStatePtr * ) xmlMalloc ( ( size ) *
sizeof
( xmlRelaxNGValidStatePtr ) ) ;
2003-03-16 17:52:32 +00:00
if ( ret - > tabState = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
xmlFree ( ret ) ;
2003-03-16 17:52:32 +00:00
return ( NULL ) ;
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-03-16 17:52:32 +00:00
}
2003-03-19 10:36:09 +00:00
/**
* xmlRelaxNGAddStateUniq :
* @ ctxt : a Relax - NG validation context
* @ states : the states container
* @ state : the validation state
*
* Add a RelaxNG validation state to the container without checking
* for unicity .
*
* Return 1 in case of success and 0 if this is a duplicate and - 1 on error
*/
static int
xmlRelaxNGAddStatesUniq ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGStatesPtr states ,
xmlRelaxNGValidStatePtr state )
2003-03-19 10:36:09 +00:00
{
if ( state = = NULL ) {
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-19 10:36:09 +00:00
}
if ( states - > nbState > = states - > maxState ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr * tmp ;
int size ;
size = states - > maxState * 2 ;
tmp = ( xmlRelaxNGValidStatePtr * ) xmlRealloc ( states - > tabState ,
( size ) *
sizeof
( xmlRelaxNGValidStatePtr ) ) ;
2003-03-19 10:36:09 +00:00
if ( tmp = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " adding states \n " ) ;
return ( - 1 ) ;
}
states - > tabState = tmp ;
states - > maxState = size ;
2003-03-19 10:36:09 +00:00
}
states - > tabState [ states - > nbState + + ] = state ;
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-03-19 10:36:09 +00:00
}
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGAddState :
* @ ctxt : a Relax - NG validation context
* @ states : the states container
* @ state : the validation state
*
* Add a RelaxNG validation state to the container
*
* Return 1 in case of success and 0 if this is a duplicate and - 1 on error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGAddStates ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGStatesPtr states ,
xmlRelaxNGValidStatePtr state )
2003-03-16 17:52:32 +00:00
{
int i ;
2014-07-14 16:08:28 +08:00
if ( state = = NULL | | states = = NULL ) {
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-16 17:52:32 +00:00
}
if ( states - > nbState > = states - > maxState ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr * tmp ;
int size ;
size = states - > maxState * 2 ;
tmp = ( xmlRelaxNGValidStatePtr * ) xmlRealloc ( states - > tabState ,
( size ) *
sizeof
( xmlRelaxNGValidStatePtr ) ) ;
2003-03-16 17:52:32 +00:00
if ( tmp = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " adding states \n " ) ;
return ( - 1 ) ;
}
states - > tabState = tmp ;
states - > maxState = size ;
}
for ( i = 0 ; i < states - > nbState ; i + + ) {
if ( xmlRelaxNGEqualValidState ( ctxt , state , states - > tabState [ i ] ) ) {
xmlRelaxNGFreeValidState ( ctxt , state ) ;
return ( 0 ) ;
}
2003-03-16 17:52:32 +00:00
}
states - > tabState [ states - > nbState + + ] = state ;
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-03-16 17:52:32 +00:00
}
/**
* xmlRelaxNGFreeStates :
* @ ctxt : a Relax - NG validation context
2019-09-30 17:04:54 +02:00
* @ states : the container
2003-03-16 17:52:32 +00:00
*
* Free a RelaxNG validation state container
*/
static void
2003-03-19 10:36:09 +00:00
xmlRelaxNGFreeStates ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGStatesPtr states )
2003-03-16 17:52:32 +00:00
{
2003-03-19 10:36:09 +00:00
if ( states = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-03-19 10:36:09 +00:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > freeStates = = NULL ) ) {
2003-10-07 11:33:24 +00:00
ctxt - > freeStatesMax = 40 ;
ctxt - > freeStatesNr = 0 ;
ctxt - > freeStates = ( xmlRelaxNGStatesPtr * )
xmlMalloc ( ctxt - > freeStatesMax * sizeof ( xmlRelaxNGStatesPtr ) ) ;
if ( ctxt - > freeStates = = NULL ) {
xmlRngVErrMemory ( ctxt , " storing states \n " ) ;
}
} else if ( ( ctxt ! = NULL )
& & ( ctxt - > freeStatesNr > = ctxt - > freeStatesMax ) ) {
xmlRelaxNGStatesPtr * tmp ;
tmp = ( xmlRelaxNGStatesPtr * ) xmlRealloc ( ctxt - > freeStates ,
2 * ctxt - > freeStatesMax *
sizeof
( xmlRelaxNGStatesPtr ) ) ;
if ( tmp = = NULL ) {
xmlRngVErrMemory ( ctxt , " storing states \n " ) ;
xmlFree ( states - > tabState ) ;
xmlFree ( states ) ;
return ;
}
ctxt - > freeStates = tmp ;
ctxt - > freeStatesMax * = 2 ;
2003-03-19 10:36:09 +00:00
}
2006-03-09 18:41:40 +00:00
if ( ( ctxt = = NULL ) | | ( ctxt - > freeStates = = NULL ) ) {
2003-10-07 11:33:24 +00:00
xmlFree ( states - > tabState ) ;
xmlFree ( states ) ;
2003-03-19 10:36:09 +00:00
} else {
2003-10-07 11:33:24 +00:00
ctxt - > freeStates [ ctxt - > freeStatesNr + + ] = states ;
2003-03-16 17:52:32 +00:00
}
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGNewValidState :
* @ ctxt : a Relax - NG validation context
* @ node : the current node or NULL for the document
*
* Allocate a new RelaxNG validation state
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlRelaxNGValidStatePtr
xmlRelaxNGNewValidState ( xmlRelaxNGValidCtxtPtr ctxt , xmlNodePtr node )
{
xmlRelaxNGValidStatePtr ret ;
xmlAttrPtr attr ;
xmlAttrPtr attrs [ MAX_ATTR ] ;
int nbAttrs = 0 ;
xmlNodePtr root = NULL ;
if ( node = = NULL ) {
2003-10-07 11:33:24 +00:00
root = xmlDocGetRootElement ( ctxt - > doc ) ;
if ( root = = NULL )
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
} else {
2003-10-07 11:33:24 +00:00
attr = node - > properties ;
while ( attr ! = NULL ) {
if ( nbAttrs < MAX_ATTR )
attrs [ nbAttrs + + ] = attr ;
else
nbAttrs + + ;
attr = attr - > next ;
}
}
if ( ( ctxt - > freeState ! = NULL ) & & ( ctxt - > freeState - > nbState > 0 ) ) {
ctxt - > freeState - > nbState - - ;
ret = ctxt - > freeState - > tabState [ ctxt - > freeState - > nbState ] ;
2003-03-19 10:36:09 +00:00
} else {
2003-10-07 11:33:24 +00:00
ret =
( xmlRelaxNGValidStatePtr )
xmlMalloc ( sizeof ( xmlRelaxNGValidState ) ) ;
if ( ret = = NULL ) {
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGValidState ) ) ;
2003-01-23 18:29:16 +00:00
}
2003-02-04 14:43:39 +00:00
ret - > value = NULL ;
ret - > endvalue = NULL ;
2003-01-23 18:29:16 +00:00
if ( node = = NULL ) {
2003-10-07 11:33:24 +00:00
ret - > node = ( xmlNodePtr ) ctxt - > doc ;
ret - > seq = root ;
2003-01-23 18:29:16 +00:00
} else {
2003-10-07 11:33:24 +00:00
ret - > node = node ;
ret - > seq = node - > children ;
2003-03-19 10:36:09 +00:00
}
ret - > nbAttrs = 0 ;
if ( nbAttrs > 0 ) {
2003-10-07 11:33:24 +00:00
if ( ret - > attrs = = NULL ) {
if ( nbAttrs < 4 )
ret - > maxAttrs = 4 ;
else
ret - > maxAttrs = nbAttrs ;
ret - > attrs = ( xmlAttrPtr * ) xmlMalloc ( ret - > maxAttrs *
sizeof ( xmlAttrPtr ) ) ;
if ( ret - > attrs = = NULL ) {
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
return ( ret ) ;
}
} else if ( ret - > maxAttrs < nbAttrs ) {
xmlAttrPtr * tmp ;
tmp = ( xmlAttrPtr * ) xmlRealloc ( ret - > attrs , nbAttrs *
sizeof ( xmlAttrPtr ) ) ;
if ( tmp = = NULL ) {
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
return ( ret ) ;
}
ret - > attrs = tmp ;
ret - > maxAttrs = nbAttrs ;
}
ret - > nbAttrs = nbAttrs ;
if ( nbAttrs < MAX_ATTR ) {
memcpy ( ret - > attrs , attrs , sizeof ( xmlAttrPtr ) * nbAttrs ) ;
} else {
attr = node - > properties ;
nbAttrs = 0 ;
while ( attr ! = NULL ) {
ret - > attrs [ nbAttrs + + ] = attr ;
attr = attr - > next ;
}
}
2003-01-23 18:29:16 +00:00
}
2003-02-03 10:57:45 +00:00
ret - > nbAttrLeft = ret - > nbAttrs ;
2003-01-23 18:29:16 +00:00
return ( ret ) ;
}
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGCopyValidState :
* @ ctxt : a Relax - NG validation context
* @ state : a validation state
*
* Copy the validation state
*
* Returns the newly allocated structure or NULL in case or error
*/
static xmlRelaxNGValidStatePtr
xmlRelaxNGCopyValidState ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr state )
2003-03-16 17:52:32 +00:00
{
xmlRelaxNGValidStatePtr ret ;
2003-03-19 10:36:09 +00:00
unsigned int maxAttrs ;
xmlAttrPtr * attrs ;
2003-03-16 17:52:32 +00:00
if ( state = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
if ( ( ctxt - > freeState ! = NULL ) & & ( ctxt - > freeState - > nbState > 0 ) ) {
ctxt - > freeState - > nbState - - ;
ret = ctxt - > freeState - > tabState [ ctxt - > freeState - > nbState ] ;
2003-03-19 10:36:09 +00:00
} else {
2003-10-07 11:33:24 +00:00
ret =
( xmlRelaxNGValidStatePtr )
xmlMalloc ( sizeof ( xmlRelaxNGValidState ) ) ;
if ( ret = = NULL ) {
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGValidState ) ) ;
2003-03-19 10:36:09 +00:00
}
attrs = ret - > attrs ;
maxAttrs = ret - > maxAttrs ;
memcpy ( ret , state , sizeof ( xmlRelaxNGValidState ) ) ;
ret - > attrs = attrs ;
ret - > maxAttrs = maxAttrs ;
if ( state - > nbAttrs > 0 ) {
2003-10-07 11:33:24 +00:00
if ( ret - > attrs = = NULL ) {
ret - > maxAttrs = state - > maxAttrs ;
ret - > attrs = ( xmlAttrPtr * ) xmlMalloc ( ret - > maxAttrs *
sizeof ( xmlAttrPtr ) ) ;
if ( ret - > attrs = = NULL ) {
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
ret - > nbAttrs = 0 ;
return ( ret ) ;
}
} else if ( ret - > maxAttrs < state - > nbAttrs ) {
xmlAttrPtr * tmp ;
tmp = ( xmlAttrPtr * ) xmlRealloc ( ret - > attrs , state - > maxAttrs *
sizeof ( xmlAttrPtr ) ) ;
if ( tmp = = NULL ) {
xmlRngVErrMemory ( ctxt , " allocating states \n " ) ;
ret - > nbAttrs = 0 ;
return ( ret ) ;
}
ret - > maxAttrs = state - > maxAttrs ;
ret - > attrs = tmp ;
}
memcpy ( ret - > attrs , state - > attrs ,
state - > nbAttrs * sizeof ( xmlAttrPtr ) ) ;
}
return ( ret ) ;
2003-03-16 17:52:32 +00:00
}
/**
* xmlRelaxNGEqualValidState :
* @ ctxt : a Relax - NG validation context
* @ state1 : a validation state
* @ state2 : a validation state
*
* Compare the validation states for equality
*
2019-09-30 17:04:54 +02:00
* Returns 1 if equal , 0 otherwise
2003-03-16 17:52:32 +00:00
*/
static int
xmlRelaxNGEqualValidState ( xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr state1 ,
xmlRelaxNGValidStatePtr state2 )
2003-03-16 17:52:32 +00:00
{
int i ;
if ( ( state1 = = NULL ) | | ( state2 = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
if ( state1 = = state2 )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-03-16 17:52:32 +00:00
if ( state1 - > node ! = state2 - > node )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
if ( state1 - > seq ! = state2 - > seq )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
if ( state1 - > nbAttrLeft ! = state2 - > nbAttrLeft )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
if ( state1 - > nbAttrs ! = state2 - > nbAttrs )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
if ( state1 - > endvalue ! = state2 - > endvalue )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
if ( ( state1 - > value ! = state2 - > value ) & &
2003-10-07 11:33:24 +00:00
( ! xmlStrEqual ( state1 - > value , state2 - > value ) ) )
return ( 0 ) ;
for ( i = 0 ; i < state1 - > nbAttrs ; i + + ) {
if ( state1 - > attrs [ i ] ! = state2 - > attrs [ i ] )
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-03-16 17:52:32 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGFreeValidState :
* @ state : a validation state structure
*
* Deallocate a RelaxNG validation state structure .
*/
static void
2003-03-19 10:36:09 +00:00
xmlRelaxNGFreeValidState ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr state )
2003-01-23 18:29:16 +00:00
{
if ( state = = NULL )
return ;
2003-03-19 10:36:09 +00:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > freeState = = NULL ) ) {
2003-10-07 11:33:24 +00:00
ctxt - > freeState = xmlRelaxNGNewStates ( ctxt , 40 ) ;
2003-03-19 10:36:09 +00:00
}
if ( ( ctxt = = NULL ) | | ( ctxt - > freeState = = NULL ) ) {
2003-10-07 11:33:24 +00:00
if ( state - > attrs ! = NULL )
xmlFree ( state - > attrs ) ;
xmlFree ( state ) ;
2003-03-19 10:36:09 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRelaxNGAddStatesUniq ( ctxt , ctxt - > freeState , state ) ;
2003-03-19 10:36:09 +00:00
}
2003-01-23 18:29:16 +00:00
}
2003-01-29 21:07:52 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Semi internal functions *
* *
2004-01-25 19:54:59 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlRelaxParserSetFlag :
* @ ctxt : a RelaxNG parser context
* @ flags : a set of flags values
*
2020-03-08 17:19:42 +01:00
* Semi private function used to pass information to a parser context
2004-01-25 19:54:59 +00:00
* which are a combination of xmlRelaxNGParserFlag .
*
* Returns 0 if success and - 1 in case of error
*/
int
xmlRelaxParserSetFlag ( xmlRelaxNGParserCtxtPtr ctxt , int flags )
{
if ( ctxt = = NULL ) return ( - 1 ) ;
if ( flags & XML_RELAXNGP_FREE_DOC ) {
ctxt - > crng | = XML_RELAXNGP_FREE_DOC ;
flags - = XML_RELAXNGP_FREE_DOC ;
}
if ( flags & XML_RELAXNGP_CRNG ) {
ctxt - > crng | = XML_RELAXNGP_CRNG ;
flags - = XML_RELAXNGP_CRNG ;
}
if ( flags ! = 0 ) return ( - 1 ) ;
return ( 0 ) ;
}
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Document functions *
* *
2003-01-29 21:07:52 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static xmlDocPtr xmlRelaxNGCleanupDoc ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlDocPtr doc ) ;
2003-01-29 21:07:52 +00:00
2003-02-01 17:43:10 +00:00
/**
* xmlRelaxNGIncludePush :
* @ ctxt : the parser context
* @ value : the element doc
*
* Pushes a new include on top of the include stack
*
* Returns 0 in case of error , the index in the stack otherwise
*/
static int
xmlRelaxNGIncludePush ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGIncludePtr value )
2003-02-01 17:43:10 +00:00
{
if ( ctxt - > incTab = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > incMax = 4 ;
ctxt - > incNr = 0 ;
ctxt - > incTab =
( xmlRelaxNGIncludePtr * ) xmlMalloc ( ctxt - > incMax *
sizeof ( ctxt - > incTab [ 0 ] ) ) ;
2003-02-01 17:43:10 +00:00
if ( ctxt - > incTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " allocating include \n " ) ;
2003-02-01 17:43:10 +00:00
return ( 0 ) ;
}
}
if ( ctxt - > incNr > = ctxt - > incMax ) {
ctxt - > incMax * = 2 ;
ctxt - > incTab =
( xmlRelaxNGIncludePtr * ) xmlRealloc ( ctxt - > incTab ,
2003-10-07 11:33:24 +00:00
ctxt - > incMax *
sizeof ( ctxt - > incTab [ 0 ] ) ) ;
2003-02-01 17:43:10 +00:00
if ( ctxt - > incTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " allocating include \n " ) ;
2003-02-01 17:43:10 +00:00
return ( 0 ) ;
}
}
ctxt - > incTab [ ctxt - > incNr ] = value ;
ctxt - > inc = value ;
return ( ctxt - > incNr + + ) ;
}
/**
* xmlRelaxNGIncludePop :
* @ ctxt : the parser context
*
* Pops the top include from the include stack
*
* Returns the include just removed
*/
static xmlRelaxNGIncludePtr
xmlRelaxNGIncludePop ( xmlRelaxNGParserCtxtPtr ctxt )
{
xmlRelaxNGIncludePtr ret ;
if ( ctxt - > incNr < = 0 )
2005-07-28 23:49:35 +00:00
return ( NULL ) ;
2003-02-01 17:43:10 +00:00
ctxt - > incNr - - ;
if ( ctxt - > incNr > 0 )
ctxt - > inc = ctxt - > incTab [ ctxt - > incNr - 1 ] ;
else
ctxt - > inc = NULL ;
ret = ctxt - > incTab [ ctxt - > incNr ] ;
2005-07-28 23:49:35 +00:00
ctxt - > incTab [ ctxt - > incNr ] = NULL ;
2003-02-01 17:43:10 +00:00
return ( ret ) ;
}
2003-03-10 13:13:58 +00:00
/**
* xmlRelaxNGRemoveRedefine :
* @ ctxt : the parser context
* @ URL : the normalized URL
* @ target : the included target
* @ name : the define name to eliminate
*
* Applies the elimination algorithm of 4.7
*
* Returns 0 in case of error , 1 in case of success .
*/
static int
xmlRelaxNGRemoveRedefine ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
const xmlChar * URL ATTRIBUTE_UNUSED ,
xmlNodePtr target , const xmlChar * name )
{
2003-03-10 13:13:58 +00:00
int found = 0 ;
xmlNodePtr tmp , tmp2 ;
xmlChar * name2 ;
# ifdef DEBUG_INCLUDE
2003-03-17 15:37:12 +00:00
if ( name = = NULL )
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Elimination of <include> start from %s \n " , URL ) ;
2003-03-17 15:37:12 +00:00
else
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Elimination of <include> define %s from %s \n " ,
name , URL ) ;
2003-03-10 13:13:58 +00:00
# endif
tmp = target ;
while ( tmp ! = NULL ) {
2003-10-07 11:33:24 +00:00
tmp2 = tmp - > next ;
if ( ( name = = NULL ) & & ( IS_RELAXNG ( tmp , " start " ) ) ) {
found = 1 ;
xmlUnlinkNode ( tmp ) ;
xmlFreeNode ( tmp ) ;
} else if ( ( name ! = NULL ) & & ( IS_RELAXNG ( tmp , " define " ) ) ) {
name2 = xmlGetProp ( tmp , BAD_CAST " name " ) ;
xmlRelaxNGNormExtSpace ( name2 ) ;
if ( name2 ! = NULL ) {
if ( xmlStrEqual ( name , name2 ) ) {
found = 1 ;
xmlUnlinkNode ( tmp ) ;
xmlFreeNode ( tmp ) ;
}
xmlFree ( name2 ) ;
}
} else if ( IS_RELAXNG ( tmp , " include " ) ) {
xmlChar * href = NULL ;
2004-02-22 22:13:27 +00:00
xmlRelaxNGDocumentPtr inc = tmp - > psvi ;
2003-10-07 11:33:24 +00:00
if ( ( inc ! = NULL ) & & ( inc - > doc ! = NULL ) & &
( inc - > doc - > children ! = NULL ) ) {
if ( xmlStrEqual
( inc - > doc - > children - > name , BAD_CAST " grammar " ) ) {
2003-03-10 13:13:58 +00:00
# ifdef DEBUG_INCLUDE
2003-10-07 11:33:24 +00:00
href = xmlGetProp ( tmp , BAD_CAST " href " ) ;
2003-03-10 13:13:58 +00:00
# endif
2003-10-07 11:33:24 +00:00
if ( xmlRelaxNGRemoveRedefine ( ctxt , href ,
2011-08-04 10:28:59 -04:00
xmlDocGetRootElement ( inc - > doc ) - > children ,
name ) = = 1 ) {
2003-10-07 11:33:24 +00:00
found = 1 ;
}
2006-03-09 18:41:40 +00:00
# ifdef DEBUG_INCLUDE
2003-10-07 11:33:24 +00:00
if ( href ! = NULL )
xmlFree ( href ) ;
2006-03-09 18:41:40 +00:00
# endif
2003-10-07 11:33:24 +00:00
}
}
2018-10-13 00:12:12 +02:00
if ( xmlRelaxNGRemoveRedefine ( ctxt , URL , tmp - > children , name ) = = 1 ) {
found = 1 ;
}
2003-10-07 11:33:24 +00:00
}
tmp = tmp2 ;
2003-03-10 13:13:58 +00:00
}
2003-10-07 11:33:24 +00:00
return ( found ) ;
2003-03-10 13:13:58 +00:00
}
2003-02-01 17:43:10 +00:00
/**
* xmlRelaxNGLoadInclude :
* @ ctxt : the parser context
* @ URL : the normalized URL
* @ node : the include node .
2003-02-17 17:25:42 +00:00
* @ ns : the namespace passed from the context .
2003-02-01 17:43:10 +00:00
*
* 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 xmlRelaxNGIncludePtr or NULL in case of error
*/
static xmlRelaxNGIncludePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGLoadInclude ( xmlRelaxNGParserCtxtPtr ctxt , const xmlChar * URL ,
xmlNodePtr node , const xmlChar * ns )
{
2003-02-01 17:43:10 +00:00
xmlRelaxNGIncludePtr ret = NULL ;
xmlDocPtr doc ;
int i ;
2003-03-10 13:13:58 +00:00
xmlNodePtr root , cur ;
# ifdef DEBUG_INCLUDE
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" xmlRelaxNGLoadInclude(%s) \n " , URL ) ;
2003-03-10 13:13:58 +00:00
# endif
2003-02-01 17:43:10 +00:00
/*
* check against recursion in the stack
*/
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
if ( xmlStrEqual ( ctxt - > incTab [ i ] - > href , URL ) ) {
xmlRngPErr ( ctxt , NULL , XML_RNGP_INCLUDE_RECURSE ,
" Detected an Include recursion for %s \n " , URL ,
NULL ) ;
return ( NULL ) ;
}
2003-02-01 17:43:10 +00:00
}
/*
* load the document
*/
2004-01-13 20:42:02 +00:00
doc = xmlReadFile ( ( const char * ) URL , NULL , 0 ) ;
2003-02-01 17:43:10 +00:00
if ( doc = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_PARSE_ERROR ,
" xmlRelaxNG: could not load %s \n " , URL , NULL ) ;
return ( NULL ) ;
2003-02-01 17:43:10 +00:00
}
2003-03-10 13:13:58 +00:00
# ifdef DEBUG_INCLUDE
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " Parsed %s Okay \n " , URL ) ;
2003-03-10 13:13:58 +00:00
# endif
2003-02-01 17:43:10 +00:00
/*
* Allocate the document structures and register it first .
*/
ret = ( xmlRelaxNGIncludePtr ) xmlMalloc ( sizeof ( xmlRelaxNGInclude ) ) ;
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " allocating include \n " ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
2003-02-01 17:43:10 +00:00
}
memset ( ret , 0 , sizeof ( xmlRelaxNGInclude ) ) ;
ret - > doc = doc ;
ret - > href = xmlStrdup ( URL ) ;
2003-02-26 14:48:48 +00:00
ret - > next = ctxt - > includes ;
ctxt - > includes = ret ;
2003-02-01 17:43:10 +00:00
2003-02-17 17:25:42 +00:00
/*
* transmit the ns if needed
*/
if ( ns ! = NULL ) {
2003-10-07 11:33:24 +00:00
root = xmlDocGetRootElement ( doc ) ;
if ( root ! = NULL ) {
if ( xmlHasProp ( root , BAD_CAST " ns " ) = = NULL ) {
xmlSetProp ( root , BAD_CAST " ns " , ns ) ;
}
}
2003-02-17 17:25:42 +00:00
}
2003-02-01 17:43:10 +00:00
/*
2003-02-26 14:48:48 +00:00
* push it on the stack
2003-02-01 17:43:10 +00:00
*/
xmlRelaxNGIncludePush ( ctxt , ret ) ;
/*
* Some preprocessing of the document content , this include recursing
* in the include stack .
*/
2003-03-10 13:13:58 +00:00
# ifdef DEBUG_INCLUDE
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " cleanup of %s \n " , URL ) ;
2003-03-10 13:13:58 +00:00
# endif
2003-02-01 17:43:10 +00:00
doc = xmlRelaxNGCleanupDoc ( ctxt , doc ) ;
if ( doc = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > inc = NULL ;
return ( NULL ) ;
2003-02-01 17:43:10 +00:00
}
/*
* Pop up the include from the stack
*/
xmlRelaxNGIncludePop ( ctxt ) ;
2003-03-10 13:13:58 +00:00
# ifdef DEBUG_INCLUDE
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " Checking of %s \n " , URL ) ;
2003-03-10 13:13:58 +00:00
# endif
2003-02-01 17:43:10 +00:00
/*
* Check that the top element is a grammar
*/
root = xmlDocGetRootElement ( doc ) ;
if ( root = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY ,
" xmlRelaxNG: included document is empty %s \n " , URL ,
NULL ) ;
return ( NULL ) ;
2003-02-01 17:43:10 +00:00
}
if ( ! IS_RELAXNG ( root , " grammar " ) ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_GRAMMAR_MISSING ,
" xmlRelaxNG: included document %s root is not a grammar \n " ,
URL , NULL ) ;
return ( NULL ) ;
2003-02-01 17:43:10 +00:00
}
/*
* Elimination of redefined rules in the include .
*/
cur = node - > children ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
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 ) ;
}
}
2018-10-12 22:30:26 +02:00
if ( IS_RELAXNG ( cur , " div " ) & & cur - > children ! = NULL ) {
cur = cur - > children ;
} else {
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
} else {
while ( cur - > parent ! = node & & cur - > parent - > next = = NULL ) {
cur = cur - > parent ;
}
cur = cur - > parent ! = node ? cur - > parent - > next : NULL ;
}
}
2003-10-07 11:33:24 +00:00
}
return ( ret ) ;
2003-02-01 17:43:10 +00:00
}
2003-03-07 18:32:59 +00:00
/**
* xmlRelaxNGValidErrorPush :
* @ ctxt : the validation context
* @ err : the error code
* @ arg1 : the first string argument
* @ arg2 : the second string argument
2003-03-18 00:31:04 +00:00
* @ dup : arg need to be duplicated
2003-03-07 18:32:59 +00:00
*
* Pushes a new error on top of the error stack
*
* Returns 0 in case of error , the index in the stack otherwise
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidErrorPush ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGValidErr err , const xmlChar * arg1 ,
const xmlChar * arg2 , int dup )
2003-03-07 18:32:59 +00:00
{
xmlRelaxNGValidErrorPtr cur ;
2003-10-07 11:33:24 +00:00
2003-03-31 16:09:37 +00:00
# ifdef DEBUG_ERROR
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" Pushing error %d at %d on stack \n " , err , ctxt - > errNr ) ;
2003-03-31 16:09:37 +00:00
# endif
2003-03-07 18:32:59 +00:00
if ( ctxt - > errTab = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > errMax = 8 ;
ctxt - > errNr = 0 ;
ctxt - > errTab =
( xmlRelaxNGValidErrorPtr ) xmlMalloc ( ctxt - > errMax *
sizeof
( xmlRelaxNGValidError ) ) ;
2003-03-07 18:32:59 +00:00
if ( ctxt - > errTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " pushing error \n " ) ;
2003-03-07 18:32:59 +00:00
return ( 0 ) ;
}
2003-10-07 11:33:24 +00:00
ctxt - > err = NULL ;
2003-03-07 18:32:59 +00:00
}
if ( ctxt - > errNr > = ctxt - > errMax ) {
2003-10-07 11:33:24 +00:00
ctxt - > errMax * = 2 ;
2003-03-07 18:32:59 +00:00
ctxt - > errTab =
( xmlRelaxNGValidErrorPtr ) xmlRealloc ( ctxt - > errTab ,
2003-10-07 11:33:24 +00:00
ctxt - > errMax *
sizeof
( xmlRelaxNGValidError ) ) ;
2003-03-07 18:32:59 +00:00
if ( ctxt - > errTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " pushing error \n " ) ;
2003-03-07 18:32:59 +00:00
return ( 0 ) ;
}
2003-10-07 11:33:24 +00:00
ctxt - > err = & ctxt - > errTab [ ctxt - > errNr - 1 ] ;
2003-03-07 18:32:59 +00:00
}
2003-03-19 21:02:29 +00:00
if ( ( ctxt - > err ! = NULL ) & & ( ctxt - > state ! = NULL ) & &
2003-10-07 11:33:24 +00:00
( ctxt - > err - > node = = ctxt - > state - > node ) & & ( ctxt - > err - > err = = err ) )
return ( ctxt - > errNr ) ;
2003-03-07 18:32:59 +00:00
cur = & ctxt - > errTab [ ctxt - > errNr ] ;
cur - > err = err ;
2003-03-18 00:31:04 +00:00
if ( dup ) {
cur - > arg1 = xmlStrdup ( arg1 ) ;
cur - > arg2 = xmlStrdup ( arg2 ) ;
2003-10-07 11:33:24 +00:00
cur - > flags = ERROR_IS_DUP ;
2003-03-18 00:31:04 +00:00
} else {
cur - > arg1 = arg1 ;
cur - > arg2 = arg2 ;
2003-10-07 11:33:24 +00:00
cur - > flags = 0 ;
2003-03-18 00:31:04 +00:00
}
2003-03-07 18:32:59 +00:00
if ( ctxt - > state ! = NULL ) {
2003-10-07 11:33:24 +00:00
cur - > node = ctxt - > state - > node ;
cur - > seq = ctxt - > state - > seq ;
2003-03-07 18:32:59 +00:00
} else {
2003-10-07 11:33:24 +00:00
cur - > node = NULL ;
cur - > seq = NULL ;
2003-03-07 18:32:59 +00:00
}
ctxt - > err = cur ;
return ( ctxt - > errNr + + ) ;
}
/**
* xmlRelaxNGValidErrorPop :
* @ ctxt : the validation context
*
* Pops the top error from the error stack
*/
2003-03-18 00:31:04 +00:00
static void
2003-03-07 18:32:59 +00:00
xmlRelaxNGValidErrorPop ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-03-18 00:31:04 +00:00
xmlRelaxNGValidErrorPtr cur ;
2003-03-07 18:32:59 +00:00
2003-03-21 21:22:48 +00:00
if ( ctxt - > errNr < = 0 ) {
2003-10-07 11:33:24 +00:00
ctxt - > err = NULL ;
2003-03-18 00:31:04 +00:00
return ;
2003-03-21 21:22:48 +00:00
}
2003-03-07 18:32:59 +00:00
ctxt - > errNr - - ;
if ( ctxt - > errNr > 0 )
ctxt - > err = & ctxt - > errTab [ ctxt - > errNr - 1 ] ;
else
ctxt - > err = NULL ;
2003-03-18 00:31:04 +00:00
cur = & ctxt - > errTab [ ctxt - > errNr ] ;
if ( cur - > flags & ERROR_IS_DUP ) {
2003-10-07 11:33:24 +00:00
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 ;
2003-03-18 00:31:04 +00:00
}
2003-03-07 18:32:59 +00:00
}
2003-01-29 21:07:52 +00:00
/**
* 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 ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDocumentPtr value )
2003-01-29 21:07:52 +00:00
{
if ( ctxt - > docTab = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > docMax = 4 ;
ctxt - > docNr = 0 ;
ctxt - > docTab =
( xmlRelaxNGDocumentPtr * ) xmlMalloc ( ctxt - > docMax *
sizeof ( ctxt - > docTab [ 0 ] ) ) ;
2003-01-29 21:07:52 +00:00
if ( ctxt - > docTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " adding document \n " ) ;
2003-01-29 21:07:52 +00:00
return ( 0 ) ;
}
}
if ( ctxt - > docNr > = ctxt - > docMax ) {
ctxt - > docMax * = 2 ;
ctxt - > docTab =
( xmlRelaxNGDocumentPtr * ) xmlRealloc ( ctxt - > docTab ,
2003-10-07 11:33:24 +00:00
ctxt - > docMax *
sizeof ( ctxt - > docTab [ 0 ] ) ) ;
2003-01-29 21:07:52 +00:00
if ( ctxt - > docTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " adding document \n " ) ;
2003-01-29 21:07:52 +00:00
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 )
2005-07-28 23:49:35 +00:00
return ( NULL ) ;
2003-01-29 21:07:52 +00:00
ctxt - > docNr - - ;
if ( ctxt - > docNr > 0 )
ctxt - > doc = ctxt - > docTab [ ctxt - > docNr - 1 ] ;
else
ctxt - > doc = NULL ;
ret = ctxt - > docTab [ ctxt - > docNr ] ;
2005-07-28 23:49:35 +00:00
ctxt - > docTab [ ctxt - > docNr ] = NULL ;
2003-01-29 21:07:52 +00:00
return ( ret ) ;
}
/**
2003-02-01 17:43:10 +00:00
* xmlRelaxNGLoadExternalRef :
2003-01-29 21:07:52 +00:00
* @ 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
2003-10-07 11:33:24 +00:00
xmlRelaxNGLoadExternalRef ( xmlRelaxNGParserCtxtPtr ctxt ,
const xmlChar * URL , const xmlChar * ns )
{
2003-01-29 21:07:52 +00:00
xmlRelaxNGDocumentPtr ret = NULL ;
xmlDocPtr doc ;
xmlNodePtr root ;
int i ;
/*
* check against recursion in the stack
*/
2003-10-07 11:33:24 +00:00
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 ) ;
}
2003-01-29 21:07:52 +00:00
}
/*
* load the document
*/
2004-01-13 20:42:02 +00:00
doc = xmlReadFile ( ( const char * ) URL , NULL , 0 ) ;
2003-01-29 21:07:52 +00:00
if ( doc = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , NULL , XML_RNGP_PARSE_ERROR ,
" xmlRelaxNG: could not load %s \n " , URL , NULL ) ;
return ( NULL ) ;
2003-01-29 21:07:52 +00:00
}
/*
* Allocate the document structures and register it first .
*/
ret = ( xmlRelaxNGDocumentPtr ) xmlMalloc ( sizeof ( xmlRelaxNGDocument ) ) ;
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , ( xmlNodePtr ) doc , XML_ERR_NO_MEMORY ,
" xmlRelaxNG: allocate memory for doc %s \n " , URL , NULL ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
2003-01-29 21:07:52 +00:00
}
memset ( ret , 0 , sizeof ( xmlRelaxNGDocument ) ) ;
ret - > doc = doc ;
ret - > href = xmlStrdup ( URL ) ;
2003-02-26 14:48:48 +00:00
ret - > next = ctxt - > documents ;
2009-08-14 18:52:10 +02:00
ret - > externalRef = 1 ;
2003-02-26 14:48:48 +00:00
ctxt - > documents = ret ;
2003-01-29 21:07:52 +00:00
/*
* transmit the ns if needed
*/
if ( ns ! = NULL ) {
2003-10-07 11:33:24 +00:00
root = xmlDocGetRootElement ( doc ) ;
if ( root ! = NULL ) {
if ( xmlHasProp ( root , BAD_CAST " ns " ) = = NULL ) {
xmlSetProp ( root , BAD_CAST " ns " , ns ) ;
}
}
2003-01-29 21:07:52 +00:00
}
/*
* 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 ) {
2003-10-07 11:33:24 +00:00
ctxt - > doc = NULL ;
return ( NULL ) ;
2003-01-29 21:07:52 +00:00
}
xmlRelaxNGDocumentPop ( ctxt ) ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-29 21:07:52 +00:00
}
2003-01-23 18:29:16 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Error functions *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-18 00:31:04 +00:00
# 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);
2003-01-23 18:29:16 +00:00
2003-02-09 14:22:17 +00:00
static const char *
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefName ( xmlRelaxNGDefinePtr def )
{
2003-02-09 14:22:17 +00:00
if ( def = = NULL )
2003-10-07 11:33:24 +00:00
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 " ) ;
2003-02-09 14:22:17 +00:00
}
2003-02-14 16:54:11 +00:00
2003-01-23 18:29:16 +00:00
/**
2003-03-07 18:32:59 +00:00
* 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 *
2003-10-07 11:33:24 +00:00
xmlRelaxNGGetErrorString ( xmlRelaxNGValidErr err , const xmlChar * arg1 ,
const xmlChar * arg2 )
{
2003-03-07 18:32:59 +00:00
char msg [ 1000 ] ;
2016-05-31 21:04:50 +08:00
xmlChar * result ;
2003-03-07 18:32:59 +00:00
if ( arg1 = = NULL )
2003-10-07 11:33:24 +00:00
arg1 = BAD_CAST " " ;
2003-03-07 18:32:59 +00:00
if ( arg2 = = NULL )
2003-10-07 11:33:24 +00:00
arg2 = BAD_CAST " " ;
2003-03-07 18:32:59 +00:00
msg [ 0 ] = 0 ;
switch ( err ) {
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_OK :
return ( NULL ) ;
case XML_RELAXNG_ERR_MEMORY :
return ( xmlCharStrdup ( " out of memory \n " ) ) ;
2003-03-07 18:32:59 +00:00
case XML_RELAXNG_ERR_TYPE :
2003-10-07 11:33:24 +00:00
snprintf ( msg , 1000 , " failed to validate type %s \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_TYPEVAL :
snprintf ( msg , 1000 , " Type %s doesn't allow value '%s' \n " , arg1 ,
arg2 ) ;
break ;
case XML_RELAXNG_ERR_DUPID :
snprintf ( msg , 1000 , " ID %s redefined \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_TYPECMP :
snprintf ( msg , 1000 , " failed to compare type %s \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_NOSTATE :
return ( xmlCharStrdup ( " Internal error: no state \n " ) ) ;
case XML_RELAXNG_ERR_NODEFINE :
return ( xmlCharStrdup ( " Internal error: no define \n " ) ) ;
case XML_RELAXNG_ERR_INTERNAL :
snprintf ( msg , 1000 , " Internal error: %s \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_LISTEXTRA :
snprintf ( msg , 1000 , " Extra data in list: %s \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_INTERNODATA :
return ( xmlCharStrdup
( " Internal: interleave block has no data \n " ) ) ;
case XML_RELAXNG_ERR_INTERSEQ :
return ( xmlCharStrdup ( " Invalid sequence in interleave \n " ) ) ;
case XML_RELAXNG_ERR_INTEREXTRA :
snprintf ( msg , 1000 , " Extra element %s in interleave \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_ELEMNAME :
snprintf ( msg , 1000 , " Expecting element %s, got %s \n " , arg1 ,
arg2 ) ;
break ;
case XML_RELAXNG_ERR_ELEMNONS :
snprintf ( msg , 1000 , " Expecting a namespace for element %s \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_ELEMWRONGNS :
snprintf ( msg , 1000 ,
" Element %s has wrong namespace: expecting %s \n " , arg1 ,
arg2 ) ;
break ;
case XML_RELAXNG_ERR_ELEMWRONG :
snprintf ( msg , 1000 , " Did not expect element %s there \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_TEXTWRONG :
snprintf ( msg , 1000 ,
" Did not expect text in element %s content \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_ELEMEXTRANS :
snprintf ( msg , 1000 , " Expecting no namespace for element %s \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_ELEMNOTEMPTY :
snprintf ( msg , 1000 , " Expecting element %s to be empty \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_NOELEM :
snprintf ( msg , 1000 , " Expecting an element %s, got nothing \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_NOTELEM :
return ( xmlCharStrdup ( " Expecting an element got text \n " ) ) ;
case XML_RELAXNG_ERR_ATTRVALID :
snprintf ( msg , 1000 , " Element %s failed to validate attributes \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_CONTENTVALID :
snprintf ( msg , 1000 , " Element %s failed to validate content \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_EXTRACONTENT :
snprintf ( msg , 1000 , " Element %s has extra content: %s \n " ,
arg1 , arg2 ) ;
break ;
case XML_RELAXNG_ERR_INVALIDATTR :
snprintf ( msg , 1000 , " Invalid attribute %s for element %s \n " ,
arg1 , arg2 ) ;
break ;
case XML_RELAXNG_ERR_LACKDATA :
snprintf ( msg , 1000 , " Datatype element %s contains no data \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_DATAELEM :
snprintf ( msg , 1000 , " Datatype element %s has child elements \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_VALELEM :
snprintf ( msg , 1000 , " Value element %s has child elements \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_LISTELEM :
snprintf ( msg , 1000 , " List element %s has child elements \n " ,
arg1 ) ;
break ;
case XML_RELAXNG_ERR_DATATYPE :
snprintf ( msg , 1000 , " Error validating datatype %s \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_VALUE :
snprintf ( msg , 1000 , " Error validating value %s \n " , arg1 ) ;
break ;
case XML_RELAXNG_ERR_LIST :
return ( xmlCharStrdup ( " Error validating list \n " ) ) ;
case XML_RELAXNG_ERR_NOGRAMMAR :
return ( xmlCharStrdup ( " No top grammar defined \n " ) ) ;
case XML_RELAXNG_ERR_EXTRADATA :
return ( xmlCharStrdup ( " Extra data in the document \n " ) ) ;
default :
return ( xmlCharStrdup ( " Unknown error ! \n " ) ) ;
2003-03-07 18:32:59 +00:00
}
if ( msg [ 0 ] = = 0 ) {
2003-10-07 11:33:24 +00:00
snprintf ( msg , 1000 , " Unknown error code %d \n " , err ) ;
2003-03-07 18:32:59 +00:00
}
2003-05-10 20:02:45 +00:00
msg [ 1000 - 1 ] = 0 ;
2016-05-31 21:04:50 +08:00
result = xmlCharStrdup ( msg ) ;
2016-05-23 14:58:41 +08:00
return ( xmlEscapeFormatString ( & result ) ) ;
2003-03-07 18:32:59 +00:00
}
/**
* xmlRelaxNGShowValidError :
* @ ctxt : the validation context
* @ err : the error number
* @ node : the node
* @ child : the node child generating the problem .
* @ arg1 : the first argument
* @ arg2 : the second argument
*
* Show a validation error .
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGShowValidError ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGValidErr err , xmlNodePtr node ,
xmlNodePtr child , const xmlChar * arg1 ,
const xmlChar * arg2 )
2003-03-07 18:32:59 +00:00
{
xmlChar * msg ;
2005-09-04 13:50:03 +00:00
if ( ctxt - > flags & FLAGS_NOERROR )
2005-09-04 12:01:57 +00:00
return ;
2003-03-31 16:09:37 +00:00
# ifdef DEBUG_ERROR
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " Show error %d \n " , err ) ;
2003-03-31 16:09:37 +00:00
# endif
2003-03-07 18:32:59 +00:00
msg = xmlRelaxNGGetErrorString ( err , arg1 , arg2 ) ;
if ( msg = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-03-07 18:32:59 +00:00
2003-03-31 16:09:37 +00:00
if ( ctxt - > errNo = = XML_RELAXNG_OK )
2003-10-07 11:33:24 +00:00
ctxt - > errNo = err ;
xmlRngVErr ( ctxt , ( child = = NULL ? node : child ) , err ,
( const char * ) msg , arg1 , arg2 ) ;
2003-03-07 18:32:59 +00:00
xmlFree ( msg ) ;
}
2003-03-18 11:39:17 +00:00
/**
* xmlRelaxNGPopErrors :
* @ ctxt : the validation context
* @ level : the error level in the stack
*
* pop and discard all errors until the given level is reached
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGPopErrors ( xmlRelaxNGValidCtxtPtr ctxt , int level )
{
2003-03-18 11:39:17 +00:00
int i ;
xmlRelaxNGValidErrorPtr err ;
2003-03-31 16:09:37 +00:00
# ifdef DEBUG_ERROR
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" Pop errors till level %d \n " , level ) ;
2003-03-31 16:09:37 +00:00
# endif
2003-10-07 11:33:24 +00:00
for ( i = level ; i < ctxt - > errNr ; i + + ) {
err = & ctxt - > errTab [ i ] ;
if ( err - > flags & ERROR_IS_DUP ) {
if ( err - > arg1 ! = NULL )
xmlFree ( ( xmlChar * ) err - > arg1 ) ;
err - > arg1 = NULL ;
if ( err - > arg2 ! = NULL )
xmlFree ( ( xmlChar * ) err - > arg2 ) ;
err - > arg2 = NULL ;
err - > flags = 0 ;
}
2003-03-18 11:39:17 +00:00
}
ctxt - > errNr = level ;
2003-03-21 21:22:48 +00:00
if ( ctxt - > errNr < = 0 )
2003-10-07 11:33:24 +00:00
ctxt - > err = NULL ;
2003-03-18 11:39:17 +00:00
}
2003-10-07 11:33:24 +00:00
2003-03-07 18:32:59 +00:00
/**
* xmlRelaxNGDumpValidError :
* @ ctxt : the validation context
*
* Show all validation error over a given index .
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGDumpValidError ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-03-31 16:38:16 +00:00
int i , j , k ;
2003-03-21 21:22:48 +00:00
xmlRelaxNGValidErrorPtr err , dup ;
2003-03-07 18:32:59 +00:00
2003-03-31 16:09:37 +00:00
# ifdef DEBUG_ERROR
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" Dumping error stack %d errors \n " , ctxt - > errNr ) ;
2003-03-31 16:09:37 +00:00
# endif
2003-10-07 11:33:24 +00:00
for ( i = 0 , k = 0 ; i < ctxt - > errNr ; i + + ) {
err = & ctxt - > errTab [ i ] ;
if ( k < MAX_ERROR ) {
for ( j = 0 ; j < i ; j + + ) {
dup = & ctxt - > errTab [ j ] ;
if ( ( err - > err = = dup - > err ) & & ( err - > node = = dup - > node ) & &
( xmlStrEqual ( err - > arg1 , dup - > arg1 ) ) & &
( xmlStrEqual ( err - > arg2 , dup - > arg2 ) ) ) {
goto skip ;
}
}
xmlRelaxNGShowValidError ( ctxt , err - > err , err - > node , err - > seq ,
err - > arg1 , err - > arg2 ) ;
k + + ;
}
skip :
if ( err - > flags & ERROR_IS_DUP ) {
if ( err - > arg1 ! = NULL )
xmlFree ( ( xmlChar * ) err - > arg1 ) ;
err - > arg1 = NULL ;
if ( err - > arg2 ! = NULL )
xmlFree ( ( xmlChar * ) err - > arg2 ) ;
err - > arg2 = NULL ;
err - > flags = 0 ;
}
2003-03-07 18:32:59 +00:00
}
ctxt - > errNr = 0 ;
}
2003-10-07 11:33:24 +00:00
2003-03-07 18:32:59 +00:00
/**
* xmlRelaxNGAddValidError :
* @ ctxt : the validation context
* @ err : the error number
* @ arg1 : the first argument
* @ arg2 : the second argument
2003-03-18 00:31:04 +00:00
* @ dup : need to dup the args
2003-03-07 18:32:59 +00:00
*
* Register a validation error , either generating it if it ' s sure
* or stacking it for later handling if unsure .
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGAddValidError ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGValidErr err , const xmlChar * arg1 ,
const xmlChar * arg2 , int dup )
2003-03-07 18:32:59 +00:00
{
2005-09-04 13:50:03 +00:00
if ( ctxt = = NULL )
return ;
if ( ctxt - > flags & FLAGS_NOERROR )
2003-10-07 11:33:24 +00:00
return ;
2003-03-07 18:32:59 +00:00
2003-03-31 16:09:37 +00:00
# ifdef DEBUG_ERROR
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " Adding error %d \n " , err ) ;
2003-03-31 16:09:37 +00:00
# endif
2003-03-07 18:32:59 +00:00
/*
* generate the error directly
*/
2004-03-27 17:54:18 +00:00
if ( ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 ) | |
2012-09-11 13:26:36 +08:00
( ctxt - > flags & FLAGS_NEGATIVE ) ) {
2003-10-07 11:33:24 +00:00
xmlNodePtr node , seq ;
/*
* Flush first any stacked error which might be the
* real cause of the problem .
*/
if ( ctxt - > errNr ! = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
if ( ctxt - > state ! = NULL ) {
node = ctxt - > state - > node ;
seq = ctxt - > state - > seq ;
} else {
node = seq = NULL ;
}
2009-08-26 18:37:43 +02:00
if ( ( node = = NULL ) & & ( seq = = NULL ) ) {
node = ctxt - > pnode ;
}
2003-10-07 11:33:24 +00:00
xmlRelaxNGShowValidError ( ctxt , err , node , seq , arg1 , arg2 ) ;
2003-03-07 18:32:59 +00:00
}
/*
* Stack the error for later processing if needed
*/
else {
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidErrorPush ( ctxt , err , arg1 , arg2 , dup ) ;
2003-03-07 18:32:59 +00:00
}
}
2003-01-23 18:29:16 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Type library hooks *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-26 19:45:18 +00:00
static xmlChar * xmlRelaxNGNormalize ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
const xmlChar * str ) ;
2003-01-23 18:29:16 +00:00
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGSchemaTypeHave :
* @ data : data needed for the library
* @ type : the type name
*
* Check if the given type is provided by
* the W3C XMLSchema Datatype library .
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGSchemaTypeHave ( void * data ATTRIBUTE_UNUSED , const xmlChar * type )
{
2003-01-27 12:35:42 +00:00
xmlSchemaTypePtr typ ;
if ( type = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
typ = xmlSchemaGetPredefinedType ( type ,
BAD_CAST
" http://www.w3.org/2001/XMLSchema " ) ;
2003-01-27 12:35:42 +00:00
if ( typ = = NULL )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
return ( 1 ) ;
2003-01-25 18:01:32 +00:00
}
/**
* xmlRelaxNGSchemaTypeCheck :
* @ data : data needed for the library
* @ type : the type name
* @ value : the value to check
2003-03-18 00:31:04 +00:00
* @ node : the node
2003-01-25 18:01:32 +00:00
*
* Check if the given type and value are validated by
* the W3C XMLSchema Datatype library .
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
xmlRelaxNGSchemaTypeCheck ( void * data ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
const xmlChar * type ,
const xmlChar * value ,
void * * result , xmlNodePtr node )
{
2003-01-27 12:35:42 +00:00
xmlSchemaTypePtr typ ;
int ret ;
if ( ( type = = NULL ) | | ( value = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
typ = xmlSchemaGetPredefinedType ( type ,
BAD_CAST
" http://www.w3.org/2001/XMLSchema " ) ;
2003-01-27 12:35:42 +00:00
if ( typ = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-18 00:31:04 +00:00
ret = xmlSchemaValPredefTypeNode ( typ , value ,
2003-10-07 11:33:24 +00:00
( xmlSchemaValPtr * ) result , node ) ;
if ( ret = = 2 ) /* special ID error code */
return ( 2 ) ;
2003-01-27 12:35:42 +00:00
if ( ret = = 0 )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-27 12:35:42 +00:00
if ( ret > 0 )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
}
2003-02-27 17:42:22 +00:00
/**
* xmlRelaxNGSchemaFacetCheck :
* @ data : data needed for the library
* @ type : the type name
* @ facet : the facet name
* @ val : the facet value
* @ strval : the string value
* @ value : the value to check
*
* Function provided by a type library to check a value facet
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGSchemaFacetCheck ( void * data ATTRIBUTE_UNUSED ,
const xmlChar * type , const xmlChar * facetname ,
const xmlChar * val , const xmlChar * strval ,
void * value )
{
2003-02-27 17:42:22 +00:00
xmlSchemaFacetPtr facet ;
xmlSchemaTypePtr typ ;
int ret ;
if ( ( type = = NULL ) | | ( strval = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
typ = xmlSchemaGetPredefinedType ( type ,
BAD_CAST
" http://www.w3.org/2001/XMLSchema " ) ;
2003-02-27 17:42:22 +00:00
if ( typ = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-02-27 17:42:22 +00:00
facet = xmlSchemaNewFacet ( ) ;
if ( facet = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-02-27 17:42:22 +00:00
2003-10-07 11:33:24 +00:00
if ( xmlStrEqual ( facetname , BAD_CAST " minInclusive " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_MININCLUSIVE ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " minExclusive " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_MINEXCLUSIVE ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " maxInclusive " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_MAXINCLUSIVE ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " maxExclusive " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_MAXEXCLUSIVE ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " totalDigits " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_TOTALDIGITS ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " fractionDigits " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_FRACTIONDIGITS ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " pattern " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_PATTERN ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " enumeration " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_ENUMERATION ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " whiteSpace " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_WHITESPACE ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " length " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_LENGTH ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( facetname , BAD_CAST " maxLength " ) ) {
2003-02-27 17:42:22 +00:00
facet - > type = XML_SCHEMA_FACET_MAXLENGTH ;
} else if ( xmlStrEqual ( facetname , BAD_CAST " minLength " ) ) {
facet - > type = XML_SCHEMA_FACET_MINLENGTH ;
} else {
2003-10-07 11:33:24 +00:00
xmlSchemaFreeFacet ( facet ) ;
return ( - 1 ) ;
2003-02-27 17:42:22 +00:00
}
2004-03-22 19:10:02 +00:00
facet - > value = val ;
2003-02-27 17:42:22 +00:00
ret = xmlSchemaCheckFacet ( facet , typ , NULL , type ) ;
if ( ret ! = 0 ) {
2003-10-07 11:33:24 +00:00
xmlSchemaFreeFacet ( facet ) ;
return ( - 1 ) ;
2003-02-27 17:42:22 +00:00
}
ret = xmlSchemaValidateFacet ( typ , facet , strval , value ) ;
xmlSchemaFreeFacet ( facet ) ;
if ( ret ! = 0 )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
return ( 0 ) ;
2003-02-27 17:42:22 +00:00
}
2003-03-28 13:29:53 +00:00
/**
* xmlRelaxNGSchemaFreeValue :
* @ data : data needed for the library
* @ value : the value to free
*
* Function provided by a type library to free a Schemas value
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGSchemaFreeValue ( void * data ATTRIBUTE_UNUSED , void * value )
{
2003-03-28 13:29:53 +00:00
xmlSchemaFreeValue ( value ) ;
}
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGSchemaTypeCompare :
* @ data : data needed for the library
* @ type : the type name
* @ value1 : the first value
* @ value2 : the second value
*
2003-03-28 13:29:53 +00:00
* Compare two values for equality accordingly a type from the W3C XMLSchema
2003-01-25 18:01:32 +00:00
* Datatype library .
*
2003-03-28 13:29:53 +00:00
* Returns 1 if equal , 0 if no and - 1 in case of error .
2003-01-25 18:01:32 +00:00
*/
static int
xmlRelaxNGSchemaTypeCompare ( void * data ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
const xmlChar * type ,
const xmlChar * value1 ,
xmlNodePtr ctxt1 ,
void * comp1 ,
const xmlChar * value2 , xmlNodePtr ctxt2 )
{
2003-03-28 13:29:53 +00:00
int ret ;
xmlSchemaTypePtr typ ;
xmlSchemaValPtr res1 = NULL , res2 = NULL ;
if ( ( type = = NULL ) | | ( value1 = = NULL ) | | ( value2 = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
typ = xmlSchemaGetPredefinedType ( type ,
BAD_CAST
" http://www.w3.org/2001/XMLSchema " ) ;
2003-03-28 13:29:53 +00:00
if ( typ = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-30 21:10:09 +00:00
if ( comp1 = = NULL ) {
2003-10-07 11:33:24 +00:00
ret = xmlSchemaValPredefTypeNode ( typ , value1 , & res1 , ctxt1 ) ;
if ( ret ! = 0 )
return ( - 1 ) ;
if ( res1 = = NULL )
return ( - 1 ) ;
2003-03-30 21:10:09 +00:00
} else {
2003-10-07 11:33:24 +00:00
res1 = ( xmlSchemaValPtr ) comp1 ;
2003-03-30 21:10:09 +00:00
}
ret = xmlSchemaValPredefTypeNode ( typ , value2 , & res2 , ctxt2 ) ;
2003-03-28 13:29:53 +00:00
if ( ret ! = 0 ) {
2013-09-30 11:27:41 +08:00
if ( res1 ! = ( xmlSchemaValPtr ) comp1 )
2005-06-13 11:41:31 +00:00
xmlSchemaFreeValue ( res1 ) ;
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-28 13:29:53 +00:00
}
ret = xmlSchemaCompareValues ( res1 , res2 ) ;
2003-03-30 21:10:09 +00:00
if ( res1 ! = ( xmlSchemaValPtr ) comp1 )
2003-10-07 11:33:24 +00:00
xmlSchemaFreeValue ( res1 ) ;
2003-03-28 13:29:53 +00:00
xmlSchemaFreeValue ( res2 ) ;
if ( ret = = - 2 )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-28 13:29:53 +00:00
if ( ret = = 0 )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
return ( 0 ) ;
2003-01-25 18:01:32 +00:00
}
2003-10-07 11:33:24 +00:00
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGDefaultTypeHave :
* @ data : data needed for the library
* @ type : the type name
*
* Check if the given type is provided by
* the default datatype library .
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefaultTypeHave ( void * data ATTRIBUTE_UNUSED ,
const xmlChar * type )
{
2003-01-25 18:01:32 +00:00
if ( type = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
if ( xmlStrEqual ( type , BAD_CAST " string " ) )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-25 18:01:32 +00:00
if ( xmlStrEqual ( type , BAD_CAST " token " ) )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
return ( 0 ) ;
2003-01-25 18:01:32 +00:00
}
/**
* xmlRelaxNGDefaultTypeCheck :
* @ data : data needed for the library
* @ type : the type name
* @ value : the value to check
2003-03-18 00:31:04 +00:00
* @ node : the node
2003-01-25 18:01:32 +00:00
*
* Check if the given type and value are validated by
* the default datatype library .
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
xmlRelaxNGDefaultTypeCheck ( void * data ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
const xmlChar * type ATTRIBUTE_UNUSED ,
const xmlChar * value ATTRIBUTE_UNUSED ,
void * * result ATTRIBUTE_UNUSED ,
xmlNodePtr node ATTRIBUTE_UNUSED )
{
2003-02-18 21:12:46 +00:00
if ( value = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-02-18 21:12:46 +00:00
if ( xmlStrEqual ( type , BAD_CAST " string " ) )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-02-18 21:12:46 +00:00
if ( xmlStrEqual ( type , BAD_CAST " token " ) ) {
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-02-18 21:12:46 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-01-25 18:01:32 +00:00
}
/**
* xmlRelaxNGDefaultTypeCompare :
* @ data : data needed for the library
* @ type : the type name
* @ value1 : the first value
* @ value2 : the second value
*
* Compare two values accordingly a type from the default
* datatype library .
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
xmlRelaxNGDefaultTypeCompare ( void * data ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
const xmlChar * type ,
const xmlChar * value1 ,
xmlNodePtr ctxt1 ATTRIBUTE_UNUSED ,
void * comp1 ATTRIBUTE_UNUSED ,
const xmlChar * value2 ,
xmlNodePtr ctxt2 ATTRIBUTE_UNUSED )
{
2003-01-26 19:45:18 +00:00
int ret = - 1 ;
if ( xmlStrEqual ( type , BAD_CAST " string " ) ) {
2003-10-07 11:33:24 +00:00
ret = xmlStrEqual ( value1 , value2 ) ;
2003-01-26 19:45:18 +00:00
} else if ( xmlStrEqual ( type , BAD_CAST " token " ) ) {
2003-10-07 11:33:24 +00:00
if ( ! xmlStrEqual ( value1 , value2 ) ) {
xmlChar * nval , * nvalue ;
/*
* TODO : trivial optimizations are possible by
* computing at compile - time
*/
nval = xmlRelaxNGNormalize ( NULL , value1 ) ;
nvalue = xmlRelaxNGNormalize ( NULL , value2 ) ;
if ( ( nval = = NULL ) | | ( nvalue = = NULL ) )
ret = - 1 ;
else if ( xmlStrEqual ( nval , nvalue ) )
ret = 1 ;
else
ret = 0 ;
if ( nval ! = NULL )
xmlFree ( nval ) ;
if ( nvalue ! = NULL )
xmlFree ( nvalue ) ;
} else
ret = 1 ;
}
return ( ret ) ;
}
2003-01-25 18:01:32 +00:00
static int xmlRelaxNGTypeInitialized = 0 ;
static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL ;
/**
* xmlRelaxNGFreeTypeLibrary :
* @ lib : the type library structure
* @ namespace : the URI bound to the library
*
* Free the structure associated to the type library
*/
2003-01-23 18:29:16 +00:00
static void
2017-11-09 16:42:47 +01:00
xmlRelaxNGFreeTypeLibrary ( void * payload ,
2003-10-07 11:33:24 +00:00
const xmlChar * namespace ATTRIBUTE_UNUSED )
{
2017-11-09 16:42:47 +01:00
xmlRelaxNGTypeLibraryPtr lib = ( xmlRelaxNGTypeLibraryPtr ) payload ;
2003-01-25 18:01:32 +00:00
if ( lib = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-25 18:01:32 +00:00
if ( lib - > namespace ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( ( xmlChar * ) lib - > namespace ) ;
2003-01-25 18:01:32 +00:00
xmlFree ( lib ) ;
}
/**
* xmlRelaxNGRegisterTypeLibrary :
* @ namespace : the URI bound to the library
* @ data : data associated to the library
* @ have : the provide function
* @ check : the checking function
* @ comp : the comparison function
*
* Register a new type library
*
* Returns 0 in case of success and - 1 in case of error .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGRegisterTypeLibrary ( const xmlChar * namespace , void * data ,
xmlRelaxNGTypeHave have ,
xmlRelaxNGTypeCheck check ,
xmlRelaxNGTypeCompare comp ,
xmlRelaxNGFacetCheck facet ,
xmlRelaxNGTypeFree freef )
{
2003-01-25 18:01:32 +00:00
xmlRelaxNGTypeLibraryPtr lib ;
int ret ;
if ( ( xmlRelaxNGRegisteredTypes = = NULL ) | | ( namespace = = NULL ) | |
2003-10-07 11:33:24 +00:00
( check = = NULL ) | | ( comp = = NULL ) )
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
if ( xmlHashLookup ( xmlRelaxNGRegisteredTypes , namespace ) ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Relax-NG types library '%s' already registered \n " ,
namespace ) ;
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
}
2003-10-07 11:33:24 +00:00
lib =
( xmlRelaxNGTypeLibraryPtr )
xmlMalloc ( sizeof ( xmlRelaxNGTypeLibrary ) ) ;
2003-01-25 18:01:32 +00:00
if ( lib = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( NULL , " adding types library \n " ) ;
2003-01-25 18:01:32 +00:00
return ( - 1 ) ;
}
memset ( lib , 0 , sizeof ( xmlRelaxNGTypeLibrary ) ) ;
lib - > namespace = xmlStrdup ( namespace ) ;
lib - > data = data ;
lib - > have = have ;
lib - > comp = comp ;
lib - > check = check ;
2003-02-27 17:42:22 +00:00
lib - > facet = facet ;
lib - > freef = freef ;
2003-01-25 18:01:32 +00:00
ret = xmlHashAddEntry ( xmlRelaxNGRegisteredTypes , namespace , lib ) ;
if ( ret < 0 ) {
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Relax-NG types library failed to register '%s' \n " ,
namespace ) ;
xmlRelaxNGFreeTypeLibrary ( lib , namespace ) ;
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-01-25 18:01:32 +00:00
}
/**
* xmlRelaxNGInitTypes :
*
2019-09-30 17:04:54 +02:00
* Initialize the default type libraries .
2003-01-25 18:01:32 +00:00
*
* Returns 0 in case of success and - 1 in case of error .
*/
2004-11-03 14:20:29 +00:00
int
2003-10-07 11:33:24 +00:00
xmlRelaxNGInitTypes ( void )
{
2003-01-25 18:01:32 +00:00
if ( xmlRelaxNGTypeInitialized ! = 0 )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-01-25 18:01:32 +00:00
xmlRelaxNGRegisteredTypes = xmlHashCreate ( 10 ) ;
if ( xmlRelaxNGRegisteredTypes = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Failed to allocate sh table for Relax-NG types \n " ) ;
return ( - 1 ) ;
}
xmlRelaxNGRegisterTypeLibrary ( BAD_CAST
" http://www.w3.org/2001/XMLSchema-datatypes " ,
NULL , xmlRelaxNGSchemaTypeHave ,
xmlRelaxNGSchemaTypeCheck ,
xmlRelaxNGSchemaTypeCompare ,
xmlRelaxNGSchemaFacetCheck ,
xmlRelaxNGSchemaFreeValue ) ;
xmlRelaxNGRegisterTypeLibrary ( xmlRelaxNGNs , NULL ,
xmlRelaxNGDefaultTypeHave ,
xmlRelaxNGDefaultTypeCheck ,
xmlRelaxNGDefaultTypeCompare , NULL ,
NULL ) ;
2003-01-25 18:01:32 +00:00
xmlRelaxNGTypeInitialized = 1 ;
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGCleanupTypes :
*
2022-03-06 13:55:48 +01:00
* DEPRECATED : This function will be made private . Call xmlCleanupParser
* to free global state but see the warnings there . xmlCleanupParser
* should be only called once at program exit . In most cases , you don ' t
* have call cleanup functions at all .
*
2003-01-23 18:29:16 +00:00
* Cleanup the default Schemas type library associated to RelaxNG
*/
2003-10-07 11:33:24 +00:00
void
xmlRelaxNGCleanupTypes ( void )
{
2003-06-02 16:58:46 +00:00
xmlSchemaCleanupTypes ( ) ;
2003-01-25 18:01:32 +00:00
if ( xmlRelaxNGTypeInitialized = = 0 )
2003-10-07 11:33:24 +00:00
return ;
2017-11-09 16:42:47 +01:00
xmlHashFree ( xmlRelaxNGRegisteredTypes , xmlRelaxNGFreeTypeLibrary ) ;
2003-01-25 18:01:32 +00:00
xmlRelaxNGTypeInitialized = 0 ;
2003-01-23 18:29:16 +00:00
}
2003-03-17 15:37:12 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Compiling element content into regexp *
* *
2003-03-17 15:37:12 +00:00
* Sometime the element content can be compiled into a pure regexp , *
* This allows a faster execution and streamability at that level *
2012-09-11 13:26:36 +08:00
* *
2003-03-17 15:37:12 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-04-13 19:53:42 +00:00
static int xmlRelaxNGTryCompile ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlRelaxNGDefinePtr def ) ;
2003-03-17 15:37:12 +00:00
/**
2019-09-30 17:04:54 +02:00
* xmlRelaxNGIsCompilable :
2003-03-17 15:37:12 +00:00
* @ define : the definition to check
*
* Check if a definition is nullable .
*
* Returns 1 if yes , 0 if no and - 1 in case of error
*/
static int
2019-09-30 17:04:54 +02:00
xmlRelaxNGIsCompilable ( xmlRelaxNGDefinePtr def )
2003-10-07 11:33:24 +00:00
{
2003-04-13 19:53:42 +00:00
int ret = - 1 ;
2003-03-17 15:37:12 +00:00
if ( def = = NULL ) {
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-17 15:37:12 +00:00
}
2003-04-13 19:53:42 +00:00
if ( ( def - > type ! = XML_RELAXNG_ELEMENT ) & &
( def - > dflags & IS_COMPILABLE ) )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-04-13 19:53:42 +00:00
if ( ( def - > type ! = XML_RELAXNG_ELEMENT ) & &
( def - > dflags & IS_NOT_COMPILABLE ) )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
switch ( def - > type ) {
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_NOOP :
2019-09-30 17:04:54 +02:00
ret = xmlRelaxNGIsCompilable ( def - > content ) ;
2003-10-07 11:33:24 +00:00
break ;
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_TEXT :
case XML_RELAXNG_EMPTY :
2003-10-07 11:33:24 +00:00
ret = 1 ;
break ;
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_ELEMENT :
2003-10-07 11:33:24 +00:00
/*
2019-09-30 17:04:54 +02:00
* Check if the element content is compilable
2003-10-07 11:33:24 +00:00
*/
if ( ( ( def - > dflags & IS_NOT_COMPILABLE ) = = 0 ) & &
( ( def - > dflags & IS_COMPILABLE ) = = 0 ) ) {
xmlRelaxNGDefinePtr list ;
list = def - > content ;
while ( list ! = NULL ) {
2019-09-30 17:04:54 +02:00
ret = xmlRelaxNGIsCompilable ( list ) ;
2003-10-07 11:33:24 +00:00
if ( ret ! = 1 )
break ;
list = list - > next ;
}
2004-03-27 17:54:18 +00:00
/*
* Because the routine is recursive , we must guard against
* discovering both COMPILABLE and NOT_COMPILABLE
*/
if ( ret = = 0 ) {
def - > dflags & = ~ IS_COMPILABLE ;
2003-10-07 11:33:24 +00:00
def - > dflags | = IS_NOT_COMPILABLE ;
2004-03-27 17:54:18 +00:00
}
if ( ( ret = = 1 ) & & ! ( def - > dflags & = IS_NOT_COMPILABLE ) )
2003-10-07 11:33:24 +00:00
def - > dflags | = IS_COMPILABLE ;
2003-07-28 13:02:24 +00:00
# ifdef DEBUG_COMPILE
2003-10-07 11:33:24 +00:00
if ( ret = = 1 ) {
xmlGenericError ( xmlGenericErrorContext ,
" element content for %s is compilable \n " ,
def - > name ) ;
} else if ( ret = = 0 ) {
xmlGenericError ( xmlGenericErrorContext ,
" element content for %s is not compilable \n " ,
def - > name ) ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
2019-09-30 17:04:54 +02:00
" Problem in RelaxNGIsCompilable for element %s \n " ,
2003-10-07 11:33:24 +00:00
def - > name ) ;
}
2003-07-28 13:02:24 +00:00
# endif
2003-10-07 11:33:24 +00:00
}
/*
2019-09-30 17:04:54 +02:00
* All elements return a compilable status unless they
2003-10-07 11:33:24 +00:00
* are generic like anyName
*/
if ( ( def - > nameClass ! = NULL ) | | ( def - > name = = NULL ) )
ret = 0 ;
else
ret = 1 ;
return ( ret ) ;
2003-07-23 19:56:29 +00:00
case XML_RELAXNG_REF :
case XML_RELAXNG_EXTERNALREF :
case XML_RELAXNG_PARENTREF :
2003-10-07 11:33:24 +00:00
if ( def - > depth = = - 20 ) {
return ( 1 ) ;
} else {
xmlRelaxNGDefinePtr list ;
def - > depth = - 20 ;
list = def - > content ;
while ( list ! = NULL ) {
2019-09-30 17:04:54 +02:00
ret = xmlRelaxNGIsCompilable ( list ) ;
2003-10-07 11:33:24 +00:00
if ( ret ! = 1 )
break ;
list = list - > next ;
}
}
break ;
2003-07-23 19:56:29 +00:00
case XML_RELAXNG_START :
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_OPTIONAL :
case XML_RELAXNG_ZEROORMORE :
case XML_RELAXNG_ONEORMORE :
case XML_RELAXNG_CHOICE :
case XML_RELAXNG_GROUP :
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_DEF : {
xmlRelaxNGDefinePtr list ;
list = def - > content ;
while ( list ! = NULL ) {
2019-09-30 17:04:54 +02:00
ret = xmlRelaxNGIsCompilable ( list ) ;
2003-10-07 11:33:24 +00:00
if ( ret ! = 1 )
break ;
list = list - > next ;
}
break ;
}
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_EXCEPT :
case XML_RELAXNG_ATTRIBUTE :
case XML_RELAXNG_INTERLEAVE :
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_DATATYPE :
case XML_RELAXNG_LIST :
case XML_RELAXNG_PARAM :
case XML_RELAXNG_VALUE :
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_NOT_ALLOWED :
2004-04-02 09:07:22 +00:00
ret = 0 ;
2003-10-07 11:33:24 +00:00
break ;
2003-03-17 15:37:12 +00:00
}
2003-10-07 11:33:24 +00:00
if ( ret = = 0 )
def - > dflags | = IS_NOT_COMPILABLE ;
if ( ret = = 1 )
def - > dflags | = IS_COMPILABLE ;
2003-07-28 13:02:24 +00:00
# ifdef DEBUG_COMPILE
if ( ret = = 1 ) {
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
2019-09-30 17:04:54 +02:00
" RelaxNGIsCompilable %s : true \n " ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefName ( def ) ) ;
2003-07-28 13:02:24 +00:00
} else if ( ret = = 0 ) {
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
2019-09-30 17:04:54 +02:00
" RelaxNGIsCompilable %s : false \n " ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefName ( def ) ) ;
2003-07-28 13:02:24 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
2019-09-30 17:04:54 +02:00
" Problem in RelaxNGIsCompilable %s \n " ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefName ( def ) ) ;
2003-07-28 13:02:24 +00:00
}
# endif
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-04-13 19:53:42 +00:00
}
/**
* xmlRelaxNGCompile :
* ctxt : the RelaxNG parser context
* @ define : the definition tree to compile
*
* Compile the set of definitions , it works recursively , till the
* element boundaries , where it tries to compile the content if possible
*
* Returns 0 if success and - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGCompile ( xmlRelaxNGParserCtxtPtr ctxt , xmlRelaxNGDefinePtr def )
{
2003-04-13 19:53:42 +00:00
int ret = 0 ;
xmlRelaxNGDefinePtr list ;
2003-10-07 11:33:24 +00:00
if ( ( ctxt = = NULL ) | | ( def = = NULL ) )
return ( - 1 ) ;
2003-04-13 19:53:42 +00:00
2003-10-07 11:33:24 +00:00
switch ( def - > type ) {
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_START :
2019-09-30 17:04:54 +02:00
if ( ( xmlRelaxNGIsCompilable ( def ) = = 1 ) & & ( def - > depth ! = - 25 ) ) {
2003-10-07 11:33:24 +00:00
xmlAutomataPtr oldam = ctxt - > am ;
xmlAutomataStatePtr oldstate = ctxt - > state ;
2003-04-13 19:53:42 +00:00
def - > depth = - 25 ;
2003-10-07 11:33:24 +00:00
list = def - > content ;
ctxt - > am = xmlNewAutomata ( ) ;
if ( ctxt - > am = = NULL )
return ( - 1 ) ;
2009-08-31 16:47:39 +02:00
/*
* assume identical strings but not same pointer are different
* atoms , needed for non - determinism detection
* That way if 2 elements with the same name are in a choice
* branch the automata is found non - deterministic and
* we fallback to the normal validation which does the right
* thing of exploring both choices .
*/
xmlAutomataSetFlags ( ctxt - > am , 1 ) ;
2003-10-07 11:33:24 +00:00
ctxt - > state = xmlAutomataGetInitState ( ctxt - > am ) ;
while ( list ! = NULL ) {
xmlRelaxNGCompile ( ctxt , list ) ;
list = list - > next ;
}
xmlAutomataSetFinalState ( ctxt - > am , ctxt - > state ) ;
2012-05-15 11:03:46 +08:00
if ( xmlAutomataIsDeterminist ( ctxt - > am ) )
def - > contModel = xmlAutomataCompile ( ctxt - > am ) ;
2003-10-07 11:33:24 +00:00
xmlFreeAutomata ( ctxt - > am ) ;
ctxt - > state = oldstate ;
ctxt - > am = oldam ;
}
break ;
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_ELEMENT :
2003-10-07 11:33:24 +00:00
if ( ( ctxt - > am ! = NULL ) & & ( def - > name ! = NULL ) ) {
ctxt - > state = xmlAutomataNewTransition2 ( ctxt - > am ,
ctxt - > state , NULL ,
def - > name , def - > ns ,
def ) ;
}
2003-04-13 19:53:42 +00:00
if ( ( def - > dflags & IS_COMPILABLE ) & & ( def - > depth ! = - 25 ) ) {
2003-10-07 11:33:24 +00:00
xmlAutomataPtr oldam = ctxt - > am ;
xmlAutomataStatePtr oldstate = ctxt - > state ;
2003-04-13 19:53:42 +00:00
def - > depth = - 25 ;
2003-10-07 11:33:24 +00:00
list = def - > content ;
ctxt - > am = xmlNewAutomata ( ) ;
if ( ctxt - > am = = NULL )
return ( - 1 ) ;
2009-08-31 16:47:39 +02:00
xmlAutomataSetFlags ( ctxt - > am , 1 ) ;
2003-10-07 11:33:24 +00:00
ctxt - > state = xmlAutomataGetInitState ( ctxt - > am ) ;
while ( list ! = NULL ) {
xmlRelaxNGCompile ( ctxt , list ) ;
list = list - > next ;
}
xmlAutomataSetFinalState ( ctxt - > am , ctxt - > state ) ;
def - > contModel = xmlAutomataCompile ( ctxt - > am ) ;
if ( ! xmlRegexpIsDeterminist ( def - > contModel ) ) {
2009-08-31 16:47:39 +02:00
# ifdef DEBUG_COMPILE
xmlGenericError ( xmlGenericErrorContext ,
" Content model not determinist %s \n " ,
def - > name ) ;
# endif
2003-10-07 11:33:24 +00:00
/*
* we can only use the automata if it is determinist
*/
xmlRegFreeRegexp ( def - > contModel ) ;
def - > contModel = NULL ;
}
xmlFreeAutomata ( ctxt - > am ) ;
ctxt - > state = oldstate ;
ctxt - > am = oldam ;
} else {
xmlAutomataPtr oldam = ctxt - > am ;
/*
* we can ' t build the content model for this element content
* but it still might be possible to build it for some of its
* children , recurse .
*/
ret = xmlRelaxNGTryCompile ( ctxt , def ) ;
ctxt - > am = oldam ;
}
break ;
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_NOOP :
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGCompile ( ctxt , def - > content ) ;
break ;
case XML_RELAXNG_OPTIONAL : {
xmlAutomataStatePtr oldstate = ctxt - > state ;
2009-08-26 18:35:29 +02:00
list = def - > content ;
while ( list ! = NULL ) {
xmlRelaxNGCompile ( ctxt , list ) ;
list = list - > next ;
}
2003-10-07 11:33:24 +00:00
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , ctxt - > state ) ;
break ;
}
case XML_RELAXNG_ZEROORMORE : {
xmlAutomataStatePtr oldstate ;
ctxt - > state =
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , NULL ) ;
oldstate = ctxt - > state ;
list = def - > content ;
while ( list ! = NULL ) {
xmlRelaxNGCompile ( ctxt , list ) ;
list = list - > next ;
}
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , oldstate ) ;
ctxt - > state =
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , NULL ) ;
break ;
}
case XML_RELAXNG_ONEORMORE : {
xmlAutomataStatePtr oldstate ;
list = def - > content ;
while ( list ! = NULL ) {
xmlRelaxNGCompile ( ctxt , list ) ;
list = list - > next ;
}
oldstate = ctxt - > state ;
list = def - > content ;
while ( list ! = NULL ) {
xmlRelaxNGCompile ( ctxt , list ) ;
list = list - > next ;
}
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , oldstate ) ;
ctxt - > state =
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , NULL ) ;
break ;
}
case XML_RELAXNG_CHOICE : {
xmlAutomataStatePtr target = NULL ;
xmlAutomataStatePtr oldstate = ctxt - > state ;
list = def - > content ;
while ( list ! = NULL ) {
ctxt - > state = oldstate ;
ret = xmlRelaxNGCompile ( ctxt , list ) ;
if ( ret ! = 0 )
break ;
if ( target = = NULL )
target = ctxt - > state ;
else {
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state ,
target ) ;
}
list = list - > next ;
}
ctxt - > state = target ;
break ;
}
2003-07-23 19:56:29 +00:00
case XML_RELAXNG_REF :
case XML_RELAXNG_EXTERNALREF :
case XML_RELAXNG_PARENTREF :
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_GROUP :
case XML_RELAXNG_DEF :
2003-10-07 11:33:24 +00:00
list = def - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGCompile ( ctxt , list ) ;
if ( ret ! = 0 )
break ;
list = list - > next ;
}
break ;
case XML_RELAXNG_TEXT : {
xmlAutomataStatePtr oldstate ;
ctxt - > state =
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , NULL ) ;
oldstate = ctxt - > state ;
xmlRelaxNGCompile ( ctxt , def - > content ) ;
xmlAutomataNewTransition ( ctxt - > am , ctxt - > state ,
ctxt - > state , BAD_CAST " #text " ,
NULL ) ;
ctxt - > state =
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , NULL ) ;
break ;
}
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_EMPTY :
2003-10-07 11:33:24 +00:00
ctxt - > state =
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , NULL ) ;
break ;
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_EXCEPT :
case XML_RELAXNG_ATTRIBUTE :
case XML_RELAXNG_INTERLEAVE :
case XML_RELAXNG_NOT_ALLOWED :
case XML_RELAXNG_DATATYPE :
case XML_RELAXNG_LIST :
case XML_RELAXNG_PARAM :
case XML_RELAXNG_VALUE :
2003-10-07 11:33:24 +00:00
/* This should not happen and generate an internal error */
fprintf ( stderr , " RNG internal error trying to compile %s \n " ,
xmlRelaxNGDefName ( def ) ) ;
break ;
2003-04-13 19:53:42 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-04-13 19:53:42 +00:00
}
/**
* xmlRelaxNGTryCompile :
* ctxt : the RelaxNG parser context
* @ define : the definition tree to compile
*
* Try to compile the set of definitions , it works recursively ,
* possibly ignoring parts which cannot be compiled .
*
* Returns 0 if success and - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGTryCompile ( xmlRelaxNGParserCtxtPtr ctxt , xmlRelaxNGDefinePtr def )
{
2003-04-13 19:53:42 +00:00
int ret = 0 ;
xmlRelaxNGDefinePtr list ;
2003-10-07 11:33:24 +00:00
if ( ( ctxt = = NULL ) | | ( def = = NULL ) )
return ( - 1 ) ;
2003-04-13 19:53:42 +00:00
if ( ( def - > type = = XML_RELAXNG_START ) | |
( def - > type = = XML_RELAXNG_ELEMENT ) ) {
2019-09-30 17:04:54 +02:00
ret = xmlRelaxNGIsCompilable ( def ) ;
2003-10-07 11:33:24 +00:00
if ( ( def - > dflags & IS_COMPILABLE ) & & ( def - > depth ! = - 25 ) ) {
ctxt - > am = NULL ;
ret = xmlRelaxNGCompile ( ctxt , def ) ;
2003-07-23 19:56:29 +00:00
# ifdef DEBUG_PROGRESSIVE
2003-10-07 11:33:24 +00:00
if ( ret = = 0 ) {
if ( def - > type = = XML_RELAXNG_START )
xmlGenericError ( xmlGenericErrorContext ,
" compiled the start \n " ) ;
else
xmlGenericError ( xmlGenericErrorContext ,
" compiled element %s \n " , def - > name ) ;
} else {
if ( def - > type = = XML_RELAXNG_START )
xmlGenericError ( xmlGenericErrorContext ,
" failed to compile the start \n " ) ;
else
xmlGenericError ( xmlGenericErrorContext ,
" failed to compile element %s \n " ,
def - > name ) ;
}
2003-07-23 19:56:29 +00:00
# endif
2003-10-07 11:33:24 +00:00
return ( ret ) ;
}
2003-04-13 19:53:42 +00:00
}
2003-10-07 11:33:24 +00:00
switch ( def - > type ) {
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_NOOP :
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGTryCompile ( ctxt , def - > content ) ;
break ;
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_TEXT :
case XML_RELAXNG_DATATYPE :
case XML_RELAXNG_LIST :
case XML_RELAXNG_PARAM :
case XML_RELAXNG_VALUE :
case XML_RELAXNG_EMPTY :
case XML_RELAXNG_ELEMENT :
2003-10-07 11:33:24 +00:00
ret = 0 ;
break ;
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_OPTIONAL :
case XML_RELAXNG_ZEROORMORE :
case XML_RELAXNG_ONEORMORE :
case XML_RELAXNG_CHOICE :
case XML_RELAXNG_GROUP :
case XML_RELAXNG_DEF :
2003-07-23 19:56:29 +00:00
case XML_RELAXNG_START :
case XML_RELAXNG_REF :
case XML_RELAXNG_EXTERNALREF :
case XML_RELAXNG_PARENTREF :
2003-10-07 11:33:24 +00:00
list = def - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGTryCompile ( ctxt , list ) ;
if ( ret ! = 0 )
break ;
list = list - > next ;
}
break ;
2003-04-13 19:53:42 +00:00
case XML_RELAXNG_EXCEPT :
case XML_RELAXNG_ATTRIBUTE :
case XML_RELAXNG_INTERLEAVE :
case XML_RELAXNG_NOT_ALLOWED :
2003-10-07 11:33:24 +00:00
ret = 0 ;
break ;
2003-04-13 19:53:42 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-03-17 15:37:12 +00:00
}
2003-01-23 18:29:16 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Parsing functions *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute ( xmlRelaxNGParserCtxtPtr
ctxt , xmlNodePtr node ) ;
static xmlRelaxNGDefinePtr xmlRelaxNGParseElement ( xmlRelaxNGParserCtxtPtr
ctxt , xmlNodePtr node ) ;
static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns ( xmlRelaxNGParserCtxtPtr
ctxt , xmlNodePtr nodes ,
int group ) ;
static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern ( xmlRelaxNGParserCtxtPtr
ctxt , xmlNodePtr node ) ;
static xmlRelaxNGPtr xmlRelaxNGParseDocument ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlNodePtr node ) ;
static int xmlRelaxNGParseGrammarContent ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlNodePtr nodes ) ;
static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass ( xmlRelaxNGParserCtxtPtr
ctxt , xmlNodePtr node ,
xmlRelaxNGDefinePtr
def ) ;
static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar ( xmlRelaxNGParserCtxtPtr
ctxt , xmlNodePtr nodes ) ;
static int xmlRelaxNGElementMatch ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define ,
xmlNodePtr elem ) ;
2003-01-23 18:29:16 +00:00
2003-03-19 21:02:29 +00:00
# define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
2003-01-23 18:29:16 +00:00
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGIsNullable :
* @ define : the definition to verify
*
* Check if a definition is nullable .
*
* Returns 1 if yes , 0 if no and - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGIsNullable ( xmlRelaxNGDefinePtr define )
{
2003-03-16 17:52:32 +00:00
int ret ;
2003-10-07 11:33:24 +00:00
2003-03-16 17:52:32 +00:00
if ( define = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-03-16 17:52:32 +00:00
2003-03-21 16:53:17 +00:00
if ( define - > dflags & IS_NULLABLE )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-03-21 16:53:17 +00:00
if ( define - > dflags & IS_NOT_NULLABLE )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
switch ( define - > type ) {
case XML_RELAXNG_EMPTY :
case XML_RELAXNG_TEXT :
2003-10-07 11:33:24 +00:00
ret = 1 ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_NOOP :
case XML_RELAXNG_DEF :
case XML_RELAXNG_REF :
case XML_RELAXNG_EXTERNALREF :
case XML_RELAXNG_PARENTREF :
case XML_RELAXNG_ONEORMORE :
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGIsNullable ( define - > content ) ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_EXCEPT :
case XML_RELAXNG_NOT_ALLOWED :
case XML_RELAXNG_ELEMENT :
case XML_RELAXNG_DATATYPE :
case XML_RELAXNG_PARAM :
case XML_RELAXNG_VALUE :
case XML_RELAXNG_LIST :
case XML_RELAXNG_ATTRIBUTE :
2003-10-07 11:33:24 +00:00
ret = 0 ;
break ;
case XML_RELAXNG_CHOICE : {
xmlRelaxNGDefinePtr list = define - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGIsNullable ( list ) ;
if ( ret ! = 0 )
goto done ;
list = list - > next ;
}
ret = 0 ;
break ;
}
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_START :
case XML_RELAXNG_INTERLEAVE :
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_GROUP : {
xmlRelaxNGDefinePtr list = define - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGIsNullable ( list ) ;
if ( ret ! = 1 )
goto done ;
list = list - > next ;
}
return ( 1 ) ;
}
default :
return ( - 1 ) ;
}
done :
2003-03-16 17:52:32 +00:00
if ( ret = = 0 )
2003-10-07 11:33:24 +00:00
define - > dflags | = IS_NOT_NULLABLE ;
2003-03-16 17:52:32 +00:00
if ( ret = = 1 )
2003-10-07 11:33:24 +00:00
define - > dflags | = IS_NULLABLE ;
return ( ret ) ;
2003-03-16 17:52:32 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGIsBlank :
* @ str : a string
*
* Check if a string is ignorable c . f . 4.2 . Whitespace
*
* Returns 1 if the string is NULL or made of blanks chars , 0 otherwise
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGIsBlank ( xmlChar * str )
{
2003-01-23 18:29:16 +00:00
if ( str = = NULL )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-23 18:29:16 +00:00
while ( * str ! = 0 ) {
2003-10-18 16:20:14 +00:00
if ( ! ( IS_BLANK_CH ( * str ) ) )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
str + + ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGGetDataTypeLibrary :
* @ ctxt : a Relax - NG parser context
* @ node : the current data or value element
*
* Applies algorithm from 4.3 . datatypeLibrary attribute
*
2019-09-30 17:04:54 +02:00
* Returns the datatypeLibrary value or NULL if not found
2003-01-23 18:29:16 +00:00
*/
static xmlChar *
xmlRelaxNGGetDataTypeLibrary ( xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
xmlNodePtr node )
{
2003-01-23 18:29:16 +00:00
xmlChar * ret , * escape ;
2009-09-07 12:15:08 +02:00
if ( node = = NULL )
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
if ( ( IS_RELAXNG ( node , " data " ) ) | | ( IS_RELAXNG ( node , " value " ) ) ) {
2003-10-07 11:33:24 +00:00
ret = xmlGetProp ( node , BAD_CAST " datatypeLibrary " ) ;
if ( ret ! = NULL ) {
if ( ret [ 0 ] = = 0 ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
escape = xmlURIEscapeStr ( ret , BAD_CAST " :/#? " ) ;
if ( escape = = NULL ) {
return ( ret ) ;
}
xmlFree ( ret ) ;
return ( escape ) ;
}
2003-01-23 18:29:16 +00:00
}
node = node - > parent ;
while ( ( node ! = NULL ) & & ( node - > type = = XML_ELEMENT_NODE ) ) {
2003-10-07 11:33:24 +00:00
ret = xmlGetProp ( node , BAD_CAST " datatypeLibrary " ) ;
if ( ret ! = NULL ) {
if ( ret [ 0 ] = = 0 ) {
xmlFree ( ret ) ;
return ( NULL ) ;
}
escape = xmlURIEscapeStr ( ret , BAD_CAST " :/#? " ) ;
if ( escape = = NULL ) {
return ( ret ) ;
}
xmlFree ( ret ) ;
return ( escape ) ;
}
node = node - > parent ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
}
2003-01-25 18:01:32 +00:00
2003-01-26 00:52:04 +00:00
/**
* xmlRelaxNGParseValue :
* @ ctxt : a Relax - NG parser context
* @ node : the data node .
*
* parse the content of a RelaxNG value node .
*
* Returns the definition pointer or NULL in case of error
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseValue ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-01-26 00:52:04 +00:00
xmlRelaxNGDefinePtr def = NULL ;
2003-03-31 16:38:16 +00:00
xmlRelaxNGTypeLibraryPtr lib = NULL ;
2003-01-26 00:52:04 +00:00
xmlChar * type ;
xmlChar * library ;
2003-03-30 21:10:09 +00:00
int success = 0 ;
2003-01-26 00:52:04 +00:00
2003-03-16 17:52:32 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
2003-01-26 00:52:04 +00:00
if ( def = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-03-16 17:52:32 +00:00
def - > type = XML_RELAXNG_VALUE ;
2003-01-26 00:52:04 +00:00
type = xmlGetProp ( node , BAD_CAST " type " ) ;
if ( type ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGNormExtSpace ( type ) ;
if ( xmlValidateNCName ( type , 0 ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_TYPE_VALUE ,
" value type '%s' is not an NCName \n " , type , NULL ) ;
}
library = xmlRelaxNGGetDataTypeLibrary ( ctxt , node ) ;
if ( library = = NULL )
library =
xmlStrdup ( BAD_CAST " http://relaxng.org/ns/structure/1.0 " ) ;
def - > name = type ;
def - > ns = library ;
lib = ( xmlRelaxNGTypeLibraryPtr )
xmlHashLookup ( xmlRelaxNGRegisteredTypes , library ) ;
if ( lib = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_UNKNOWN_TYPE_LIB ,
" Use of unregistered type library '%s' \n " , library ,
NULL ) ;
def - > data = NULL ;
} else {
def - > data = lib ;
if ( lib - > have = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_ERROR_TYPE_LIB ,
" Internal error with type library '%s': no 'have' \n " ,
library , NULL ) ;
} else {
success = lib - > have ( lib - > data , def - > name ) ;
if ( success ! = 1 ) {
xmlRngPErr ( ctxt , node , XML_RNGP_TYPE_NOT_FOUND ,
" Error type '%s' is not exported by type library '%s' \n " ,
def - > name , library ) ;
}
}
}
2003-01-26 00:52:04 +00:00
}
if ( node - > children = = NULL ) {
2003-10-07 11:33:24 +00:00
def - > value = xmlStrdup ( BAD_CAST " " ) ;
2003-03-11 11:21:28 +00:00
} else if ( ( ( node - > children - > type ! = XML_TEXT_NODE ) & &
2003-10-07 11:33:24 +00:00
( node - > children - > type ! = XML_CDATA_SECTION_NODE ) ) | |
( node - > children - > next ! = NULL ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_TEXT_EXPECTED ,
" Expecting a single text value for <value>content \n " ,
NULL , NULL ) ;
2003-03-30 21:10:09 +00:00
} else if ( def ! = NULL ) {
2003-10-07 11:33:24 +00:00
def - > value = xmlNodeGetContent ( node ) ;
if ( def - > value = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_VALUE_NO_CONTENT ,
" Element <value> has no content \n " , NULL , NULL ) ;
} else if ( ( lib ! = NULL ) & & ( lib - > check ! = NULL ) & & ( success = = 1 ) ) {
void * val = NULL ;
success =
lib - > check ( lib - > data , def - > name , def - > value , & val , node ) ;
if ( success ! = 1 ) {
xmlRngPErr ( ctxt , node , XML_RNGP_INVALID_VALUE ,
" Value '%s' is not acceptable for type '%s' \n " ,
def - > value , def - > name ) ;
} else {
if ( val ! = NULL )
def - > attrs = val ;
}
}
}
return ( def ) ;
2003-01-26 00:52:04 +00:00
}
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGParseData :
* @ ctxt : a Relax - NG parser context
* @ node : the data node .
*
* parse the content of a RelaxNG data node .
*
* Returns the definition pointer or NULL in case of error
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseData ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2006-03-09 18:41:40 +00:00
xmlRelaxNGDefinePtr def = NULL , except ;
2003-02-19 00:19:14 +00:00
xmlRelaxNGDefinePtr param , lastparam = NULL ;
2003-01-25 18:01:32 +00:00
xmlRelaxNGTypeLibraryPtr lib ;
xmlChar * type ;
xmlChar * library ;
xmlNodePtr content ;
int tmp ;
type = xmlGetProp ( node , BAD_CAST " type " ) ;
if ( type = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_TYPE_MISSING , " data has no type \n " , NULL ,
NULL ) ;
return ( NULL ) ;
2003-01-25 18:01:32 +00:00
}
2003-02-14 16:54:11 +00:00
xmlRelaxNGNormExtSpace ( type ) ;
if ( xmlValidateNCName ( type , 0 ) ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_TYPE_VALUE ,
" data type '%s' is not an NCName \n " , type , NULL ) ;
2003-02-14 16:54:11 +00:00
}
2003-01-25 18:01:32 +00:00
library = xmlRelaxNGGetDataTypeLibrary ( ctxt , node ) ;
if ( library = = NULL )
2003-10-07 11:33:24 +00:00
library =
xmlStrdup ( BAD_CAST " http://relaxng.org/ns/structure/1.0 " ) ;
2003-01-25 18:01:32 +00:00
2003-03-16 17:52:32 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
2003-01-25 18:01:32 +00:00
if ( def = = NULL ) {
2021-07-14 15:31:55 +01:00
xmlFree ( library ) ;
2003-10-07 11:33:24 +00:00
xmlFree ( type ) ;
return ( NULL ) ;
2003-01-25 18:01:32 +00:00
}
2003-03-16 17:52:32 +00:00
def - > type = XML_RELAXNG_DATATYPE ;
2003-01-25 18:01:32 +00:00
def - > name = type ;
def - > ns = library ;
lib = ( xmlRelaxNGTypeLibraryPtr )
2003-10-07 11:33:24 +00:00
xmlHashLookup ( xmlRelaxNGRegisteredTypes , library ) ;
2003-01-25 18:01:32 +00:00
if ( lib = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_UNKNOWN_TYPE_LIB ,
" Use of unregistered type library '%s' \n " , library ,
NULL ) ;
def - > data = NULL ;
2003-01-25 18:01:32 +00:00
} else {
2003-10-07 11:33:24 +00:00
def - > data = lib ;
if ( lib - > have = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_ERROR_TYPE_LIB ,
" Internal error with type library '%s': no 'have' \n " ,
library , NULL ) ;
} else {
tmp = lib - > have ( lib - > data , def - > name ) ;
if ( tmp ! = 1 ) {
xmlRngPErr ( ctxt , node , XML_RNGP_TYPE_NOT_FOUND ,
" Error type '%s' is not exported by type library '%s' \n " ,
def - > name , library ) ;
} else
if ( ( xmlStrEqual
( library ,
BAD_CAST
" http://www.w3.org/2001/XMLSchema-datatypes " ) )
& & ( ( xmlStrEqual ( def - > name , BAD_CAST " IDREF " ) )
| | ( xmlStrEqual ( def - > name , BAD_CAST " IDREFS " ) ) ) ) {
ctxt - > idref = 1 ;
}
}
2003-01-25 18:01:32 +00:00
}
content = node - > children ;
2003-02-17 17:25:42 +00:00
/*
* Handle optional params
*/
2003-01-25 18:01:32 +00:00
while ( content ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ! xmlStrEqual ( content - > name , BAD_CAST " param " ) )
break ;
if ( xmlStrEqual ( library ,
BAD_CAST " http://relaxng.org/ns/structure/1.0 " ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARAM_FORBIDDEN ,
" Type library '%s' does not allow type parameters \n " ,
library , NULL ) ;
content = content - > next ;
while ( ( content ! = NULL ) & &
( xmlStrEqual ( content - > name , BAD_CAST " param " ) ) )
content = content - > next ;
} else {
param = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( param ! = NULL ) {
param - > type = XML_RELAXNG_PARAM ;
param - > name = xmlGetProp ( content , BAD_CAST " name " ) ;
if ( param - > name = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARAM_NAME_MISSING ,
" param has no name \n " , NULL , NULL ) ;
}
param - > value = xmlNodeGetContent ( content ) ;
if ( lastparam = = NULL ) {
def - > attrs = lastparam = param ;
} else {
lastparam - > next = param ;
lastparam = param ;
}
if ( lib ! = NULL ) {
}
}
content = content - > next ;
}
2003-01-25 18:01:32 +00:00
}
2003-02-17 17:25:42 +00:00
/*
* Handle optional except
*/
2003-10-07 11:33:24 +00:00
if ( ( content ! = NULL )
& & ( xmlStrEqual ( content - > name , BAD_CAST " except " ) ) ) {
xmlNodePtr child ;
2006-03-09 18:41:40 +00:00
xmlRelaxNGDefinePtr tmp2 , last = NULL ;
2003-10-07 11:33:24 +00:00
except = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( except = = NULL ) {
return ( def ) ;
}
except - > type = XML_RELAXNG_EXCEPT ;
child = content - > children ;
2006-03-09 18:41:40 +00:00
def - > content = except ;
2003-10-07 11:33:24 +00:00
if ( child = = NULL ) {
xmlRngPErr ( ctxt , content , XML_RNGP_EXCEPT_NO_CONTENT ,
" except has no content \n " , NULL , NULL ) ;
}
while ( child ! = NULL ) {
tmp2 = xmlRelaxNGParsePattern ( ctxt , child ) ;
if ( tmp2 ! = NULL ) {
2006-03-09 18:41:40 +00:00
if ( last = = NULL ) {
except - > content = last = tmp2 ;
2003-10-07 11:33:24 +00:00
} else {
2006-03-09 18:41:40 +00:00
last - > next = tmp2 ;
last = tmp2 ;
2003-10-07 11:33:24 +00:00
}
}
child = child - > next ;
}
content = content - > next ;
2003-02-17 17:25:42 +00:00
}
/*
* Check there is no unhandled data
*/
if ( content ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , content , XML_RNGP_DATA_CONTENT ,
" Element data has unexpected content %s \n " ,
content - > name , NULL ) ;
2003-02-17 17:25:42 +00:00
}
2003-01-25 18:01:32 +00:00
2003-10-07 11:33:24 +00:00
return ( def ) ;
2003-01-25 18:01:32 +00:00
}
2003-02-24 17:17:58 +00:00
static const xmlChar * invalidName = BAD_CAST " \1 " ;
2003-01-28 20:58:15 +00:00
/**
2003-02-24 17:17:58 +00:00
* xmlRelaxNGCompareNameClasses :
* @ defs1 : the first element / attribute defs
* @ defs2 : the second element / attribute defs
* @ name : the restriction on the name
* @ ns : the restriction on the namespace
2003-01-28 20:58:15 +00:00
*
* Compare the 2 lists of element definitions . The comparison is
* that if both lists do not accept the same QNames , it returns 1
* If the 2 lists can accept the same QName the comparison returns 0
*
2019-09-30 17:04:54 +02:00
* Returns 1 distinct , 0 if equal
2003-01-28 20:58:15 +00:00
*/
static int
2003-02-24 17:17:58 +00:00
xmlRelaxNGCompareNameClasses ( xmlRelaxNGDefinePtr def1 ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def2 )
{
2003-02-24 17:17:58 +00:00
int ret = 1 ;
xmlNode node ;
xmlNs ns ;
xmlRelaxNGValidCtxt ctxt ;
2003-10-07 11:33:24 +00:00
2003-03-07 18:32:59 +00:00
memset ( & ctxt , 0 , sizeof ( xmlRelaxNGValidCtxt ) ) ;
2005-09-04 13:50:03 +00:00
ctxt . flags = FLAGS_IGNORABLE | FLAGS_NOERROR ;
2003-02-24 17:17:58 +00:00
if ( ( def1 - > type = = XML_RELAXNG_ELEMENT ) | |
2003-10-07 11:33:24 +00:00
( def1 - > type = = XML_RELAXNG_ATTRIBUTE ) ) {
if ( def2 - > type = = XML_RELAXNG_TEXT )
return ( 1 ) ;
if ( def1 - > name ! = NULL ) {
node . name = def1 - > name ;
} else {
node . name = invalidName ;
}
if ( def1 - > ns ! = NULL ) {
if ( def1 - > ns [ 0 ] = = 0 ) {
node . ns = NULL ;
} else {
2004-04-02 14:03:22 +00:00
node . ns = & ns ;
2003-10-07 11:33:24 +00:00
ns . href = def1 - > ns ;
}
} else {
2004-04-02 14:03:22 +00:00
node . ns = NULL ;
2003-10-07 11:33:24 +00:00
}
2003-03-16 17:52:32 +00:00
if ( xmlRelaxNGElementMatch ( & ctxt , def2 , & node ) ) {
2003-10-07 11:33:24 +00:00
if ( def1 - > nameClass ! = NULL ) {
ret = xmlRelaxNGCompareNameClasses ( def1 - > nameClass , def2 ) ;
} else {
ret = 0 ;
}
} else {
ret = 1 ;
}
2003-02-24 17:17:58 +00:00
} else if ( def1 - > type = = XML_RELAXNG_TEXT ) {
2003-10-07 11:33:24 +00:00
if ( def2 - > type = = XML_RELAXNG_TEXT )
return ( 0 ) ;
return ( 1 ) ;
2003-02-24 17:17:58 +00:00
} else if ( def1 - > type = = XML_RELAXNG_EXCEPT ) {
2015-03-16 08:38:36 +08:00
ret = xmlRelaxNGCompareNameClasses ( def1 - > content , def2 ) ;
if ( ret = = 0 )
ret = 1 ;
else if ( ret = = 1 )
ret = 0 ;
2003-02-24 17:17:58 +00:00
} else {
2003-10-07 11:33:24 +00:00
TODO ret = 0 ;
2003-02-24 17:17:58 +00:00
}
if ( ret = = 0 )
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-02-24 17:17:58 +00:00
if ( ( def2 - > type = = XML_RELAXNG_ELEMENT ) | |
2003-10-07 11:33:24 +00:00
( def2 - > type = = XML_RELAXNG_ATTRIBUTE ) ) {
if ( def2 - > name ! = NULL ) {
node . name = def2 - > name ;
} else {
node . name = invalidName ;
}
node . ns = & ns ;
if ( def2 - > ns ! = NULL ) {
if ( def2 - > ns [ 0 ] = = 0 ) {
node . ns = NULL ;
} else {
ns . href = def2 - > ns ;
}
} else {
ns . href = invalidName ;
}
2003-03-16 17:52:32 +00:00
if ( xmlRelaxNGElementMatch ( & ctxt , def1 , & node ) ) {
2003-10-07 11:33:24 +00:00
if ( def2 - > nameClass ! = NULL ) {
ret = xmlRelaxNGCompareNameClasses ( def2 - > nameClass , def1 ) ;
} else {
ret = 0 ;
}
} else {
ret = 1 ;
}
2003-02-24 17:17:58 +00:00
} else {
2003-10-07 11:33:24 +00:00
TODO ret = 0 ;
2003-02-24 17:17:58 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-02-24 17:17:58 +00:00
}
/**
* xmlRelaxNGCompareElemDefLists :
* @ ctxt : a Relax - NG parser context
* @ defs1 : the first list of element / attribute defs
* @ defs2 : the second list of element / attribute defs
*
* Compare the 2 lists of element or attribute definitions . The comparison
* is that if both lists do not accept the same QNames , it returns 1
* If the 2 lists can accept the same QName the comparison returns 0
*
2019-09-30 17:04:54 +02:00
* Returns 1 distinct , 0 if equal
2003-02-24 17:17:58 +00:00
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGCompareElemDefLists ( xmlRelaxNGParserCtxtPtr ctxt
ATTRIBUTE_UNUSED , xmlRelaxNGDefinePtr * def1 ,
xmlRelaxNGDefinePtr * def2 )
{
2003-01-28 20:58:15 +00:00
xmlRelaxNGDefinePtr * basedef2 = def2 ;
2003-10-07 11:33:24 +00:00
2003-01-30 12:17:05 +00:00
if ( ( def1 = = NULL ) | | ( def2 = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-28 20:58:15 +00:00
if ( ( * def1 = = NULL ) | | ( * def2 = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-28 20:58:15 +00:00
while ( * def1 ! = NULL ) {
2003-10-07 11:33:24 +00:00
while ( ( * def2 ) ! = NULL ) {
if ( xmlRelaxNGCompareNameClasses ( * def1 , * def2 ) = = 0 )
return ( 0 ) ;
def2 + + ;
}
def2 = basedef2 ;
def1 + + ;
2003-01-28 20:58:15 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-28 20:58:15 +00:00
}
2003-04-16 15:58:05 +00:00
/**
* xmlRelaxNGGenerateAttributes :
* @ ctxt : a Relax - NG parser context
* @ def : the definition definition
*
* Check if the definition can only generate attributes
*
* Returns 1 if yes , 0 if no and - 1 in case of error .
*/
static int
xmlRelaxNGGenerateAttributes ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def )
{
2003-04-16 15:58:05 +00:00
xmlRelaxNGDefinePtr parent , cur , tmp ;
/*
* Don ' t run that check in case of error . Infinite recursion
* becomes possible .
*/
if ( ctxt - > nbErrors ! = 0 )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-04-16 15:58:05 +00:00
parent = NULL ;
cur = def ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( cur - > type = = XML_RELAXNG_ELEMENT ) | |
( cur - > type = = XML_RELAXNG_TEXT ) | |
( cur - > type = = XML_RELAXNG_DATATYPE ) | |
( cur - > type = = XML_RELAXNG_PARAM ) | |
( cur - > type = = XML_RELAXNG_LIST ) | |
( cur - > type = = XML_RELAXNG_VALUE ) | |
( cur - > type = = XML_RELAXNG_EMPTY ) )
return ( 0 ) ;
if ( ( cur - > type = = XML_RELAXNG_CHOICE ) | |
( cur - > type = = XML_RELAXNG_INTERLEAVE ) | |
( cur - > type = = XML_RELAXNG_GROUP ) | |
( cur - > type = = XML_RELAXNG_ONEORMORE ) | |
( cur - > type = = XML_RELAXNG_ZEROORMORE ) | |
( cur - > type = = XML_RELAXNG_OPTIONAL ) | |
( cur - > type = = XML_RELAXNG_PARENTREF ) | |
( cur - > type = = XML_RELAXNG_EXTERNALREF ) | |
( cur - > type = = XML_RELAXNG_REF ) | |
( cur - > type = = XML_RELAXNG_DEF ) ) {
if ( cur - > content ! = NULL ) {
parent = cur ;
cur = cur - > content ;
tmp = cur ;
while ( tmp ! = NULL ) {
tmp - > parent = parent ;
tmp = tmp - > next ;
}
continue ;
}
}
if ( cur = = def )
break ;
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
continue ;
}
do {
cur = cur - > parent ;
if ( cur = = NULL )
break ;
if ( cur = = def )
return ( 1 ) ;
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
break ;
}
} while ( cur ! = NULL ) ;
}
return ( 1 ) ;
}
2003-01-28 20:58:15 +00:00
/**
* xmlRelaxNGGetElements :
* @ ctxt : a Relax - NG parser context
2003-02-21 23:23:28 +00:00
* @ def : the definition definition
2018-11-22 18:09:51 +01:00
* @ eora : gather elements ( 0 ) , attributes ( 1 ) or elements and text ( 2 )
2003-01-28 20:58:15 +00:00
*
* Compute the list of top elements a definition can generate
*
* Returns a list of elements or NULL if none was found .
*/
static xmlRelaxNGDefinePtr *
xmlRelaxNGGetElements ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def , int eora )
{
2003-03-16 17:52:32 +00:00
xmlRelaxNGDefinePtr * ret = NULL , parent , cur , tmp ;
2003-01-28 20:58:15 +00:00
int len = 0 ;
int max = 0 ;
2003-02-21 23:23:28 +00:00
/*
* Don ' t run that check in case of error . Infinite recursion
* becomes possible .
*/
if ( ctxt - > nbErrors ! = 0 )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-02-21 23:23:28 +00:00
2003-01-28 20:58:15 +00:00
parent = NULL ;
cur = def ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( ( eora = = 0 ) & & ( ( cur - > type = = XML_RELAXNG_ELEMENT ) | |
( cur - > type = = XML_RELAXNG_TEXT ) ) ) | |
2018-11-22 18:09:51 +01:00
( ( eora = = 1 ) & & ( cur - > type = = XML_RELAXNG_ATTRIBUTE ) ) | |
( ( eora = = 2 ) & & ( ( cur - > type = = XML_RELAXNG_DATATYPE ) | |
( cur - > type = = XML_RELAXNG_ELEMENT ) | |
( cur - > type = = XML_RELAXNG_LIST ) | |
2019-01-01 19:58:07 +01:00
( cur - > type = = XML_RELAXNG_TEXT ) | |
2018-11-22 18:09:51 +01:00
( cur - > type = = XML_RELAXNG_VALUE ) ) ) ) {
2003-10-07 11:33:24 +00:00
if ( ret = = NULL ) {
max = 10 ;
ret = ( xmlRelaxNGDefinePtr * )
xmlMalloc ( ( max + 1 ) * sizeof ( xmlRelaxNGDefinePtr ) ) ;
if ( ret = = NULL ) {
xmlRngPErrMemory ( ctxt , " getting element list \n " ) ;
return ( NULL ) ;
}
} else if ( max < = len ) {
2004-09-23 13:15:03 +00:00
xmlRelaxNGDefinePtr * temp ;
2003-10-07 11:33:24 +00:00
max * = 2 ;
2004-09-23 13:15:03 +00:00
temp = xmlRealloc ( ret ,
2003-10-07 11:33:24 +00:00
( max + 1 ) * sizeof ( xmlRelaxNGDefinePtr ) ) ;
2004-09-23 13:15:03 +00:00
if ( temp = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " getting element list \n " ) ;
2004-09-23 13:15:03 +00:00
xmlFree ( ret ) ;
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
}
2004-09-23 13:15:03 +00:00
ret = temp ;
2003-10-07 11:33:24 +00:00
}
ret [ len + + ] = cur ;
ret [ len ] = NULL ;
} else if ( ( cur - > type = = XML_RELAXNG_CHOICE ) | |
( cur - > type = = XML_RELAXNG_INTERLEAVE ) | |
( cur - > type = = XML_RELAXNG_GROUP ) | |
( cur - > type = = XML_RELAXNG_ONEORMORE ) | |
( cur - > type = = XML_RELAXNG_ZEROORMORE ) | |
( cur - > type = = XML_RELAXNG_OPTIONAL ) | |
( cur - > type = = XML_RELAXNG_PARENTREF ) | |
( cur - > type = = XML_RELAXNG_REF ) | |
2004-03-20 11:32:36 +00:00
( cur - > type = = XML_RELAXNG_DEF ) | |
( cur - > type = = XML_RELAXNG_EXTERNALREF ) ) {
2003-10-07 11:33:24 +00:00
/*
* Don ' t go within elements or attributes or string values .
* Just gather the element top list
*/
if ( cur - > content ! = NULL ) {
parent = cur ;
cur = cur - > content ;
tmp = cur ;
while ( tmp ! = NULL ) {
tmp - > parent = parent ;
tmp = tmp - > next ;
}
continue ;
}
}
if ( cur = = def )
break ;
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
continue ;
}
do {
cur = cur - > parent ;
if ( cur = = NULL )
break ;
if ( cur = = def )
return ( ret ) ;
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
break ;
}
} while ( cur ! = NULL ) ;
}
return ( ret ) ;
}
2003-02-21 23:23:28 +00:00
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGCheckChoiceDeterminism :
2003-02-21 23:23:28 +00:00
* @ ctxt : a Relax - NG parser context
2003-03-16 17:52:32 +00:00
* @ def : the choice definition
2003-02-21 23:23:28 +00:00
*
2003-03-16 17:52:32 +00:00
* Also used to find indeterministic pattern in choice
2003-02-21 23:23:28 +00:00
*/
static void
2003-03-16 17:52:32 +00:00
xmlRelaxNGCheckChoiceDeterminism ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def )
{
2003-03-16 17:52:32 +00:00
xmlRelaxNGDefinePtr * * list ;
xmlRelaxNGDefinePtr cur ;
int nbchild = 0 , i , j , ret ;
int is_nullable = 0 ;
int is_indeterminist = 0 ;
2003-03-21 16:53:17 +00:00
xmlHashTablePtr triage = NULL ;
int is_triable = 1 ;
2003-02-21 23:23:28 +00:00
2003-10-07 11:33:24 +00:00
if ( ( def = = NULL ) | | ( def - > type ! = XML_RELAXNG_CHOICE ) )
return ;
2003-02-21 23:23:28 +00:00
2003-03-21 16:53:17 +00:00
if ( def - > dflags & IS_PROCESSED )
2003-10-07 11:33:24 +00:00
return ;
2003-03-21 16:53:17 +00:00
2003-02-21 23:23:28 +00:00
/*
* Don ' t run that check in case of error . Infinite recursion
* becomes possible .
*/
if ( ctxt - > nbErrors ! = 0 )
2003-10-07 11:33:24 +00:00
return ;
2003-02-21 23:23:28 +00:00
2003-03-16 17:52:32 +00:00
is_nullable = xmlRelaxNGIsNullable ( def ) ;
2003-02-21 23:23:28 +00:00
2003-03-16 17:52:32 +00:00
cur = def - > content ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
nbchild + + ;
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
2003-02-21 23:23:28 +00:00
2003-03-16 17:52:32 +00:00
list = ( xmlRelaxNGDefinePtr * * ) xmlMalloc ( nbchild *
2003-10-07 11:33:24 +00:00
sizeof ( xmlRelaxNGDefinePtr
* ) ) ;
2003-03-16 17:52:32 +00:00
if ( list = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " building choice \n " ) ;
return ;
2003-03-16 17:52:32 +00:00
}
i = 0 ;
2003-03-21 16:53:17 +00:00
/*
* a bit strong but safe
*/
if ( is_nullable = = 0 ) {
2003-10-07 11:33:24 +00:00
triage = xmlHashCreate ( 10 ) ;
2003-03-21 16:53:17 +00:00
} else {
2003-10-07 11:33:24 +00:00
is_triable = 0 ;
2003-03-21 16:53:17 +00:00
}
2003-03-16 17:52:32 +00:00
cur = def - > content ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
list [ i ] = xmlRelaxNGGetElements ( ctxt , cur , 0 ) ;
if ( ( list [ i ] = = NULL ) | | ( list [ i ] [ 0 ] = = NULL ) ) {
is_triable = 0 ;
} else if ( is_triable = = 1 ) {
xmlRelaxNGDefinePtr * tmp ;
int res ;
tmp = list [ i ] ;
while ( ( * tmp ! = NULL ) & & ( is_triable = = 1 ) ) {
if ( ( * tmp ) - > type = = XML_RELAXNG_TEXT ) {
res = xmlHashAddEntry2 ( triage ,
BAD_CAST " #text " , NULL ,
( void * ) cur ) ;
if ( res ! = 0 )
is_triable = - 1 ;
} else if ( ( ( * tmp ) - > type = = XML_RELAXNG_ELEMENT ) & &
( ( * tmp ) - > name ! = NULL ) ) {
if ( ( ( * tmp ) - > ns = = NULL ) | | ( ( * tmp ) - > ns [ 0 ] = = 0 ) )
res = xmlHashAddEntry2 ( triage ,
( * tmp ) - > name , NULL ,
( void * ) cur ) ;
else
res = xmlHashAddEntry2 ( triage ,
( * tmp ) - > name , ( * tmp ) - > ns ,
( void * ) cur ) ;
if ( res ! = 0 )
is_triable = - 1 ;
} else if ( ( * tmp ) - > type = = XML_RELAXNG_ELEMENT ) {
if ( ( ( * tmp ) - > ns = = NULL ) | | ( ( * tmp ) - > ns [ 0 ] = = 0 ) )
res = xmlHashAddEntry2 ( triage ,
BAD_CAST " #any " , NULL ,
( void * ) cur ) ;
else
res = xmlHashAddEntry2 ( triage ,
BAD_CAST " #any " , ( * tmp ) - > ns ,
( void * ) cur ) ;
if ( res ! = 0 )
is_triable = - 1 ;
} else {
is_triable = - 1 ;
}
tmp + + ;
}
}
i + + ;
cur = cur - > next ;
}
for ( i = 0 ; i < nbchild ; i + + ) {
if ( list [ i ] = = NULL )
continue ;
for ( j = 0 ; j < i ; j + + ) {
if ( list [ j ] = = NULL )
continue ;
ret = xmlRelaxNGCompareElemDefLists ( ctxt , list [ i ] , list [ j ] ) ;
if ( ret = = 0 ) {
is_indeterminist = 1 ;
}
}
}
for ( i = 0 ; i < nbchild ; i + + ) {
if ( list [ i ] ! = NULL )
xmlFree ( list [ i ] ) ;
2003-03-16 17:52:32 +00:00
}
xmlFree ( list ) ;
if ( is_indeterminist ) {
2003-10-07 11:33:24 +00:00
def - > dflags | = IS_INDETERMINIST ;
2003-03-21 16:53:17 +00:00
}
if ( is_triable = = 1 ) {
2003-10-07 11:33:24 +00:00
def - > dflags | = IS_TRIABLE ;
def - > data = triage ;
2003-03-21 16:53:17 +00:00
} else if ( triage ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlHashFree ( triage , NULL ) ;
2003-02-21 23:23:28 +00:00
}
2003-03-21 16:53:17 +00:00
def - > dflags | = IS_PROCESSED ;
2003-02-21 23:23:28 +00:00
}
2003-01-28 20:58:15 +00:00
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGCheckGroupAttrs :
2003-01-28 20:58:15 +00:00
* @ ctxt : a Relax - NG parser context
2003-03-15 21:30:25 +00:00
* @ def : the group definition
2003-01-28 20:58:15 +00:00
*
2003-03-15 21:30:25 +00:00
* Detects violations of rule 7.3
2003-01-28 20:58:15 +00:00
*/
static void
2003-03-16 17:52:32 +00:00
xmlRelaxNGCheckGroupAttrs ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def )
{
2003-03-16 17:52:32 +00:00
xmlRelaxNGDefinePtr * * list ;
xmlRelaxNGDefinePtr cur ;
int nbchild = 0 , i , j , ret ;
2003-01-28 20:58:15 +00:00
2003-03-15 21:30:25 +00:00
if ( ( def = = NULL ) | |
2003-10-07 11:33:24 +00:00
( ( def - > type ! = XML_RELAXNG_GROUP ) & &
( def - > type ! = XML_RELAXNG_ELEMENT ) ) )
return ;
2003-01-28 20:58:15 +00:00
2003-03-21 16:53:17 +00:00
if ( def - > dflags & IS_PROCESSED )
2003-10-07 11:33:24 +00:00
return ;
2003-03-21 16:53:17 +00:00
2003-02-21 23:23:28 +00:00
/*
* Don ' t run that check in case of error . Infinite recursion
* becomes possible .
*/
if ( ctxt - > nbErrors ! = 0 )
2003-10-07 11:33:24 +00:00
return ;
2003-02-21 23:23:28 +00:00
2003-03-16 17:52:32 +00:00
cur = def - > attrs ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
nbchild + + ;
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
cur = def - > content ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
nbchild + + ;
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
list = ( xmlRelaxNGDefinePtr * * ) xmlMalloc ( nbchild *
2003-10-07 11:33:24 +00:00
sizeof ( xmlRelaxNGDefinePtr
* ) ) ;
2003-03-16 17:52:32 +00:00
if ( list = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " building group \n " ) ;
return ;
2003-03-16 17:52:32 +00:00
}
i = 0 ;
cur = def - > attrs ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
list [ i ] = xmlRelaxNGGetElements ( ctxt , cur , 1 ) ;
i + + ;
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
cur = def - > content ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
list [ i ] = xmlRelaxNGGetElements ( ctxt , cur , 1 ) ;
i + + ;
cur = cur - > next ;
}
for ( i = 0 ; i < nbchild ; i + + ) {
if ( list [ i ] = = NULL )
continue ;
for ( j = 0 ; j < i ; j + + ) {
if ( list [ j ] = = NULL )
continue ;
ret = xmlRelaxNGCompareElemDefLists ( ctxt , list [ i ] , list [ j ] ) ;
if ( ret = = 0 ) {
xmlRngPErr ( ctxt , def - > node , XML_RNGP_GROUP_ATTR_CONFLICT ,
" Attributes conflicts in group \n " , NULL , NULL ) ;
}
}
}
for ( i = 0 ; i < nbchild ; i + + ) {
if ( list [ i ] ! = NULL )
xmlFree ( list [ i ] ) ;
2003-03-16 17:52:32 +00:00
}
xmlFree ( list ) ;
2003-03-21 16:53:17 +00:00
def - > dflags | = IS_PROCESSED ;
2003-03-16 17:52:32 +00:00
}
/**
* xmlRelaxNGComputeInterleaves :
* @ def : the interleave definition
* @ ctxt : a Relax - NG parser context
* @ name : the definition name
*
* A lot of work for preprocessing interleave definitions
* is potentially needed to get a decent execution speed at runtime
* - trying to get a total order on the element nodes generated
* by the interleaves , order the list of interleave definitions
* following that order .
* - if < text / > is used to handle mixed content , it is better to
* flag this in the define and simplify the runtime checking
* algorithm
*/
static void
2017-11-09 16:42:47 +01:00
xmlRelaxNGComputeInterleaves ( void * payload , void * data ,
const xmlChar * name ATTRIBUTE_UNUSED )
2003-10-07 11:33:24 +00:00
{
2017-11-09 16:42:47 +01:00
xmlRelaxNGDefinePtr def = ( xmlRelaxNGDefinePtr ) payload ;
xmlRelaxNGParserCtxtPtr ctxt = ( xmlRelaxNGParserCtxtPtr ) data ;
2003-03-21 01:24:45 +00:00
xmlRelaxNGDefinePtr cur , * tmp ;
2003-03-16 17:52:32 +00:00
xmlRelaxNGPartitionPtr partitions = NULL ;
xmlRelaxNGInterleaveGroupPtr * groups = NULL ;
xmlRelaxNGInterleaveGroupPtr group ;
2003-10-07 11:33:24 +00:00
int i , j , ret , res ;
2003-03-16 17:52:32 +00:00
int nbgroups = 0 ;
int nbchild = 0 ;
2003-03-19 21:02:29 +00:00
int is_mixed = 0 ;
2003-03-21 01:24:45 +00:00
int is_determinist = 1 ;
2003-03-16 17:52:32 +00:00
/*
* Don ' t run that check in case of error . Infinite recursion
* becomes possible .
*/
if ( ctxt - > nbErrors ! = 0 )
2003-10-07 11:33:24 +00:00
return ;
2003-03-16 17:52:32 +00:00
# ifdef DEBUG_INTERLEAVE
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" xmlRelaxNGComputeInterleaves(%s) \n " , name ) ;
2003-03-16 17:52:32 +00:00
# endif
cur = def - > content ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
nbchild + + ;
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
2003-10-07 11:33:24 +00:00
2003-03-16 17:52:32 +00:00
# ifdef DEBUG_INTERLEAVE
xmlGenericError ( xmlGenericErrorContext , " %d child \n " , nbchild ) ;
# endif
groups = ( xmlRelaxNGInterleaveGroupPtr * )
2003-10-07 11:33:24 +00:00
xmlMalloc ( nbchild * sizeof ( xmlRelaxNGInterleaveGroupPtr ) ) ;
2003-03-16 17:52:32 +00:00
if ( groups = = NULL )
2003-10-07 11:33:24 +00:00
goto error ;
2003-03-16 17:52:32 +00:00
cur = def - > content ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
groups [ nbgroups ] = ( xmlRelaxNGInterleaveGroupPtr )
xmlMalloc ( sizeof ( xmlRelaxNGInterleaveGroup ) ) ;
if ( groups [ nbgroups ] = = NULL )
goto error ;
if ( cur - > type = = XML_RELAXNG_TEXT )
is_mixed + + ;
groups [ nbgroups ] - > rule = cur ;
2018-11-22 18:09:51 +01:00
groups [ nbgroups ] - > defs = xmlRelaxNGGetElements ( ctxt , cur , 2 ) ;
2003-10-07 11:33:24 +00:00
groups [ nbgroups ] - > attrs = xmlRelaxNGGetElements ( ctxt , cur , 1 ) ;
nbgroups + + ;
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
# ifdef DEBUG_INTERLEAVE
xmlGenericError ( xmlGenericErrorContext , " %d groups \n " , nbgroups ) ;
# endif
/*
* Let ' s check that all rules makes a partitions according to 7.4
*/
partitions = ( xmlRelaxNGPartitionPtr )
2003-10-07 11:33:24 +00:00
xmlMalloc ( sizeof ( xmlRelaxNGPartition ) ) ;
2003-03-16 17:52:32 +00:00
if ( partitions = = NULL )
goto error ;
2003-03-22 17:51:47 +00:00
memset ( partitions , 0 , sizeof ( xmlRelaxNGPartition ) ) ;
2003-03-16 17:52:32 +00:00
partitions - > nbgroups = nbgroups ;
2003-03-21 01:24:45 +00:00
partitions - > triage = xmlHashCreate ( nbgroups ) ;
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < nbgroups ; i + + ) {
group = groups [ i ] ;
for ( j = i + 1 ; j < nbgroups ; j + + ) {
if ( groups [ j ] = = NULL )
continue ;
ret = xmlRelaxNGCompareElemDefLists ( ctxt , group - > defs ,
groups [ j ] - > defs ) ;
if ( ret = = 0 ) {
xmlRngPErr ( ctxt , def - > node , XML_RNGP_ELEM_TEXT_CONFLICT ,
" Element or text conflicts in interleave \n " ,
NULL , NULL ) ;
}
ret = xmlRelaxNGCompareElemDefLists ( ctxt , group - > attrs ,
groups [ j ] - > attrs ) ;
if ( ret = = 0 ) {
xmlRngPErr ( ctxt , def - > node , XML_RNGP_ATTR_CONFLICT ,
" Attributes conflicts in interleave \n " , NULL ,
NULL ) ;
}
}
tmp = group - > defs ;
if ( ( tmp ! = NULL ) & & ( * tmp ! = NULL ) ) {
while ( * tmp ! = NULL ) {
if ( ( * tmp ) - > type = = XML_RELAXNG_TEXT ) {
res = xmlHashAddEntry2 ( partitions - > triage ,
BAD_CAST " #text " , NULL ,
2017-10-09 13:37:42 +02:00
( void * ) ( ptrdiff_t ) ( i + 1 ) ) ;
2003-10-07 11:33:24 +00:00
if ( res ! = 0 )
is_determinist = - 1 ;
} else if ( ( ( * tmp ) - > type = = XML_RELAXNG_ELEMENT ) & &
( ( * tmp ) - > name ! = NULL ) ) {
if ( ( ( * tmp ) - > ns = = NULL ) | | ( ( * tmp ) - > ns [ 0 ] = = 0 ) )
res = xmlHashAddEntry2 ( partitions - > triage ,
( * tmp ) - > name , NULL ,
2017-10-09 13:37:42 +02:00
( void * ) ( ptrdiff_t ) ( i + 1 ) ) ;
2003-10-07 11:33:24 +00:00
else
res = xmlHashAddEntry2 ( partitions - > triage ,
( * tmp ) - > name , ( * tmp ) - > ns ,
2017-10-09 13:37:42 +02:00
( void * ) ( ptrdiff_t ) ( i + 1 ) ) ;
2003-10-07 11:33:24 +00:00
if ( res ! = 0 )
is_determinist = - 1 ;
} else if ( ( * tmp ) - > type = = XML_RELAXNG_ELEMENT ) {
if ( ( ( * tmp ) - > ns = = NULL ) | | ( ( * tmp ) - > ns [ 0 ] = = 0 ) )
res = xmlHashAddEntry2 ( partitions - > triage ,
BAD_CAST " #any " , NULL ,
2017-10-09 13:37:42 +02:00
( void * ) ( ptrdiff_t ) ( i + 1 ) ) ;
2003-10-07 11:33:24 +00:00
else
res = xmlHashAddEntry2 ( partitions - > triage ,
BAD_CAST " #any " , ( * tmp ) - > ns ,
2017-10-09 13:37:42 +02:00
( void * ) ( ptrdiff_t ) ( i + 1 ) ) ;
2003-10-07 11:33:24 +00:00
if ( ( * tmp ) - > nameClass ! = NULL )
is_determinist = 2 ;
if ( res ! = 0 )
is_determinist = - 1 ;
} else {
is_determinist = - 1 ;
}
tmp + + ;
}
} else {
is_determinist = 0 ;
}
2003-03-16 17:52:32 +00:00
}
partitions - > groups = groups ;
/*
* and save the partition list back in the def
*/
def - > data = partitions ;
2003-03-19 21:02:29 +00:00
if ( is_mixed ! = 0 )
2003-10-07 11:33:24 +00:00
def - > dflags | = IS_MIXED ;
2003-03-21 01:24:45 +00:00
if ( is_determinist = = 1 )
2003-10-07 11:33:24 +00:00
partitions - > flags = IS_DETERMINIST ;
2003-03-21 01:24:45 +00:00
if ( is_determinist = = 2 )
2003-10-07 11:33:24 +00:00
partitions - > flags = IS_DETERMINIST | IS_NEEDCHECK ;
2003-03-16 17:52:32 +00:00
return ;
2003-10-07 11:33:24 +00:00
error :
xmlRngPErrMemory ( ctxt , " in interleave computation \n " ) ;
2003-03-16 17:52:32 +00:00
if ( groups ! = NULL ) {
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < nbgroups ; i + + )
if ( groups [ i ] ! = NULL ) {
if ( groups [ i ] - > defs ! = NULL )
xmlFree ( groups [ i ] - > defs ) ;
xmlFree ( groups [ i ] ) ;
}
xmlFree ( groups ) ;
2003-01-28 20:58:15 +00:00
}
2003-03-16 17:52:32 +00:00
xmlRelaxNGFreePartition ( partitions ) ;
2003-01-28 20:58:15 +00:00
}
/**
* xmlRelaxNGParseInterleave :
* @ ctxt : a Relax - NG parser context
* @ node : the data node .
*
* parse the content of a RelaxNG interleave node .
*
* Returns the definition pointer or NULL in case of error
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseInterleave ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-01-28 20:58:15 +00:00
xmlRelaxNGDefinePtr def = NULL ;
2003-03-16 17:52:32 +00:00
xmlRelaxNGDefinePtr last = NULL , cur ;
2003-01-28 20:58:15 +00:00
xmlNodePtr child ;
2003-03-16 17:52:32 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL ) {
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-03-16 17:52:32 +00:00
}
def - > type = XML_RELAXNG_INTERLEAVE ;
if ( ctxt - > interleaves = = NULL )
2003-10-07 11:33:24 +00:00
ctxt - > interleaves = xmlHashCreate ( 10 ) ;
2003-03-16 17:52:32 +00:00
if ( ctxt - > interleaves = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( ctxt , " create interleaves \n " ) ;
2003-01-28 20:58:15 +00:00
} else {
2003-10-07 11:33:24 +00:00
char name [ 32 ] ;
2003-01-28 20:58:15 +00:00
2003-10-07 11:33:24 +00:00
snprintf ( name , 32 , " interleave%d " , ctxt - > nbInterleaves + + ) ;
if ( xmlHashAddEntry ( ctxt - > interleaves , BAD_CAST name , def ) < 0 ) {
xmlRngPErr ( ctxt , node , XML_RNGP_INTERLEAVE_ADD ,
" Failed to add %s to hash table \n " ,
( const xmlChar * ) name , NULL ) ;
}
2003-01-28 20:58:15 +00:00
}
2003-03-16 17:52:32 +00:00
child = node - > children ;
if ( child = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_INTERLEAVE_NO_CONTENT ,
" Element interleave is empty \n " , NULL , NULL ) ;
2003-03-16 17:52:32 +00:00
}
while ( child ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( IS_RELAXNG ( child , " element " ) ) {
cur = xmlRelaxNGParseElement ( ctxt , child ) ;
} else {
cur = xmlRelaxNGParsePattern ( ctxt , child ) ;
}
if ( cur ! = NULL ) {
cur - > parent = def ;
if ( last = = NULL ) {
def - > content = last = cur ;
} else {
last - > next = cur ;
last = cur ;
}
}
child = child - > next ;
2003-03-16 17:52:32 +00:00
}
2003-10-07 11:33:24 +00:00
return ( def ) ;
2003-01-28 20:58:15 +00:00
}
2003-01-23 18:29:16 +00:00
2003-02-02 14:35:17 +00:00
/**
* xmlRelaxNGParseInclude :
* @ ctxt : a Relax - NG parser context
* @ node : the include node
*
* Integrate the content of an include node in the current grammar
*
* Returns 0 in case of success or - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseInclude ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-02-02 14:35:17 +00:00
xmlRelaxNGIncludePtr incl ;
xmlNodePtr root ;
int ret = 0 , tmp ;
2004-02-22 22:13:27 +00:00
incl = node - > psvi ;
2003-02-02 14:35:17 +00:00
if ( incl = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_INCLUDE_EMPTY ,
" Include node has no data \n " , NULL , NULL ) ;
return ( - 1 ) ;
2003-02-02 14:35:17 +00:00
}
root = xmlDocGetRootElement ( incl - > doc ) ;
if ( root = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY , " Include document is empty \n " ,
NULL , NULL ) ;
return ( - 1 ) ;
2003-02-02 14:35:17 +00:00
}
if ( ! xmlStrEqual ( root - > name , BAD_CAST " grammar " ) ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_GRAMMAR_MISSING ,
" Include document root is not a grammar \n " , NULL , NULL ) ;
return ( - 1 ) ;
2003-02-02 14:35:17 +00:00
}
/*
* Merge the definition from both the include and the internal list
*/
if ( root - > children ! = NULL ) {
2003-10-07 11:33:24 +00:00
tmp = xmlRelaxNGParseGrammarContent ( ctxt , root - > children ) ;
if ( tmp ! = 0 )
ret = - 1 ;
2003-02-02 14:35:17 +00:00
}
if ( node - > children ! = NULL ) {
2003-10-07 11:33:24 +00:00
tmp = xmlRelaxNGParseGrammarContent ( ctxt , node - > children ) ;
if ( tmp ! = 0 )
ret = - 1 ;
2003-02-02 14:35:17 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-02-02 14:35:17 +00:00
}
2003-01-24 01:03:34 +00:00
/**
* xmlRelaxNGParseDefine :
* @ ctxt : a Relax - NG parser context
* @ node : the define node
*
* parse the content of a RelaxNG define element node .
*
2003-02-02 14:35:17 +00:00
* Returns 0 in case of success or - 1 in case of error
2003-01-24 01:03:34 +00:00
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseDefine ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-01-24 01:03:34 +00:00
xmlChar * name ;
int ret = 0 , tmp ;
xmlRelaxNGDefinePtr def ;
const xmlChar * olddefine ;
name = xmlGetProp ( node , BAD_CAST " name " ) ;
if ( name = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_DEFINE_NAME_MISSING ,
" define has no name \n " , NULL , NULL ) ;
2003-01-24 01:03:34 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRelaxNGNormExtSpace ( name ) ;
if ( xmlValidateNCName ( name , 0 ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_INVALID_DEFINE_NAME ,
" define name '%s' is not an NCName \n " , name , NULL ) ;
}
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL ) {
xmlFree ( name ) ;
return ( - 1 ) ;
}
def - > type = XML_RELAXNG_DEF ;
def - > name = name ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_DEFINE_EMPTY ,
" define has no children \n " , NULL , NULL ) ;
} else {
olddefine = ctxt - > define ;
ctxt - > define = name ;
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 0 ) ;
ctxt - > define = olddefine ;
}
if ( ctxt - > grammar - > defs = = NULL )
ctxt - > grammar - > defs = xmlHashCreate ( 10 ) ;
if ( ctxt - > grammar - > defs = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_DEFINE_CREATE_FAILED ,
" Could not create definition hash \n " , NULL , NULL ) ;
ret = - 1 ;
} else {
tmp = xmlHashAddEntry ( ctxt - > grammar - > defs , name , def ) ;
if ( tmp < 0 ) {
xmlRelaxNGDefinePtr prev ;
prev = xmlHashLookup ( ctxt - > grammar - > defs , name ) ;
if ( prev = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_DEFINE_CREATE_FAILED ,
" Internal error on define aggregation of %s \n " ,
name , NULL ) ;
ret = - 1 ;
} else {
while ( prev - > nextHash ! = NULL )
prev = prev - > nextHash ;
prev - > nextHash = def ;
}
}
}
}
return ( ret ) ;
2003-01-24 01:03:34 +00:00
}
2009-08-14 18:52:10 +02:00
/**
* xmlRelaxNGParseImportRef :
* @ payload : the parser context
* @ data : the current grammar
* @ name : the reference name
*
* Import import one references into the current grammar
*/
static void
2017-11-09 16:42:47 +01:00
xmlRelaxNGParseImportRef ( void * payload , void * data , const xmlChar * name ) {
2009-08-14 18:52:10 +02:00
xmlRelaxNGParserCtxtPtr ctxt = ( xmlRelaxNGParserCtxtPtr ) data ;
xmlRelaxNGDefinePtr def = ( xmlRelaxNGDefinePtr ) payload ;
int tmp ;
2009-09-24 11:31:48 +02:00
def - > dflags | = IS_EXTERNAL_REF ;
2009-08-14 18:52:10 +02:00
tmp = xmlHashAddEntry ( ctxt - > grammar - > refs , name , def ) ;
if ( tmp < 0 ) {
xmlRelaxNGDefinePtr prev ;
prev = ( xmlRelaxNGDefinePtr )
xmlHashLookup ( ctxt - > grammar - > refs , def - > name ) ;
if ( prev = = NULL ) {
if ( def - > name ! = NULL ) {
xmlRngPErr ( ctxt , NULL , XML_RNGP_REF_CREATE_FAILED ,
" Error refs definitions '%s' \n " ,
def - > name , NULL ) ;
} else {
xmlRngPErr ( ctxt , NULL , XML_RNGP_REF_CREATE_FAILED ,
" Error refs definitions \n " ,
NULL , NULL ) ;
}
} else {
def - > nextHash = prev - > nextHash ;
prev - > nextHash = def ;
}
}
}
/**
* xmlRelaxNGParseImportRefs :
* @ ctxt : the parser context
* @ grammar : the sub grammar
*
* Import references from the subgrammar into the current grammar
*
* Returns 0 in case of success , - 1 in case of failure
*/
static int
xmlRelaxNGParseImportRefs ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlRelaxNGGrammarPtr grammar ) {
if ( ( ctxt = = NULL ) | | ( grammar = = NULL ) | | ( ctxt - > grammar = = NULL ) )
return ( - 1 ) ;
if ( grammar - > refs = = NULL )
return ( 0 ) ;
if ( ctxt - > grammar - > refs = = NULL )
ctxt - > grammar - > refs = xmlHashCreate ( 10 ) ;
if ( ctxt - > grammar - > refs = = NULL ) {
xmlRngPErr ( ctxt , NULL , XML_RNGP_REF_CREATE_FAILED ,
" Could not create references hash \n " , NULL , NULL ) ;
return ( - 1 ) ;
}
xmlHashScan ( grammar - > refs , xmlRelaxNGParseImportRef , ctxt ) ;
2009-08-26 18:37:43 +02:00
return ( 0 ) ;
2009-08-14 18:52:10 +02:00
}
2003-02-16 15:44:18 +00:00
/**
* xmlRelaxNGProcessExternalRef :
* @ ctxt : the parser context
2019-09-30 17:04:54 +02:00
* @ node : the externalRef node
2003-02-16 15:44:18 +00:00
*
2019-09-30 17:04:54 +02:00
* Process and compile an externalRef node
2003-02-16 15:44:18 +00:00
*
* Returns the xmlRelaxNGDefinePtr or NULL in case of error
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGProcessExternalRef ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-02-16 15:44:18 +00:00
xmlRelaxNGDocumentPtr docu ;
xmlNodePtr root , tmp ;
xmlChar * ns ;
2003-02-20 15:03:22 +00:00
int newNs = 0 , oldflags ;
2003-02-16 15:44:18 +00:00
xmlRelaxNGDefinePtr def ;
2004-02-22 22:13:27 +00:00
docu = node - > psvi ;
2003-02-16 15:44:18 +00:00
if ( docu ! = NULL ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_EXTERNALREF ;
if ( docu - > content = = NULL ) {
/*
* Then do the parsing for good
*/
root = xmlDocGetRootElement ( docu - > doc ) ;
if ( root = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EXTERNALREF_EMTPY ,
" xmlRelaxNGParse: %s is empty \n " , ctxt - > URL ,
NULL ) ;
return ( NULL ) ;
}
/*
* ns transmission rules
*/
ns = xmlGetProp ( root , BAD_CAST " ns " ) ;
if ( ns = = NULL ) {
tmp = node ;
while ( ( tmp ! = NULL ) & & ( tmp - > type = = XML_ELEMENT_NODE ) ) {
ns = xmlGetProp ( tmp , BAD_CAST " ns " ) ;
if ( ns ! = NULL ) {
break ;
}
tmp = tmp - > parent ;
}
if ( ns ! = NULL ) {
xmlSetProp ( root , BAD_CAST " ns " , ns ) ;
newNs = 1 ;
xmlFree ( ns ) ;
}
} else {
xmlFree ( ns ) ;
}
/*
* Parsing to get a precompiled schemas .
*/
oldflags = ctxt - > flags ;
ctxt - > flags | = XML_RELAXNG_IN_EXTERNALREF ;
docu - > schema = xmlRelaxNGParseDocument ( ctxt , root ) ;
ctxt - > flags = oldflags ;
if ( ( docu - > schema ! = NULL ) & &
( docu - > schema - > topgrammar ! = NULL ) ) {
docu - > content = docu - > schema - > topgrammar - > start ;
2009-08-14 18:52:10 +02:00
if ( docu - > schema - > topgrammar - > refs )
xmlRelaxNGParseImportRefs ( ctxt , docu - > schema - > topgrammar ) ;
2003-10-07 11:33:24 +00:00
}
/*
* the externalRef may be reused in a different ns context
*/
if ( newNs = = 1 ) {
xmlUnsetProp ( root , BAD_CAST " ns " ) ;
}
}
def - > content = docu - > content ;
2003-02-16 15:44:18 +00:00
} else {
2003-10-07 11:33:24 +00:00
def = NULL ;
2003-02-16 15:44:18 +00:00
}
2003-10-07 11:33:24 +00:00
return ( def ) ;
2003-02-16 15:44:18 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGParsePattern :
* @ ctxt : a Relax - NG parser context
* @ node : the pattern node .
*
* parse the content of a RelaxNG pattern node .
*
2003-01-24 01:03:34 +00:00
* Returns the definition pointer or NULL in case of error or if no
* pattern is generated .
2003-01-23 18:29:16 +00:00
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParsePattern ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGDefinePtr def = NULL ;
2003-02-14 16:54:11 +00:00
if ( node = = NULL ) {
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-02-14 16:54:11 +00:00
}
2003-01-23 18:29:16 +00:00
if ( IS_RELAXNG ( node , " element " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGParseElement ( ctxt , node ) ;
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " attribute " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGParseAttribute ( ctxt , node ) ;
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " empty " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_EMPTY ;
if ( node - > children ! = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_NOT_EMPTY ,
" empty: had a child node \n " , NULL , NULL ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " text " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_TEXT ;
if ( node - > children ! = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_TEXT_HAS_CHILD ,
" text: had a child node \n " , NULL , NULL ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " zeroOrMore " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_ZEROORMORE ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT ,
" Element %s is empty \n " , node - > name , NULL ) ;
} else {
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 1 ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " oneOrMore " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_ONEORMORE ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT ,
" Element %s is empty \n " , node - > name , NULL ) ;
} else {
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 1 ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " optional " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_OPTIONAL ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT ,
" Element %s is empty \n " , node - > name , NULL ) ;
} else {
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 1 ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " choice " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_CHOICE ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT ,
" Element %s is empty \n " , node - > name , NULL ) ;
} else {
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 0 ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " group " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_GROUP ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT ,
" Element %s is empty \n " , node - > name , NULL ) ;
} else {
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 0 ) ;
}
2003-01-23 18:29:16 +00:00
} else if ( IS_RELAXNG ( node , " ref " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_REF ;
def - > name = xmlGetProp ( node , BAD_CAST " name " ) ;
if ( def - > name = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_REF_NO_NAME , " ref has no name \n " ,
NULL , NULL ) ;
} else {
xmlRelaxNGNormExtSpace ( def - > name ) ;
if ( xmlValidateNCName ( def - > name , 0 ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_REF_NAME_INVALID ,
" ref name '%s' is not an NCName \n " , def - > name ,
NULL ) ;
}
}
if ( node - > children ! = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_REF_NOT_EMPTY , " ref is not empty \n " ,
NULL , NULL ) ;
}
if ( ctxt - > grammar - > refs = = NULL )
ctxt - > grammar - > refs = xmlHashCreate ( 10 ) ;
if ( ctxt - > grammar - > refs = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_REF_CREATE_FAILED ,
" Could not create references hash \n " , NULL , NULL ) ;
def = NULL ;
} else {
int tmp ;
tmp = xmlHashAddEntry ( ctxt - > grammar - > refs , def - > name , def ) ;
if ( tmp < 0 ) {
xmlRelaxNGDefinePtr prev ;
prev = ( xmlRelaxNGDefinePtr )
xmlHashLookup ( ctxt - > grammar - > refs , def - > name ) ;
if ( prev = = NULL ) {
if ( def - > name ! = NULL ) {
2003-10-07 12:17:44 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_REF_CREATE_FAILED ,
" Error refs definitions '%s' \n " ,
def - > name , NULL ) ;
2003-10-07 11:33:24 +00:00
} else {
2003-10-07 12:17:44 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_REF_CREATE_FAILED ,
" Error refs definitions \n " ,
NULL , NULL ) ;
2003-10-07 11:33:24 +00:00
}
def = NULL ;
} else {
def - > nextHash = prev - > nextHash ;
prev - > nextHash = def ;
}
}
}
2003-01-25 18:01:32 +00:00
} else if ( IS_RELAXNG ( node , " data " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGParseData ( ctxt , node ) ;
2003-01-26 00:52:04 +00:00
} else if ( IS_RELAXNG ( node , " value " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGParseValue ( ctxt , node ) ;
2003-01-27 12:35:42 +00:00
} else if ( IS_RELAXNG ( node , " list " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_LIST ;
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT ,
" Element %s is empty \n " , node - > name , NULL ) ;
} else {
def - > content =
xmlRelaxNGParsePatterns ( ctxt , node - > children , 0 ) ;
}
2003-03-16 17:52:32 +00:00
} else if ( IS_RELAXNG ( node , " interleave " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGParseInterleave ( ctxt , node ) ;
2003-01-29 21:07:52 +00:00
} else if ( IS_RELAXNG ( node , " externalRef " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGProcessExternalRef ( ctxt , node ) ;
2003-02-02 14:35:17 +00:00
} else if ( IS_RELAXNG ( node , " notAllowed " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_NOT_ALLOWED ;
if ( node - > children ! = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_NOTALLOWED_NOT_EMPTY ,
" xmlRelaxNGParse: notAllowed element is not empty \n " ,
NULL , NULL ) ;
}
2003-02-03 23:22:49 +00:00
} else if ( IS_RELAXNG ( node , " grammar " ) ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGGrammarPtr grammar , old ;
xmlRelaxNGGrammarPtr oldparent ;
2003-02-03 23:22:49 +00:00
2003-02-26 14:48:48 +00:00
# ifdef DEBUG_GRAMMAR
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Found <grammar> pattern \n " ) ;
2003-02-26 14:48:48 +00:00
# endif
2003-10-07 11:33:24 +00:00
oldparent = ctxt - > parentgrammar ;
old = ctxt - > grammar ;
ctxt - > parentgrammar = old ;
grammar = xmlRelaxNGParseGrammar ( ctxt , node - > children ) ;
if ( old ! = NULL ) {
ctxt - > grammar = old ;
ctxt - > parentgrammar = oldparent ;
2003-02-26 14:48:48 +00:00
#if 0
2003-10-07 11:33:24 +00:00
if ( grammar ! = NULL ) {
grammar - > next = old - > next ;
old - > next = grammar ;
}
2003-02-26 14:48:48 +00:00
# endif
2003-10-07 11:33:24 +00:00
}
if ( grammar ! = NULL )
def = grammar - > start ;
else
def = NULL ;
2003-02-03 23:22:49 +00:00
} else if ( IS_RELAXNG ( node , " parentRef " ) ) {
2003-10-07 11:33:24 +00:00
if ( ctxt - > parentgrammar = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARENTREF_NO_PARENT ,
" Use of parentRef without a parent grammar \n " , NULL ,
NULL ) ;
return ( NULL ) ;
}
def = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( def = = NULL )
return ( NULL ) ;
def - > type = XML_RELAXNG_PARENTREF ;
def - > name = xmlGetProp ( node , BAD_CAST " name " ) ;
if ( def - > name = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARENTREF_NO_NAME ,
" parentRef has no name \n " , NULL , NULL ) ;
} else {
xmlRelaxNGNormExtSpace ( def - > name ) ;
if ( xmlValidateNCName ( def - > name , 0 ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARENTREF_NAME_INVALID ,
" parentRef name '%s' is not an NCName \n " ,
def - > name , NULL ) ;
}
}
if ( node - > children ! = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARENTREF_NOT_EMPTY ,
" parentRef is not empty \n " , NULL , NULL ) ;
}
if ( ctxt - > parentgrammar - > refs = = NULL )
ctxt - > parentgrammar - > refs = xmlHashCreate ( 10 ) ;
if ( ctxt - > parentgrammar - > refs = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARENTREF_CREATE_FAILED ,
" Could not create references hash \n " , NULL , NULL ) ;
def = NULL ;
} else if ( def - > name ! = NULL ) {
int tmp ;
tmp =
xmlHashAddEntry ( ctxt - > parentgrammar - > refs , def - > name , def ) ;
if ( tmp < 0 ) {
xmlRelaxNGDefinePtr prev ;
prev = ( xmlRelaxNGDefinePtr )
xmlHashLookup ( ctxt - > parentgrammar - > refs , def - > name ) ;
if ( prev = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_PARENTREF_CREATE_FAILED ,
" Internal error parentRef definitions '%s' \n " ,
def - > name , NULL ) ;
def = NULL ;
} else {
def - > nextHash = prev - > nextHash ;
prev - > nextHash = def ;
}
}
}
2003-02-14 16:54:11 +00:00
} else if ( IS_RELAXNG ( node , " mixed " ) ) {
2003-10-07 11:33:24 +00:00
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_EMPTY_CONSTRUCT , " Mixed is empty \n " ,
NULL , NULL ) ;
def = NULL ;
} else {
def = xmlRelaxNGParseInterleave ( ctxt , node ) ;
if ( def ! = NULL ) {
xmlRelaxNGDefinePtr tmp ;
if ( ( def - > content ! = NULL ) & & ( def - > content - > next ! = NULL ) ) {
tmp = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( tmp ! = NULL ) {
tmp - > type = XML_RELAXNG_GROUP ;
tmp - > content = def - > content ;
def - > content = tmp ;
}
}
tmp = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( tmp = = NULL )
return ( def ) ;
tmp - > type = XML_RELAXNG_TEXT ;
tmp - > next = def - > content ;
def - > content = tmp ;
}
}
2003-02-14 16:54:11 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_UNKNOWN_CONSTRUCT ,
" Unexpected node %s is not a pattern \n " , node - > name ,
NULL ) ;
def = NULL ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( def ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGParseAttribute :
* @ ctxt : a Relax - NG parser context
* @ node : the element node
*
* parse the content of a RelaxNG attribute node .
*
* Returns the definition pointer or NULL in case of error .
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseAttribute ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-02-14 16:54:11 +00:00
xmlRelaxNGDefinePtr ret , cur ;
2003-01-23 18:29:16 +00:00
xmlNodePtr child ;
int old_flags ;
2003-03-16 17:52:32 +00:00
ret = xmlRelaxNGNewDefine ( ctxt , node ) ;
2003-01-23 18:29:16 +00:00
if ( ret = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-03-16 17:52:32 +00:00
ret - > type = XML_RELAXNG_ATTRIBUTE ;
2003-01-28 20:58:15 +00:00
ret - > parent = ctxt - > def ;
2003-01-23 18:29:16 +00:00
child = node - > children ;
if ( child = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_ATTRIBUTE_EMPTY ,
" xmlRelaxNGParseattribute: attribute has no children \n " ,
NULL , NULL ) ;
return ( ret ) ;
}
2003-01-23 18:29:16 +00:00
old_flags = ctxt - > flags ;
ctxt - > flags | = XML_RELAXNG_IN_ATTRIBUTE ;
2003-02-03 08:52:58 +00:00
cur = xmlRelaxNGParseNameClass ( ctxt , child , ret ) ;
if ( cur ! = NULL )
2003-10-07 11:33:24 +00:00
child = child - > next ;
2003-02-03 08:52:58 +00:00
2003-02-14 16:54:11 +00:00
if ( child ! = NULL ) {
2003-10-07 11:33:24 +00:00
cur = xmlRelaxNGParsePattern ( ctxt , child ) ;
if ( cur ! = NULL ) {
switch ( cur - > type ) {
case XML_RELAXNG_EMPTY :
case XML_RELAXNG_NOT_ALLOWED :
case XML_RELAXNG_TEXT :
case XML_RELAXNG_ELEMENT :
case XML_RELAXNG_DATATYPE :
case XML_RELAXNG_VALUE :
case XML_RELAXNG_LIST :
case XML_RELAXNG_REF :
case XML_RELAXNG_PARENTREF :
case XML_RELAXNG_EXTERNALREF :
case XML_RELAXNG_DEF :
case XML_RELAXNG_ONEORMORE :
case XML_RELAXNG_ZEROORMORE :
case XML_RELAXNG_OPTIONAL :
case XML_RELAXNG_CHOICE :
case XML_RELAXNG_GROUP :
case XML_RELAXNG_INTERLEAVE :
case XML_RELAXNG_ATTRIBUTE :
ret - > content = cur ;
cur - > parent = ret ;
break ;
case XML_RELAXNG_START :
case XML_RELAXNG_PARAM :
case XML_RELAXNG_EXCEPT :
xmlRngPErr ( ctxt , node , XML_RNGP_ATTRIBUTE_CONTENT ,
" attribute has invalid content \n " , NULL ,
NULL ) ;
break ;
case XML_RELAXNG_NOOP :
xmlRngPErr ( ctxt , node , XML_RNGP_ATTRIBUTE_NOOP ,
" RNG Internal error, noop found in attribute \n " ,
NULL , NULL ) ;
break ;
}
}
child = child - > next ;
2003-01-23 18:29:16 +00:00
}
2003-02-14 16:54:11 +00:00
if ( child ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_ATTRIBUTE_CHILDREN ,
" attribute has multiple children \n " , NULL , NULL ) ;
2003-02-14 16:54:11 +00:00
}
2003-01-23 18:29:16 +00:00
ctxt - > flags = old_flags ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
2003-02-03 08:52:58 +00:00
/**
* xmlRelaxNGParseExceptNameClass :
* @ ctxt : a Relax - NG parser context
* @ node : the except node
2003-02-03 13:17:57 +00:00
* @ attr : 1 if within an attribute , 0 if within an element
2003-02-03 08:52:58 +00:00
*
* parse the content of a RelaxNG nameClass node .
*
* Returns the definition pointer or NULL in case of error .
*/
static xmlRelaxNGDefinePtr
2003-02-03 13:17:57 +00:00
xmlRelaxNGParseExceptNameClass ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlNodePtr node , int attr )
{
2003-02-03 13:17:57 +00:00
xmlRelaxNGDefinePtr ret , cur , last = NULL ;
xmlNodePtr child ;
2003-02-14 16:54:11 +00:00
if ( ! IS_RELAXNG ( node , " except " ) ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_EXCEPT_MISSING ,
" Expecting an except node \n " , NULL , NULL ) ;
return ( NULL ) ;
2003-02-14 16:54:11 +00:00
}
if ( node - > next ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_EXCEPT_MULTIPLE ,
" exceptNameClass allows only a single except node \n " ,
NULL , NULL ) ;
2003-02-14 16:54:11 +00:00
}
2003-02-03 13:17:57 +00:00
if ( node - > children = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_EXCEPT_EMPTY , " except has no content \n " ,
NULL , NULL ) ;
return ( NULL ) ;
2003-02-03 13:17:57 +00:00
}
2003-03-16 17:52:32 +00:00
ret = xmlRelaxNGNewDefine ( ctxt , node ) ;
2003-02-03 13:17:57 +00:00
if ( ret = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-03-16 17:52:32 +00:00
ret - > type = XML_RELAXNG_EXCEPT ;
2003-02-03 13:17:57 +00:00
child = node - > children ;
while ( child ! = NULL ) {
2003-10-07 11:33:24 +00:00
cur = xmlRelaxNGNewDefine ( ctxt , child ) ;
if ( cur = = NULL )
break ;
if ( attr )
cur - > type = XML_RELAXNG_ATTRIBUTE ;
else
cur - > type = XML_RELAXNG_ELEMENT ;
2003-02-03 23:22:49 +00:00
if ( xmlRelaxNGParseNameClass ( ctxt , child , cur ) ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( last = = NULL ) {
ret - > content = cur ;
} else {
last - > next = cur ;
}
last = cur ;
}
child = child - > next ;
2003-02-03 13:17:57 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-02-03 08:52:58 +00:00
}
/**
* xmlRelaxNGParseNameClass :
* @ ctxt : a Relax - NG parser context
* @ node : the nameClass node
* @ def : the current definition
*
* parse the content of a RelaxNG nameClass node .
*
* Returns the definition pointer or NULL in case of error .
*/
static xmlRelaxNGDefinePtr
xmlRelaxNGParseNameClass ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def )
{
2003-03-16 17:52:32 +00:00
xmlRelaxNGDefinePtr ret , tmp ;
2003-02-03 08:52:58 +00:00
xmlChar * val ;
2003-02-19 13:29:45 +00:00
ret = def ;
2003-10-07 11:33:24 +00:00
if ( ( IS_RELAXNG ( node , " name " ) ) | | ( IS_RELAXNG ( node , " anyName " ) ) | |
2003-02-19 13:29:45 +00:00
( IS_RELAXNG ( node , " nsName " ) ) ) {
2003-10-07 11:33:24 +00:00
if ( ( def - > type ! = XML_RELAXNG_ELEMENT ) & &
( def - > type ! = XML_RELAXNG_ATTRIBUTE ) ) {
ret = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( ret = = NULL )
return ( NULL ) ;
ret - > parent = def ;
if ( ctxt - > flags & XML_RELAXNG_IN_ATTRIBUTE )
ret - > type = XML_RELAXNG_ATTRIBUTE ;
else
ret - > type = XML_RELAXNG_ELEMENT ;
}
2003-02-19 13:29:45 +00:00
}
2003-02-03 08:52:58 +00:00
if ( IS_RELAXNG ( node , " name " ) ) {
2003-10-07 11:33:24 +00:00
val = xmlNodeGetContent ( node ) ;
xmlRelaxNGNormExtSpace ( val ) ;
if ( xmlValidateNCName ( val , 0 ) ) {
2003-10-07 12:17:44 +00:00
if ( node - > parent ! = NULL )
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_NAME ,
" Element %s name '%s' is not an NCName \n " ,
node - > parent - > name , val ) ;
else
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_NAME ,
" name '%s' is not an NCName \n " ,
val , NULL ) ;
2003-10-07 11:33:24 +00:00
}
ret - > name = val ;
val = xmlGetProp ( node , BAD_CAST " ns " ) ;
ret - > ns = val ;
if ( ( ctxt - > flags & XML_RELAXNG_IN_ATTRIBUTE ) & &
( val ! = NULL ) & &
( xmlStrEqual ( val , BAD_CAST " http://www.w3.org/2000/xmlns " ) ) ) {
2003-10-07 12:17:44 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_XML_NS ,
2003-10-07 11:33:24 +00:00
" Attribute with namespace '%s' is not allowed \n " ,
2003-10-07 12:17:44 +00:00
val , NULL ) ;
2003-10-07 11:33:24 +00:00
}
if ( ( ctxt - > flags & XML_RELAXNG_IN_ATTRIBUTE ) & &
( val ! = NULL ) & &
( val [ 0 ] = = 0 ) & & ( xmlStrEqual ( ret - > name , BAD_CAST " xmlns " ) ) ) {
2003-10-07 12:17:44 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_XMLNS_NAME ,
" Attribute with QName 'xmlns' is not allowed \n " ,
val , NULL ) ;
2003-10-07 11:33:24 +00:00
}
2003-02-03 08:52:58 +00:00
} else if ( IS_RELAXNG ( node , " anyName " ) ) {
2003-10-07 11:33:24 +00:00
ret - > name = NULL ;
ret - > ns = NULL ;
if ( node - > children ! = NULL ) {
ret - > nameClass =
xmlRelaxNGParseExceptNameClass ( ctxt , node - > children ,
( def - > type = =
XML_RELAXNG_ATTRIBUTE ) ) ;
}
2003-02-03 08:52:58 +00:00
} else if ( IS_RELAXNG ( node , " nsName " ) ) {
2003-10-07 11:33:24 +00:00
ret - > name = NULL ;
ret - > ns = xmlGetProp ( node , BAD_CAST " ns " ) ;
if ( ret - > ns = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_NSNAME_NO_NS ,
" nsName has no ns attribute \n " , NULL , NULL ) ;
}
if ( ( ctxt - > flags & XML_RELAXNG_IN_ATTRIBUTE ) & &
( ret - > ns ! = NULL ) & &
( xmlStrEqual
( ret - > ns , BAD_CAST " http://www.w3.org/2000/xmlns " ) ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_XML_NS ,
" Attribute with namespace '%s' is not allowed \n " ,
ret - > ns , NULL ) ;
}
if ( node - > children ! = NULL ) {
ret - > nameClass =
xmlRelaxNGParseExceptNameClass ( ctxt , node - > children ,
( def - > type = =
XML_RELAXNG_ATTRIBUTE ) ) ;
}
2003-02-03 08:52:58 +00:00
} else if ( IS_RELAXNG ( node , " choice " ) ) {
2003-10-07 11:33:24 +00:00
xmlNodePtr child ;
xmlRelaxNGDefinePtr last = NULL ;
2018-10-12 23:46:24 +02:00
if ( def - > type = = XML_RELAXNG_CHOICE ) {
ret = def ;
} else {
ret = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( ret = = NULL )
return ( NULL ) ;
ret - > parent = def ;
ret - > type = XML_RELAXNG_CHOICE ;
}
2003-10-07 11:33:24 +00:00
if ( node - > children = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_CHOICE_EMPTY ,
" Element choice is empty \n " , NULL , NULL ) ;
} else {
child = node - > children ;
while ( child ! = NULL ) {
tmp = xmlRelaxNGParseNameClass ( ctxt , child , ret ) ;
if ( tmp ! = NULL ) {
if ( last = = NULL ) {
2018-10-12 23:46:24 +02:00
last = tmp ;
2003-10-07 11:33:24 +00:00
} else {
last - > next = tmp ;
last = tmp ;
}
}
child = child - > next ;
}
}
2003-02-03 08:52:58 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_CHOICE_CONTENT ,
" expecting name, anyName, nsName or choice : got %s \n " ,
2010-03-15 10:06:36 +01:00
( node = = NULL ? ( const xmlChar * ) " nothing " : node - > name ) ,
NULL ) ;
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-02-03 08:52:58 +00:00
}
2003-02-19 13:29:45 +00:00
if ( ret ! = def ) {
2003-10-07 11:33:24 +00:00
if ( def - > nameClass = = NULL ) {
def - > nameClass = ret ;
} else {
tmp = def - > nameClass ;
while ( tmp - > next ! = NULL ) {
tmp = tmp - > next ;
}
tmp - > next = ret ;
}
2003-02-19 13:29:45 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-02-03 08:52:58 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGParseElement :
* @ ctxt : a Relax - NG parser context
* @ node : the element node
*
* parse the content of a RelaxNG element node .
*
* Returns the definition pointer or NULL in case of error .
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseElement ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGDefinePtr ret , cur , last ;
xmlNodePtr child ;
2003-01-24 01:03:34 +00:00
const xmlChar * olddefine ;
2003-01-23 18:29:16 +00:00
2003-03-16 17:52:32 +00:00
ret = xmlRelaxNGNewDefine ( ctxt , node ) ;
2003-01-23 18:29:16 +00:00
if ( ret = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-03-16 17:52:32 +00:00
ret - > type = XML_RELAXNG_ELEMENT ;
2003-01-28 20:58:15 +00:00
ret - > parent = ctxt - > def ;
2003-01-23 18:29:16 +00:00
child = node - > children ;
if ( child = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_EMPTY ,
" xmlRelaxNGParseElement: element has no children \n " ,
NULL , NULL ) ;
return ( ret ) ;
}
2003-02-03 08:52:58 +00:00
cur = xmlRelaxNGParseNameClass ( ctxt , child , ret ) ;
if ( cur ! = NULL )
2003-10-07 11:33:24 +00:00
child = child - > next ;
2003-02-03 08:52:58 +00:00
2003-01-23 18:29:16 +00:00
if ( child = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_NO_CONTENT ,
" xmlRelaxNGParseElement: element has no content \n " ,
NULL , NULL ) ;
return ( ret ) ;
}
2003-01-24 01:03:34 +00:00
olddefine = ctxt - > define ;
ctxt - > define = NULL ;
2003-01-23 18:29:16 +00:00
last = NULL ;
while ( child ! = NULL ) {
2003-10-07 11:33:24 +00:00
cur = xmlRelaxNGParsePattern ( ctxt , child ) ;
if ( cur ! = NULL ) {
cur - > parent = ret ;
switch ( cur - > type ) {
case XML_RELAXNG_EMPTY :
case XML_RELAXNG_NOT_ALLOWED :
case XML_RELAXNG_TEXT :
case XML_RELAXNG_ELEMENT :
case XML_RELAXNG_DATATYPE :
case XML_RELAXNG_VALUE :
case XML_RELAXNG_LIST :
case XML_RELAXNG_REF :
case XML_RELAXNG_PARENTREF :
case XML_RELAXNG_EXTERNALREF :
case XML_RELAXNG_DEF :
case XML_RELAXNG_ZEROORMORE :
case XML_RELAXNG_ONEORMORE :
case XML_RELAXNG_OPTIONAL :
case XML_RELAXNG_CHOICE :
case XML_RELAXNG_GROUP :
case XML_RELAXNG_INTERLEAVE :
if ( last = = NULL ) {
ret - > content = last = cur ;
} else {
if ( ( last - > type = = XML_RELAXNG_ELEMENT ) & &
( ret - > content = = last ) ) {
ret - > content = xmlRelaxNGNewDefine ( ctxt , node ) ;
if ( ret - > content ! = NULL ) {
ret - > content - > type = XML_RELAXNG_GROUP ;
ret - > content - > content = last ;
} else {
ret - > content = last ;
}
}
last - > next = cur ;
last = cur ;
}
break ;
case XML_RELAXNG_ATTRIBUTE :
cur - > next = ret - > attrs ;
ret - > attrs = cur ;
break ;
case XML_RELAXNG_START :
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_CONTENT ,
" RNG Internal error, start found in element \n " ,
NULL , NULL ) ;
break ;
case XML_RELAXNG_PARAM :
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_CONTENT ,
" RNG Internal error, param found in element \n " ,
NULL , NULL ) ;
break ;
case XML_RELAXNG_EXCEPT :
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_CONTENT ,
" RNG Internal error, except found in element \n " ,
NULL , NULL ) ;
break ;
case XML_RELAXNG_NOOP :
xmlRngPErr ( ctxt , node , XML_RNGP_ELEMENT_CONTENT ,
" RNG Internal error, noop found in element \n " ,
NULL , NULL ) ;
break ;
}
}
child = child - > next ;
2003-01-23 18:29:16 +00:00
}
2003-01-24 01:03:34 +00:00
ctxt - > define = olddefine ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGParsePatterns :
* @ ctxt : a Relax - NG parser context
* @ nodes : list of nodes
2003-01-30 12:17:05 +00:00
* @ group : use an implicit < group > for elements
2003-01-23 18:29:16 +00:00
*
* parse the content of a RelaxNG start node .
*
* Returns the definition pointer or NULL in case of error .
*/
static xmlRelaxNGDefinePtr
2003-01-30 12:17:05 +00:00
xmlRelaxNGParsePatterns ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr nodes ,
2003-10-07 11:33:24 +00:00
int group )
{
2003-01-28 20:58:15 +00:00
xmlRelaxNGDefinePtr def = NULL , last = NULL , cur , parent ;
2003-01-23 18:29:16 +00:00
2003-01-28 20:58:15 +00:00
parent = ctxt - > def ;
2003-01-23 18:29:16 +00:00
while ( nodes ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( IS_RELAXNG ( nodes , " element " ) ) {
cur = xmlRelaxNGParseElement ( ctxt , nodes ) ;
2019-08-25 13:58:41 +02:00
if ( cur = = NULL )
return ( NULL ) ;
2003-10-07 11:33:24 +00:00
if ( def = = NULL ) {
def = last = cur ;
} else {
if ( ( group = = 1 ) & & ( def - > type = = XML_RELAXNG_ELEMENT ) & &
( def = = last ) ) {
def = xmlRelaxNGNewDefine ( ctxt , nodes ) ;
2019-08-25 13:58:41 +02:00
if ( def = = NULL )
return ( NULL ) ;
2003-10-07 11:33:24 +00:00
def - > type = XML_RELAXNG_GROUP ;
def - > content = last ;
}
last - > next = cur ;
last = cur ;
}
cur - > parent = parent ;
} else {
cur = xmlRelaxNGParsePattern ( ctxt , nodes ) ;
if ( cur ! = NULL ) {
if ( def = = NULL ) {
def = last = cur ;
} else {
last - > next = cur ;
last = cur ;
}
}
}
nodes = nodes - > next ;
}
return ( def ) ;
}
/**
* xmlRelaxNGParseStart :
* @ ctxt : a Relax - NG parser context
* @ nodes : start children nodes
*
* parse the content of a RelaxNG start node .
*
2003-01-23 18:29:16 +00:00
* Returns 0 in case of success , - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseStart ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr nodes )
{
2003-01-23 18:29:16 +00:00
int ret = 0 ;
2003-02-17 23:34:33 +00:00
xmlRelaxNGDefinePtr def = NULL , last ;
2003-01-23 18:29:16 +00:00
2003-02-14 16:54:11 +00:00
if ( nodes = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , nodes , XML_RNGP_START_EMPTY , " start has no children \n " ,
NULL , NULL ) ;
return ( - 1 ) ;
2003-02-14 16:54:11 +00:00
}
if ( IS_RELAXNG ( nodes , " empty " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , nodes ) ;
if ( def = = NULL )
return ( - 1 ) ;
def - > type = XML_RELAXNG_EMPTY ;
if ( nodes - > children ! = NULL ) {
xmlRngPErr ( ctxt , nodes , XML_RNGP_EMPTY_CONTENT ,
" element empty is not empty \n " , NULL , NULL ) ;
}
2003-02-14 16:54:11 +00:00
} else if ( IS_RELAXNG ( nodes , " notAllowed " ) ) {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , nodes ) ;
if ( def = = NULL )
return ( - 1 ) ;
def - > type = XML_RELAXNG_NOT_ALLOWED ;
if ( nodes - > children ! = NULL ) {
xmlRngPErr ( ctxt , nodes , XML_RNGP_NOTALLOWED_NOT_EMPTY ,
" element notAllowed is not empty \n " , NULL , NULL ) ;
}
2003-02-14 16:54:11 +00:00
} else {
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGParsePatterns ( ctxt , nodes , 1 ) ;
2003-02-17 23:34:33 +00:00
}
if ( ctxt - > grammar - > start ! = NULL ) {
2003-10-07 11:33:24 +00:00
last = ctxt - > grammar - > start ;
while ( last - > next ! = NULL )
last = last - > next ;
last - > next = def ;
2003-02-17 23:34:33 +00:00
} else {
2003-10-07 11:33:24 +00:00
ctxt - > grammar - > start = def ;
2003-02-14 16:54:11 +00:00
}
nodes = nodes - > next ;
if ( nodes ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , nodes , XML_RNGP_START_CONTENT ,
" start more than one children \n " , NULL , NULL ) ;
return ( - 1 ) ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGParseGrammarContent :
* @ ctxt : a Relax - NG parser context
* @ nodes : grammar children nodes
*
* parse the content of a RelaxNG grammar node .
*
* Returns 0 in case of success , - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseGrammarContent ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlNodePtr nodes )
2003-01-23 18:29:16 +00:00
{
2003-02-02 14:35:17 +00:00
int ret = 0 , tmp ;
2003-01-23 18:29:16 +00:00
if ( nodes = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , nodes , XML_RNGP_GRAMMAR_EMPTY ,
" grammar has no children \n " , NULL , NULL ) ;
return ( - 1 ) ;
2003-01-23 18:29:16 +00:00
}
while ( nodes ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( IS_RELAXNG ( nodes , " start " ) ) {
if ( nodes - > children = = NULL ) {
xmlRngPErr ( ctxt , nodes , XML_RNGP_START_EMPTY ,
" start has no children \n " , NULL , NULL ) ;
} else {
tmp = xmlRelaxNGParseStart ( ctxt , nodes - > children ) ;
if ( tmp ! = 0 )
ret = - 1 ;
}
} else if ( IS_RELAXNG ( nodes , " define " ) ) {
tmp = xmlRelaxNGParseDefine ( ctxt , nodes ) ;
if ( tmp ! = 0 )
ret = - 1 ;
} else if ( IS_RELAXNG ( nodes , " include " ) ) {
tmp = xmlRelaxNGParseInclude ( ctxt , nodes ) ;
if ( tmp ! = 0 )
ret = - 1 ;
2003-01-23 18:29:16 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , nodes , XML_RNGP_GRAMMAR_CONTENT ,
" grammar has unexpected child %s \n " , nodes - > name ,
NULL ) ;
ret = - 1 ;
}
2003-01-23 18:29:16 +00:00
nodes = nodes - > next ;
}
return ( ret ) ;
}
/**
* xmlRelaxNGCheckReference :
* @ ref : the ref
* @ ctxt : a Relax - NG parser context
* @ name : the name associated to the defines
*
* Applies the 4.17 . combine attribute rule for all the define
* element of a given grammar using the same name .
*/
static void
2017-11-09 16:42:47 +01:00
xmlRelaxNGCheckReference ( void * payload , void * data , const xmlChar * name )
2003-10-07 11:33:24 +00:00
{
2017-11-09 16:42:47 +01:00
xmlRelaxNGDefinePtr ref = ( xmlRelaxNGDefinePtr ) payload ;
xmlRelaxNGParserCtxtPtr ctxt = ( xmlRelaxNGParserCtxtPtr ) data ;
2003-01-23 18:29:16 +00:00
xmlRelaxNGGrammarPtr grammar ;
2003-01-24 01:03:34 +00:00
xmlRelaxNGDefinePtr def , cur ;
2003-01-23 18:29:16 +00:00
2009-09-24 11:31:48 +02:00
/*
* Those rules don ' t apply to imported ref from xmlRelaxNGParseImportRef
*/
if ( ref - > dflags & IS_EXTERNAL_REF )
return ;
2003-01-23 18:29:16 +00:00
grammar = ctxt - > grammar ;
if ( grammar = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , ref - > node , XML_ERR_INTERNAL_ERROR ,
" Internal error: no grammar in CheckReference %s \n " ,
name , NULL ) ;
return ;
2003-01-23 18:29:16 +00:00
}
if ( ref - > content ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , ref - > node , XML_ERR_INTERNAL_ERROR ,
" Internal error: reference has content in CheckReference %s \n " ,
name , NULL ) ;
return ;
2003-01-23 18:29:16 +00:00
}
if ( grammar - > defs ! = NULL ) {
2003-10-07 11:33:24 +00:00
def = xmlHashLookup ( grammar - > defs , name ) ;
if ( def ! = NULL ) {
cur = ref ;
while ( cur ! = NULL ) {
cur - > content = def ;
cur = cur - > nextHash ;
}
} else {
xmlRngPErr ( ctxt , ref - > node , XML_RNGP_REF_NO_DEF ,
" Reference %s has no matching definition \n " , name ,
NULL ) ;
}
2003-02-18 21:12:46 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , ref - > node , XML_RNGP_REF_NO_DEF ,
" Reference %s has no matching definition \n " , name ,
NULL ) ;
2003-01-23 18:29:16 +00:00
}
}
/**
* xmlRelaxNGCheckCombine :
* @ define : the define ( s ) list
* @ ctxt : a Relax - NG parser context
* @ name : the name associated to the defines
*
* Applies the 4.17 . combine attribute rule for all the define
* element of a given grammar using the same name .
*/
static void
2017-11-09 16:42:47 +01:00
xmlRelaxNGCheckCombine ( void * payload , void * data , const xmlChar * name )
2003-10-07 11:33:24 +00:00
{
2017-11-09 16:42:47 +01:00
xmlRelaxNGDefinePtr define = ( xmlRelaxNGDefinePtr ) payload ;
xmlRelaxNGParserCtxtPtr ctxt = ( xmlRelaxNGParserCtxtPtr ) data ;
2003-01-23 18:29:16 +00:00
xmlChar * combine ;
int choiceOrInterleave = - 1 ;
int missing = 0 ;
xmlRelaxNGDefinePtr cur , last , tmp , tmp2 ;
if ( define - > nextHash = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
cur = define ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
combine = xmlGetProp ( cur - > node , BAD_CAST " combine " ) ;
if ( combine ! = NULL ) {
if ( xmlStrEqual ( combine , BAD_CAST " choice " ) ) {
if ( choiceOrInterleave = = - 1 )
choiceOrInterleave = 1 ;
else if ( choiceOrInterleave = = 0 ) {
xmlRngPErr ( ctxt , define - > node , XML_RNGP_DEF_CHOICE_AND_INTERLEAVE ,
" Defines for %s use both 'choice' and 'interleave' \n " ,
name , NULL ) ;
}
} else if ( xmlStrEqual ( combine , BAD_CAST " interleave " ) ) {
if ( choiceOrInterleave = = - 1 )
choiceOrInterleave = 0 ;
else if ( choiceOrInterleave = = 1 ) {
xmlRngPErr ( ctxt , define - > node , XML_RNGP_DEF_CHOICE_AND_INTERLEAVE ,
" Defines for %s use both 'choice' and 'interleave' \n " ,
name , NULL ) ;
}
} else {
xmlRngPErr ( ctxt , define - > node , XML_RNGP_UNKNOWN_COMBINE ,
" Defines for %s use unknown combine value '%s'' \n " ,
name , combine ) ;
}
xmlFree ( combine ) ;
} else {
if ( missing = = 0 )
missing = 1 ;
else {
xmlRngPErr ( ctxt , define - > node , XML_RNGP_NEED_COMBINE ,
" Some defines for %s needs the combine attribute \n " ,
name , NULL ) ;
}
}
cur = cur - > nextHash ;
2003-01-23 18:29:16 +00:00
}
# ifdef DEBUG
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" xmlRelaxNGCheckCombine(): merging %s defines: %d \n " ,
name , choiceOrInterleave ) ;
2003-01-23 18:29:16 +00:00
# endif
if ( choiceOrInterleave = = - 1 )
2003-10-07 11:33:24 +00:00
choiceOrInterleave = 0 ;
2003-03-16 17:52:32 +00:00
cur = xmlRelaxNGNewDefine ( ctxt , define - > node ) ;
2003-01-23 18:29:16 +00:00
if ( cur = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
if ( choiceOrInterleave = = 0 )
2003-10-07 11:33:24 +00:00
cur - > type = XML_RELAXNG_INTERLEAVE ;
2003-03-16 17:52:32 +00:00
else
2003-10-07 11:33:24 +00:00
cur - > type = XML_RELAXNG_CHOICE ;
2003-01-23 18:29:16 +00:00
tmp = define ;
last = NULL ;
while ( tmp ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( tmp - > content ! = NULL ) {
if ( tmp - > content - > next ! = NULL ) {
/*
* we need first to create a wrapper .
*/
tmp2 = xmlRelaxNGNewDefine ( ctxt , tmp - > content - > node ) ;
if ( tmp2 = = NULL )
break ;
tmp2 - > type = XML_RELAXNG_GROUP ;
tmp2 - > content = tmp - > content ;
} else {
tmp2 = tmp - > content ;
}
if ( last = = NULL ) {
cur - > content = tmp2 ;
} else {
last - > next = tmp2 ;
}
last = tmp2 ;
}
tmp - > content = cur ;
tmp = tmp - > nextHash ;
2003-01-23 18:29:16 +00:00
}
define - > content = cur ;
2003-03-16 17:52:32 +00:00
if ( choiceOrInterleave = = 0 ) {
2003-10-07 11:33:24 +00:00
if ( ctxt - > interleaves = = NULL )
ctxt - > interleaves = xmlHashCreate ( 10 ) ;
if ( ctxt - > interleaves = = NULL ) {
xmlRngPErr ( ctxt , define - > node , XML_RNGP_INTERLEAVE_CREATE_FAILED ,
" Failed to create interleaves hash table \n " , NULL ,
NULL ) ;
} else {
char tmpname [ 32 ] ;
snprintf ( tmpname , 32 , " interleave%d " , ctxt - > nbInterleaves + + ) ;
if ( xmlHashAddEntry ( ctxt - > interleaves , BAD_CAST tmpname , cur ) <
0 ) {
xmlRngPErr ( ctxt , define - > node , XML_RNGP_INTERLEAVE_CREATE_FAILED ,
" Failed to add %s to hash table \n " ,
( const xmlChar * ) tmpname , NULL ) ;
}
}
2003-03-16 17:52:32 +00:00
}
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGCombineStart :
* @ ctxt : a Relax - NG parser context
* @ grammar : the grammar
*
* Applies the 4.17 . combine rule for all the start
* element of a given grammar .
*/
static void
xmlRelaxNGCombineStart ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGGrammarPtr grammar )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGDefinePtr starts ;
xmlChar * combine ;
int choiceOrInterleave = - 1 ;
int missing = 0 ;
2003-02-17 23:34:33 +00:00
xmlRelaxNGDefinePtr cur ;
2003-01-23 18:29:16 +00:00
2003-02-17 23:34:33 +00:00
starts = grammar - > start ;
if ( ( starts = = NULL ) | | ( starts - > next = = NULL ) )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
cur = starts ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( cur - > node = = NULL ) | | ( cur - > node - > parent = = NULL ) | |
( ! xmlStrEqual ( cur - > node - > parent - > name , BAD_CAST " start " ) ) ) {
combine = NULL ;
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_START_MISSING ,
" Internal error: start element not found \n " , NULL ,
NULL ) ;
} else {
combine = xmlGetProp ( cur - > node - > parent , BAD_CAST " combine " ) ;
}
if ( combine ! = NULL ) {
if ( xmlStrEqual ( combine , BAD_CAST " choice " ) ) {
if ( choiceOrInterleave = = - 1 )
choiceOrInterleave = 1 ;
else if ( choiceOrInterleave = = 0 ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_START_CHOICE_AND_INTERLEAVE ,
" <start> use both 'choice' and 'interleave' \n " ,
NULL , NULL ) ;
}
} else if ( xmlStrEqual ( combine , BAD_CAST " interleave " ) ) {
if ( choiceOrInterleave = = - 1 )
choiceOrInterleave = 0 ;
else if ( choiceOrInterleave = = 1 ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_START_CHOICE_AND_INTERLEAVE ,
" <start> use both 'choice' and 'interleave' \n " ,
NULL , NULL ) ;
}
} else {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_UNKNOWN_COMBINE ,
" <start> uses unknown combine value '%s'' \n " ,
combine , NULL ) ;
}
xmlFree ( combine ) ;
} else {
if ( missing = = 0 )
missing = 1 ;
else {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_NEED_COMBINE ,
" Some <start> element miss the combine attribute \n " ,
NULL , NULL ) ;
}
}
cur = cur - > next ;
2003-01-23 18:29:16 +00:00
}
# ifdef DEBUG
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" xmlRelaxNGCombineStart(): merging <start>: %d \n " ,
choiceOrInterleave ) ;
2003-01-23 18:29:16 +00:00
# endif
if ( choiceOrInterleave = = - 1 )
2003-10-07 11:33:24 +00:00
choiceOrInterleave = 0 ;
2003-03-16 17:52:32 +00:00
cur = xmlRelaxNGNewDefine ( ctxt , starts - > node ) ;
2003-01-23 18:29:16 +00:00
if ( cur = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
if ( choiceOrInterleave = = 0 )
2003-10-07 11:33:24 +00:00
cur - > type = XML_RELAXNG_INTERLEAVE ;
2003-03-16 17:52:32 +00:00
else
2003-10-07 11:33:24 +00:00
cur - > type = XML_RELAXNG_CHOICE ;
2003-02-17 23:34:33 +00:00
cur - > content = grammar - > start ;
grammar - > start = cur ;
2003-03-16 17:52:32 +00:00
if ( choiceOrInterleave = = 0 ) {
2003-10-07 11:33:24 +00:00
if ( ctxt - > interleaves = = NULL )
ctxt - > interleaves = xmlHashCreate ( 10 ) ;
if ( ctxt - > interleaves = = NULL ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_INTERLEAVE_CREATE_FAILED ,
" Failed to create interleaves hash table \n " , NULL ,
NULL ) ;
} else {
char tmpname [ 32 ] ;
snprintf ( tmpname , 32 , " interleave%d " , ctxt - > nbInterleaves + + ) ;
if ( xmlHashAddEntry ( ctxt - > interleaves , BAD_CAST tmpname , cur ) <
0 ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_INTERLEAVE_CREATE_FAILED ,
" Failed to add %s to hash table \n " ,
( const xmlChar * ) tmpname , NULL ) ;
}
}
2003-03-16 17:52:32 +00:00
}
2003-01-23 18:29:16 +00:00
}
2003-02-18 21:12:46 +00:00
/**
* xmlRelaxNGCheckCycles :
* @ ctxt : a Relax - NG parser context
* @ nodes : grammar children nodes
* @ depth : the counter
*
* Check for cycles .
*
* Returns 0 if check passed , and - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGCheckCycles ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlRelaxNGDefinePtr cur , int depth )
{
2003-02-18 21:12:46 +00:00
int ret = 0 ;
while ( ( ret = = 0 ) & & ( cur ! = NULL ) ) {
2003-10-07 11:33:24 +00:00
if ( ( cur - > type = = XML_RELAXNG_REF ) | |
( cur - > type = = XML_RELAXNG_PARENTREF ) ) {
if ( cur - > depth = = - 1 ) {
cur - > depth = depth ;
ret = xmlRelaxNGCheckCycles ( ctxt , cur - > content , depth ) ;
cur - > depth = - 2 ;
} else if ( depth = = cur - > depth ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_REF_CYCLE ,
" Detected a cycle in %s references \n " ,
cur - > name , NULL ) ;
return ( - 1 ) ;
}
} else if ( cur - > type = = XML_RELAXNG_ELEMENT ) {
ret = xmlRelaxNGCheckCycles ( ctxt , cur - > content , depth + 1 ) ;
} else {
ret = xmlRelaxNGCheckCycles ( ctxt , cur - > content , depth ) ;
}
cur = cur - > next ;
}
return ( ret ) ;
2003-02-18 21:12:46 +00:00
}
2003-02-20 15:03:22 +00:00
/**
* xmlRelaxNGTryUnlink :
* @ ctxt : a Relax - NG parser context
* @ cur : the definition to unlink
* @ parent : the parent definition
* @ prev : the previous sibling definition
*
2019-09-30 17:04:54 +02:00
* Try to unlink a definition . If not possible make it a NOOP
2003-02-20 15:03:22 +00:00
*
* Returns the new prev definition
*/
static xmlRelaxNGDefinePtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGTryUnlink ( xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED ,
xmlRelaxNGDefinePtr cur ,
xmlRelaxNGDefinePtr parent , xmlRelaxNGDefinePtr prev )
{
2003-03-16 17:52:32 +00:00
if ( prev ! = NULL ) {
2003-10-07 11:33:24 +00:00
prev - > next = cur - > next ;
2003-03-16 17:52:32 +00:00
} else {
2003-10-07 11:33:24 +00:00
if ( parent ! = NULL ) {
if ( parent - > content = = cur )
parent - > content = cur - > next ;
else if ( parent - > attrs = = cur )
parent - > attrs = cur - > next ;
else if ( parent - > nameClass = = cur )
parent - > nameClass = cur - > next ;
} else {
cur - > type = XML_RELAXNG_NOOP ;
prev = cur ;
}
2003-03-16 17:52:32 +00:00
}
2003-10-07 11:33:24 +00:00
return ( prev ) ;
2003-02-20 15:03:22 +00:00
}
2003-02-20 00:11:02 +00:00
/**
2003-02-21 15:40:34 +00:00
* xmlRelaxNGSimplify :
2003-02-20 00:11:02 +00:00
* @ ctxt : a Relax - NG parser context
* @ nodes : grammar children nodes
*
* Check for simplification of empty and notAllowed
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGSimplify ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlRelaxNGDefinePtr cur , xmlRelaxNGDefinePtr parent )
{
2003-03-16 17:52:32 +00:00
xmlRelaxNGDefinePtr prev = NULL ;
2003-03-15 21:30:25 +00:00
2003-03-16 17:52:32 +00:00
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( cur - > type = = XML_RELAXNG_REF ) | |
( cur - > type = = XML_RELAXNG_PARENTREF ) ) {
if ( cur - > depth ! = - 3 ) {
cur - > depth = - 3 ;
xmlRelaxNGSimplify ( ctxt , cur - > content , cur ) ;
}
} else if ( cur - > type = = XML_RELAXNG_NOT_ALLOWED ) {
cur - > parent = parent ;
if ( ( parent ! = NULL ) & &
( ( parent - > type = = XML_RELAXNG_ATTRIBUTE ) | |
( parent - > type = = XML_RELAXNG_LIST ) | |
( parent - > type = = XML_RELAXNG_GROUP ) | |
( parent - > type = = XML_RELAXNG_INTERLEAVE ) | |
( parent - > type = = XML_RELAXNG_ONEORMORE ) | |
( parent - > type = = XML_RELAXNG_ZEROORMORE ) ) ) {
parent - > type = XML_RELAXNG_NOT_ALLOWED ;
break ;
}
if ( ( parent ! = NULL ) & & ( parent - > type = = XML_RELAXNG_CHOICE ) ) {
prev = xmlRelaxNGTryUnlink ( ctxt , cur , parent , prev ) ;
} else
prev = cur ;
} else if ( cur - > type = = XML_RELAXNG_EMPTY ) {
cur - > parent = parent ;
if ( ( parent ! = NULL ) & &
( ( parent - > type = = XML_RELAXNG_ONEORMORE ) | |
( parent - > type = = XML_RELAXNG_ZEROORMORE ) ) ) {
parent - > type = XML_RELAXNG_EMPTY ;
break ;
}
if ( ( parent ! = NULL ) & &
( ( parent - > type = = XML_RELAXNG_GROUP ) | |
( parent - > type = = XML_RELAXNG_INTERLEAVE ) ) ) {
prev = xmlRelaxNGTryUnlink ( ctxt , cur , parent , prev ) ;
} else
prev = cur ;
} else {
cur - > parent = parent ;
if ( cur - > content ! = NULL )
xmlRelaxNGSimplify ( ctxt , cur - > content , cur ) ;
if ( ( cur - > type ! = XML_RELAXNG_VALUE ) & & ( cur - > attrs ! = NULL ) )
xmlRelaxNGSimplify ( ctxt , cur - > attrs , cur ) ;
if ( cur - > nameClass ! = NULL )
xmlRelaxNGSimplify ( ctxt , cur - > nameClass , cur ) ;
/*
* On Elements , try to move attribute only generating rules on
* the attrs rules .
*/
if ( cur - > type = = XML_RELAXNG_ELEMENT ) {
int attronly ;
xmlRelaxNGDefinePtr tmp , pre ;
while ( cur - > content ! = NULL ) {
attronly =
xmlRelaxNGGenerateAttributes ( ctxt , cur - > content ) ;
if ( attronly = = 1 ) {
/*
* migrate cur - > content to attrs
*/
tmp = cur - > content ;
cur - > content = tmp - > next ;
tmp - > next = cur - > attrs ;
cur - > attrs = tmp ;
} else {
/*
* cur - > content can generate elements or text
*/
break ;
}
}
pre = cur - > content ;
while ( ( pre ! = NULL ) & & ( pre - > next ! = NULL ) ) {
tmp = pre - > next ;
attronly = xmlRelaxNGGenerateAttributes ( ctxt , tmp ) ;
if ( attronly = = 1 ) {
/*
* migrate tmp to attrs
*/
pre - > next = tmp - > next ;
tmp - > next = cur - > attrs ;
cur - > attrs = tmp ;
} else {
pre = tmp ;
}
}
}
/*
* This may result in a simplification
*/
if ( ( cur - > type = = XML_RELAXNG_GROUP ) | |
( cur - > type = = XML_RELAXNG_INTERLEAVE ) ) {
if ( cur - > content = = NULL )
cur - > type = XML_RELAXNG_EMPTY ;
else if ( cur - > content - > next = = NULL ) {
if ( ( parent = = NULL ) & & ( prev = = NULL ) ) {
cur - > type = XML_RELAXNG_NOOP ;
} else if ( prev = = NULL ) {
parent - > content = cur - > content ;
cur - > content - > next = cur - > next ;
cur = cur - > content ;
} else {
cur - > content - > next = cur - > next ;
prev - > next = cur - > content ;
cur = cur - > content ;
}
}
}
/*
* the current node may have been transformed back
*/
if ( ( cur - > type = = XML_RELAXNG_EXCEPT ) & &
( cur - > content ! = NULL ) & &
( cur - > content - > type = = XML_RELAXNG_NOT_ALLOWED ) ) {
prev = xmlRelaxNGTryUnlink ( ctxt , cur , parent , prev ) ;
} else if ( cur - > type = = XML_RELAXNG_NOT_ALLOWED ) {
if ( ( parent ! = NULL ) & &
( ( parent - > type = = XML_RELAXNG_ATTRIBUTE ) | |
( parent - > type = = XML_RELAXNG_LIST ) | |
( parent - > type = = XML_RELAXNG_GROUP ) | |
( parent - > type = = XML_RELAXNG_INTERLEAVE ) | |
( parent - > type = = XML_RELAXNG_ONEORMORE ) | |
( parent - > type = = XML_RELAXNG_ZEROORMORE ) ) ) {
parent - > type = XML_RELAXNG_NOT_ALLOWED ;
break ;
}
if ( ( parent ! = NULL ) & &
( parent - > type = = XML_RELAXNG_CHOICE ) ) {
prev = xmlRelaxNGTryUnlink ( ctxt , cur , parent , prev ) ;
} else
prev = cur ;
} else if ( cur - > type = = XML_RELAXNG_EMPTY ) {
if ( ( parent ! = NULL ) & &
( ( parent - > type = = XML_RELAXNG_ONEORMORE ) | |
( parent - > type = = XML_RELAXNG_ZEROORMORE ) ) ) {
parent - > type = XML_RELAXNG_EMPTY ;
break ;
}
if ( ( parent ! = NULL ) & &
( ( parent - > type = = XML_RELAXNG_GROUP ) | |
( parent - > type = = XML_RELAXNG_INTERLEAVE ) | |
( parent - > type = = XML_RELAXNG_CHOICE ) ) ) {
prev = xmlRelaxNGTryUnlink ( ctxt , cur , parent , prev ) ;
} else
prev = cur ;
} else {
prev = cur ;
}
}
cur = cur - > next ;
2003-02-20 00:11:02 +00:00
}
}
2003-02-21 15:40:34 +00:00
/**
* xmlRelaxNGGroupContentType :
* @ ct1 : the first content type
* @ ct2 : the second content type
*
* Try to group 2 content types
*
* Returns the content type
*/
static xmlRelaxNGContentType
xmlRelaxNGGroupContentType ( xmlRelaxNGContentType ct1 ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGContentType ct2 )
{
2003-02-21 15:40:34 +00:00
if ( ( ct1 = = XML_RELAXNG_CONTENT_ERROR ) | |
2003-10-07 11:33:24 +00:00
( ct2 = = XML_RELAXNG_CONTENT_ERROR ) )
return ( XML_RELAXNG_CONTENT_ERROR ) ;
2003-02-21 15:40:34 +00:00
if ( ct1 = = XML_RELAXNG_CONTENT_EMPTY )
2003-10-07 11:33:24 +00:00
return ( ct2 ) ;
2003-02-21 15:40:34 +00:00
if ( ct2 = = XML_RELAXNG_CONTENT_EMPTY )
2003-10-07 11:33:24 +00:00
return ( ct1 ) ;
2003-02-21 15:40:34 +00:00
if ( ( ct1 = = XML_RELAXNG_CONTENT_COMPLEX ) & &
2003-10-07 11:33:24 +00:00
( ct2 = = XML_RELAXNG_CONTENT_COMPLEX ) )
return ( XML_RELAXNG_CONTENT_COMPLEX ) ;
return ( XML_RELAXNG_CONTENT_ERROR ) ;
2003-02-21 15:40:34 +00:00
}
/**
* xmlRelaxNGMaxContentType :
* @ ct1 : the first content type
* @ ct2 : the second content type
*
* Compute the max content - type
*
* Returns the content type
*/
static xmlRelaxNGContentType
xmlRelaxNGMaxContentType ( xmlRelaxNGContentType ct1 ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGContentType ct2 )
{
2003-02-21 15:40:34 +00:00
if ( ( ct1 = = XML_RELAXNG_CONTENT_ERROR ) | |
2003-10-07 11:33:24 +00:00
( ct2 = = XML_RELAXNG_CONTENT_ERROR ) )
return ( XML_RELAXNG_CONTENT_ERROR ) ;
2003-02-21 15:40:34 +00:00
if ( ( ct1 = = XML_RELAXNG_CONTENT_SIMPLE ) | |
2003-10-07 11:33:24 +00:00
( ct2 = = XML_RELAXNG_CONTENT_SIMPLE ) )
return ( XML_RELAXNG_CONTENT_SIMPLE ) ;
2003-02-21 15:40:34 +00:00
if ( ( ct1 = = XML_RELAXNG_CONTENT_COMPLEX ) | |
2003-10-07 11:33:24 +00:00
( ct2 = = XML_RELAXNG_CONTENT_COMPLEX ) )
return ( XML_RELAXNG_CONTENT_COMPLEX ) ;
return ( XML_RELAXNG_CONTENT_EMPTY ) ;
2003-02-21 15:40:34 +00:00
}
2003-02-20 15:03:22 +00:00
2003-02-20 00:11:02 +00:00
/**
* xmlRelaxNGCheckRules :
* @ ctxt : a Relax - NG parser context
2003-02-21 15:40:34 +00:00
* @ cur : the current definition
2003-02-20 15:03:22 +00:00
* @ flags : some accumulated flags
2003-03-16 17:52:32 +00:00
* @ ptype : the parent type
2003-02-20 00:11:02 +00:00
*
2003-02-21 15:40:34 +00:00
* Check for rules in section 7.1 and 7.2
2003-02-20 00:11:02 +00:00
*
2003-02-21 15:40:34 +00:00
* Returns the content type of @ cur
2003-02-20 00:11:02 +00:00
*/
2003-02-21 15:40:34 +00:00
static xmlRelaxNGContentType
2003-10-07 11:33:24 +00:00
xmlRelaxNGCheckRules ( xmlRelaxNGParserCtxtPtr ctxt ,
xmlRelaxNGDefinePtr cur , int flags ,
xmlRelaxNGType ptype )
{
2009-09-07 12:15:08 +02:00
int nflags ;
2003-03-16 17:52:32 +00:00
xmlRelaxNGContentType ret , tmp , val = XML_RELAXNG_CONTENT_EMPTY ;
2003-02-20 00:11:02 +00:00
2003-03-16 17:52:32 +00:00
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
ret = XML_RELAXNG_CONTENT_EMPTY ;
if ( ( cur - > type = = XML_RELAXNG_REF ) | |
( cur - > type = = XML_RELAXNG_PARENTREF ) ) {
2005-03-31 13:50:00 +00:00
/*
* This should actually be caught by list //element(ref) at the
* element boundaries , c . f . Bug # 159968 local refs are dropped
* in step 4.19 .
*/
#if 0
2003-10-07 11:33:24 +00:00
if ( flags & XML_RELAXNG_IN_LIST ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_LIST_REF ,
" Found forbidden pattern list//ref \n " , NULL ,
NULL ) ;
}
2005-03-31 13:50:00 +00:00
# endif
2003-10-07 11:33:24 +00:00
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_REF ,
" Found forbidden pattern data/except//ref \n " ,
NULL , NULL ) ;
}
2009-08-14 18:52:10 +02:00
if ( cur - > content = = NULL ) {
if ( cur - > type = = XML_RELAXNG_PARENTREF )
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_REF_NO_DEF ,
" Internal found no define for parent refs \n " ,
NULL , NULL ) ;
else
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_REF_NO_DEF ,
" Internal found no define for ref %s \n " ,
2009-08-21 17:34:17 +02:00
( cur - > name ? cur - > name : BAD_CAST " null " ) , NULL ) ;
2009-08-14 18:52:10 +02:00
}
2003-10-07 11:33:24 +00:00
if ( cur - > depth > - 4 ) {
cur - > depth = - 4 ;
ret = xmlRelaxNGCheckRules ( ctxt , cur - > content ,
flags , cur - > type ) ;
cur - > depth = ret - 15 ;
} else if ( cur - > depth = = - 4 ) {
ret = XML_RELAXNG_CONTENT_COMPLEX ;
} else {
ret = ( xmlRelaxNGContentType ) ( cur - > depth + 15 ) ;
}
} else if ( cur - > type = = XML_RELAXNG_ELEMENT ) {
/*
* The 7.3 Attribute derivation rule for groups is plugged there
*/
xmlRelaxNGCheckGroupAttrs ( ctxt , cur ) ;
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_ELEM ,
" Found forbidden pattern data/except//element(ref) \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_LIST ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_LIST_ELEM ,
" Found forbidden pattern list//element(ref) \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_ATTRIBUTE ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_ATTR_ELEM ,
" Found forbidden pattern attribute//element(ref) \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_ATTRIBUTE ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_ATTR_ELEM ,
" Found forbidden pattern attribute//element(ref) \n " ,
NULL , NULL ) ;
}
/*
* reset since in the simple form elements are only child
* of grammar / define
*/
nflags = 0 ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > attrs , nflags , cur - > type ) ;
if ( ret ! = XML_RELAXNG_CONTENT_EMPTY ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_ELEM_CONTENT_EMPTY ,
" Element %s attributes have a content type error \n " ,
cur - > name , NULL ) ;
}
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags ,
cur - > type ) ;
if ( ret = = XML_RELAXNG_CONTENT_ERROR ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_ELEM_CONTENT_ERROR ,
" Element %s has a content type error \n " ,
cur - > name , NULL ) ;
} else {
ret = XML_RELAXNG_CONTENT_COMPLEX ;
}
} else if ( cur - > type = = XML_RELAXNG_ATTRIBUTE ) {
if ( flags & XML_RELAXNG_IN_ATTRIBUTE ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_ATTR_ATTR ,
" Found forbidden pattern attribute//attribute \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_LIST ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_LIST_ATTR ,
" Found forbidden pattern list//attribute \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_OOMGROUP ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_ONEMORE_GROUP_ATTR ,
" Found forbidden pattern oneOrMore//group//attribute \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_OOMINTERLEAVE ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR ,
" Found forbidden pattern oneOrMore//interleave//attribute \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_ATTR ,
" Found forbidden pattern data/except//attribute \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_ATTR ,
" Found forbidden pattern start//attribute \n " ,
NULL , NULL ) ;
}
if ( ( ! ( flags & XML_RELAXNG_IN_ONEORMORE ) )
2019-08-09 15:09:22 +02:00
& & cur - > name = = NULL
/* following is checking alternative name class readiness
in case it went the " choice " route */
& & cur - > nameClass = = NULL ) {
2003-10-07 11:33:24 +00:00
if ( cur - > ns = = NULL ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_ANYNAME_ATTR_ANCESTOR ,
" Found anyName attribute without oneOrMore ancestor \n " ,
NULL , NULL ) ;
} else {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_NSNAME_ATTR_ANCESTOR ,
" Found nsName attribute without oneOrMore ancestor \n " ,
NULL , NULL ) ;
}
}
nflags = flags | XML_RELAXNG_IN_ATTRIBUTE ;
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags , cur - > type ) ;
ret = XML_RELAXNG_CONTENT_EMPTY ;
} else if ( ( cur - > type = = XML_RELAXNG_ONEORMORE ) | |
( cur - > type = = XML_RELAXNG_ZEROORMORE ) ) {
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_ONEMORE ,
" Found forbidden pattern data/except//oneOrMore \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_ONEMORE ,
" Found forbidden pattern start//oneOrMore \n " ,
NULL , NULL ) ;
}
nflags = flags | XML_RELAXNG_IN_ONEORMORE ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags ,
cur - > type ) ;
ret = xmlRelaxNGGroupContentType ( ret , ret ) ;
} else if ( cur - > type = = XML_RELAXNG_LIST ) {
if ( flags & XML_RELAXNG_IN_LIST ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_LIST_LIST ,
" Found forbidden pattern list//list \n " , NULL ,
NULL ) ;
}
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_LIST ,
" Found forbidden pattern data/except//list \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_LIST ,
" Found forbidden pattern start//list \n " , NULL ,
NULL ) ;
}
nflags = flags | XML_RELAXNG_IN_LIST ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags ,
cur - > type ) ;
} else if ( cur - > type = = XML_RELAXNG_GROUP ) {
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_GROUP ,
" Found forbidden pattern data/except//group \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_GROUP ,
" Found forbidden pattern start//group \n " , NULL ,
NULL ) ;
}
if ( flags & XML_RELAXNG_IN_ONEORMORE )
nflags = flags | XML_RELAXNG_IN_OOMGROUP ;
else
nflags = flags ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags ,
cur - > type ) ;
/*
* The 7.3 Attribute derivation rule for groups is plugged there
*/
xmlRelaxNGCheckGroupAttrs ( ctxt , cur ) ;
} else if ( cur - > type = = XML_RELAXNG_INTERLEAVE ) {
if ( flags & XML_RELAXNG_IN_LIST ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_LIST_INTERLEAVE ,
" Found forbidden pattern list//interleave \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE ,
" Found forbidden pattern data/except//interleave \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE ,
" Found forbidden pattern start//interleave \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_ONEORMORE )
nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE ;
else
nflags = flags ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags ,
cur - > type ) ;
} else if ( cur - > type = = XML_RELAXNG_EXCEPT ) {
if ( ( cur - > parent ! = NULL ) & &
( cur - > parent - > type = = XML_RELAXNG_DATATYPE ) )
nflags = flags | XML_RELAXNG_IN_DATAEXCEPT ;
else
nflags = flags ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , nflags ,
cur - > type ) ;
} else if ( cur - > type = = XML_RELAXNG_DATATYPE ) {
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_DATA ,
" Found forbidden pattern start//data \n " , NULL ,
NULL ) ;
}
xmlRelaxNGCheckRules ( ctxt , cur - > content , flags , cur - > type ) ;
ret = XML_RELAXNG_CONTENT_SIMPLE ;
} else if ( cur - > type = = XML_RELAXNG_VALUE ) {
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_VALUE ,
" Found forbidden pattern start//value \n " , NULL ,
NULL ) ;
}
xmlRelaxNGCheckRules ( ctxt , cur - > content , flags , cur - > type ) ;
ret = XML_RELAXNG_CONTENT_SIMPLE ;
} else if ( cur - > type = = XML_RELAXNG_TEXT ) {
if ( flags & XML_RELAXNG_IN_LIST ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_LIST_TEXT ,
" Found forbidden pattern list//text \n " , NULL ,
NULL ) ;
}
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_TEXT ,
" Found forbidden pattern data/except//text \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_TEXT ,
" Found forbidden pattern start//text \n " , NULL ,
NULL ) ;
}
ret = XML_RELAXNG_CONTENT_COMPLEX ;
} else if ( cur - > type = = XML_RELAXNG_EMPTY ) {
if ( flags & XML_RELAXNG_IN_DATAEXCEPT ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_DATA_EXCEPT_EMPTY ,
" Found forbidden pattern data/except//empty \n " ,
NULL , NULL ) ;
}
if ( flags & XML_RELAXNG_IN_START ) {
xmlRngPErr ( ctxt , cur - > node , XML_RNGP_PAT_START_EMPTY ,
" Found forbidden pattern start//empty \n " , NULL ,
NULL ) ;
}
ret = XML_RELAXNG_CONTENT_EMPTY ;
} else if ( cur - > type = = XML_RELAXNG_CHOICE ) {
xmlRelaxNGCheckChoiceDeterminism ( ctxt , cur ) ;
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , flags , cur - > type ) ;
} else {
ret =
xmlRelaxNGCheckRules ( ctxt , cur - > content , flags , cur - > type ) ;
}
cur = cur - > next ;
if ( ptype = = XML_RELAXNG_GROUP ) {
val = xmlRelaxNGGroupContentType ( val , ret ) ;
} else if ( ptype = = XML_RELAXNG_INTERLEAVE ) {
2009-09-07 14:58:47 +02:00
/*
* TODO : scan complain that tmp is never used , seems on purpose
* need double - checking
*/
2003-10-07 11:33:24 +00:00
tmp = xmlRelaxNGGroupContentType ( val , ret ) ;
if ( tmp ! = XML_RELAXNG_CONTENT_ERROR )
tmp = xmlRelaxNGMaxContentType ( val , ret ) ;
} else if ( ptype = = XML_RELAXNG_CHOICE ) {
val = xmlRelaxNGMaxContentType ( val , ret ) ;
} else if ( ptype = = XML_RELAXNG_LIST ) {
val = XML_RELAXNG_CONTENT_SIMPLE ;
} else if ( ptype = = XML_RELAXNG_EXCEPT ) {
if ( ret = = XML_RELAXNG_CONTENT_ERROR )
val = XML_RELAXNG_CONTENT_ERROR ;
else
val = XML_RELAXNG_CONTENT_SIMPLE ;
} else {
val = xmlRelaxNGGroupContentType ( val , ret ) ;
}
}
return ( val ) ;
2003-02-20 00:11:02 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGParseGrammar :
* @ ctxt : a Relax - NG parser context
* @ nodes : grammar children nodes
*
* parse a Relax - NG < grammar > node
*
* Returns the internal xmlRelaxNGGrammarPtr built or
* NULL in case of error
*/
static xmlRelaxNGGrammarPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseGrammar ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr nodes )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGGrammarPtr ret , tmp , old ;
2003-02-26 14:48:48 +00:00
# ifdef DEBUG_GRAMMAR
xmlGenericError ( xmlGenericErrorContext , " Parsing a new grammar \n " ) ;
# endif
2003-01-23 18:29:16 +00:00
ret = xmlRelaxNGNewGrammar ( ctxt ) ;
if ( ret = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
/*
* Link the new grammar in the tree
*/
ret - > parent = ctxt - > grammar ;
if ( ctxt - > grammar ! = NULL ) {
2003-10-07 11:33:24 +00:00
tmp = ctxt - > grammar - > children ;
if ( tmp = = NULL ) {
ctxt - > grammar - > children = ret ;
} else {
while ( tmp - > next ! = NULL )
tmp = tmp - > next ;
tmp - > next = ret ;
}
2003-01-23 18:29:16 +00:00
}
old = ctxt - > grammar ;
ctxt - > grammar = ret ;
xmlRelaxNGParseGrammarContent ( ctxt , nodes ) ;
ctxt - > grammar = ret ;
2003-02-17 23:34:33 +00:00
if ( ctxt - > grammar = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , nodes , XML_RNGP_GRAMMAR_CONTENT ,
" Failed to parse <grammar> content \n " , NULL , NULL ) ;
2003-02-17 23:34:33 +00:00
} else if ( ctxt - > grammar - > start = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , nodes , XML_RNGP_GRAMMAR_NO_START ,
" Element <grammar> has no <start> \n " , NULL , NULL ) ;
2003-02-17 23:34:33 +00:00
}
2003-01-23 18:29:16 +00:00
/*
2014-06-09 23:45:24 +02:00
* Apply 4.17 merging rules to defines and starts
2003-01-23 18:29:16 +00:00
*/
xmlRelaxNGCombineStart ( ctxt , ret ) ;
if ( ret - > defs ! = NULL ) {
2017-11-09 16:42:47 +01:00
xmlHashScan ( ret - > defs , xmlRelaxNGCheckCombine , ctxt ) ;
2003-01-23 18:29:16 +00:00
}
/*
* link together defines and refs in this grammar
*/
if ( ret - > refs ! = NULL ) {
2017-11-09 16:42:47 +01:00
xmlHashScan ( ret - > refs , xmlRelaxNGCheckReference , ctxt ) ;
2003-01-23 18:29:16 +00:00
}
2003-03-17 15:37:12 +00:00
2009-08-14 18:52:10 +02:00
2008-06-02 16:04:12 +00:00
/* @@@@ */
2003-01-23 18:29:16 +00:00
ctxt - > grammar = old ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGParseDocument :
* @ ctxt : a Relax - NG parser context
* @ node : the root node of the RelaxNG schema
*
* parse a Relax - NG definition resource and build an internal
2019-09-30 17:04:54 +02:00
* xmlRelaxNG structure which can be used to validate instances .
2003-01-23 18:29:16 +00:00
*
* Returns the internal XML RelaxNG structure built or
* NULL in case of error
*/
static xmlRelaxNGPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGParseDocument ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGPtr schema = NULL ;
2003-01-24 01:03:34 +00:00
const xmlChar * olddefine ;
2003-01-29 23:02:33 +00:00
xmlRelaxNGGrammarPtr old ;
2003-01-23 18:29:16 +00:00
if ( ( ctxt = = NULL ) | | ( node = = NULL ) )
return ( NULL ) ;
schema = xmlRelaxNGNewRelaxNG ( ctxt ) ;
if ( schema = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
2003-01-24 01:03:34 +00:00
olddefine = ctxt - > define ;
ctxt - > define = NULL ;
2003-01-23 18:29:16 +00:00
if ( IS_RELAXNG ( node , " grammar " ) ) {
2003-10-07 11:33:24 +00:00
schema - > topgrammar = xmlRelaxNGParseGrammar ( ctxt , node - > children ) ;
2014-07-26 21:04:54 +08:00
if ( schema - > topgrammar = = NULL ) {
xmlRelaxNGFree ( schema ) ;
return ( NULL ) ;
}
2003-01-23 18:29:16 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRelaxNGGrammarPtr tmp , ret ;
schema - > topgrammar = ret = xmlRelaxNGNewGrammar ( ctxt ) ;
if ( schema - > topgrammar = = NULL ) {
2014-07-26 21:04:54 +08:00
xmlRelaxNGFree ( schema ) ;
return ( NULL ) ;
2003-10-07 11:33:24 +00:00
}
/*
* Link the new grammar in the tree
*/
ret - > parent = ctxt - > grammar ;
if ( ctxt - > grammar ! = NULL ) {
tmp = ctxt - > grammar - > children ;
if ( tmp = = NULL ) {
ctxt - > grammar - > children = ret ;
} else {
while ( tmp - > next ! = NULL )
tmp = tmp - > next ;
tmp - > next = ret ;
}
}
old = ctxt - > grammar ;
ctxt - > grammar = ret ;
xmlRelaxNGParseStart ( ctxt , node ) ;
if ( old ! = NULL )
ctxt - > grammar = old ;
2003-01-23 18:29:16 +00:00
}
2003-01-24 01:03:34 +00:00
ctxt - > define = olddefine ;
2003-02-18 21:12:46 +00:00
if ( schema - > topgrammar - > start ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGCheckCycles ( ctxt , schema - > topgrammar - > start , 0 ) ;
if ( ( ctxt - > flags & XML_RELAXNG_IN_EXTERNALREF ) = = 0 ) {
xmlRelaxNGSimplify ( ctxt , schema - > topgrammar - > start , NULL ) ;
while ( ( schema - > topgrammar - > start ! = NULL ) & &
( schema - > topgrammar - > start - > type = = XML_RELAXNG_NOOP ) & &
( schema - > topgrammar - > start - > next ! = NULL ) )
schema - > topgrammar - > start =
schema - > topgrammar - > start - > content ;
xmlRelaxNGCheckRules ( ctxt , schema - > topgrammar - > start ,
XML_RELAXNG_IN_START , XML_RELAXNG_NOOP ) ;
}
2003-02-18 21:12:46 +00:00
}
2003-01-23 18:29:16 +00:00
# ifdef DEBUG
if ( schema = = NULL )
xmlGenericError ( xmlGenericErrorContext ,
" xmlRelaxNGParseDocument() failed \n " ) ;
# endif
return ( schema ) ;
}
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Reading RelaxNGs *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlRelaxNGNewParserCtxt :
* @ URL : the location of the schema
*
* Create an XML RelaxNGs parse context for that file / resource expected
* to contain an XML RelaxNGs file .
*
* Returns the parser context or NULL in case of error
*/
xmlRelaxNGParserCtxtPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGNewParserCtxt ( const char * URL )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGParserCtxtPtr ret ;
if ( URL = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
ret =
( xmlRelaxNGParserCtxtPtr ) xmlMalloc ( sizeof ( xmlRelaxNGParserCtxt ) ) ;
2003-01-23 18:29:16 +00:00
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( NULL , " building parser \n " ) ;
2003-01-23 18:29:16 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGParserCtxt ) ) ;
2003-10-07 11:33:24 +00:00
ret - > URL = xmlStrdup ( ( const xmlChar * ) URL ) ;
2003-02-10 14:28:44 +00:00
ret - > error = xmlGenericError ;
ret - > userData = xmlGenericErrorContext ;
2003-01-23 18:29:16 +00:00
return ( ret ) ;
}
/**
* xmlRelaxNGNewMemParserCtxt :
* @ buffer : a pointer to a char array containing the schemas
* @ size : the size of the array
*
* Create an XML RelaxNGs parse context for that memory buffer expected
* to contain an XML RelaxNGs file .
*
* Returns the parser context or NULL in case of error
*/
xmlRelaxNGParserCtxtPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGNewMemParserCtxt ( const char * buffer , int size )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGParserCtxtPtr ret ;
if ( ( buffer = = NULL ) | | ( size < = 0 ) )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
ret =
( xmlRelaxNGParserCtxtPtr ) xmlMalloc ( sizeof ( xmlRelaxNGParserCtxt ) ) ;
2003-01-23 18:29:16 +00:00
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( NULL , " building parser \n " ) ;
2003-01-23 18:29:16 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGParserCtxt ) ) ;
ret - > buffer = buffer ;
ret - > size = size ;
2003-02-10 14:28:44 +00:00
ret - > error = xmlGenericError ;
ret - > userData = xmlGenericErrorContext ;
2003-01-23 18:29:16 +00:00
return ( ret ) ;
}
2003-04-17 09:09:19 +00:00
/**
* xmlRelaxNGNewDocParserCtxt :
* @ doc : a preparsed document tree
*
* Create an XML RelaxNGs parser context for that document .
* Note : since the process of compiling a RelaxNG schemas modifies the
* document , the @ doc parameter is duplicated internally .
*
* Returns the parser context or NULL in case of error
*/
xmlRelaxNGParserCtxtPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGNewDocParserCtxt ( xmlDocPtr doc )
{
2003-04-17 09:09:19 +00:00
xmlRelaxNGParserCtxtPtr ret ;
xmlDocPtr copy ;
if ( doc = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-04-17 09:09:19 +00:00
copy = xmlCopyDoc ( doc , 1 ) ;
if ( copy = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-04-17 09:09:19 +00:00
2003-10-07 11:33:24 +00:00
ret =
( xmlRelaxNGParserCtxtPtr ) xmlMalloc ( sizeof ( xmlRelaxNGParserCtxt ) ) ;
2003-04-17 09:09:19 +00:00
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErrMemory ( NULL , " building parser \n " ) ;
2021-07-14 15:35:31 +01:00
xmlFreeDoc ( copy ) ;
2003-04-17 09:09:19 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGParserCtxt ) ) ;
ret - > document = copy ;
2004-11-08 10:52:06 +00:00
ret - > freedoc = 1 ;
2003-04-17 09:09:19 +00:00
ret - > userData = xmlGenericErrorContext ;
return ( ret ) ;
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGFreeParserCtxt :
* @ ctxt : the schema parser context
*
* Free the resources associated to the schema parser context
*/
void
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeParserCtxt ( xmlRelaxNGParserCtxtPtr ctxt )
{
2003-01-23 18:29:16 +00:00
if ( ctxt = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
if ( ctxt - > URL ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( ctxt - > URL ) ;
2003-01-23 18:29:16 +00:00
if ( ctxt - > doc ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeDocument ( ctxt - > doc ) ;
2003-01-28 20:58:15 +00:00
if ( ctxt - > interleaves ! = NULL )
xmlHashFree ( ctxt - > interleaves , NULL ) ;
2003-01-29 21:07:52 +00:00
if ( ctxt - > documents ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeDocumentList ( ctxt - > documents ) ;
2003-02-24 17:17:58 +00:00
if ( ctxt - > includes ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeIncludeList ( ctxt - > includes ) ;
2003-01-29 21:07:52 +00:00
if ( ctxt - > docTab ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( ctxt - > docTab ) ;
2003-02-01 17:43:10 +00:00
if ( ctxt - > incTab ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( ctxt - > incTab ) ;
2003-02-03 23:22:49 +00:00
if ( ctxt - > defTab ! = NULL ) {
2003-10-07 11:33:24 +00:00
int i ;
2003-02-03 23:22:49 +00:00
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < ctxt - > defNr ; i + + )
xmlRelaxNGFreeDefine ( ctxt - > defTab [ i ] ) ;
xmlFree ( ctxt - > defTab ) ;
2003-02-03 23:22:49 +00:00
}
2004-11-08 10:52:06 +00:00
if ( ( ctxt - > document ! = NULL ) & & ( ctxt - > freedoc ) )
xmlFreeDoc ( ctxt - > document ) ;
2003-01-23 18:29:16 +00:00
xmlFree ( ctxt ) ;
}
2003-02-14 16:54:11 +00:00
/**
* xmlRelaxNGNormExtSpace :
* @ value : a value
*
* Removes the leading and ending spaces of the value
* The string is modified " in situ "
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGNormExtSpace ( xmlChar * value )
{
2003-02-14 16:54:11 +00:00
xmlChar * start = value ;
xmlChar * cur = value ;
2003-10-07 11:33:24 +00:00
2003-02-14 16:54:11 +00:00
if ( value = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-02-14 16:54:11 +00:00
2003-10-18 16:20:14 +00:00
while ( IS_BLANK_CH ( * cur ) )
2003-10-07 11:33:24 +00:00
cur + + ;
2003-02-14 16:54:11 +00:00
if ( cur = = start ) {
2003-10-07 11:33:24 +00:00
do {
2003-10-18 16:20:14 +00:00
while ( ( * cur ! = 0 ) & & ( ! IS_BLANK_CH ( * cur ) ) )
2003-10-07 11:33:24 +00:00
cur + + ;
if ( * cur = = 0 )
return ;
start = cur ;
2003-10-18 16:20:14 +00:00
while ( IS_BLANK_CH ( * cur ) )
2003-10-07 11:33:24 +00:00
cur + + ;
if ( * cur = = 0 ) {
* start = 0 ;
return ;
}
} while ( 1 ) ;
2003-02-14 16:54:11 +00:00
} else {
2003-10-07 11:33:24 +00:00
do {
2003-10-18 16:20:14 +00:00
while ( ( * cur ! = 0 ) & & ( ! IS_BLANK_CH ( * cur ) ) )
2003-10-07 11:33:24 +00:00
* start + + = * cur + + ;
if ( * cur = = 0 ) {
* start = 0 ;
return ;
}
/* don't try to normalize the inner spaces */
2003-10-18 16:20:14 +00:00
while ( IS_BLANK_CH ( * cur ) )
2003-10-07 11:33:24 +00:00
cur + + ;
if ( * cur = = 0 ) {
* start = 0 ;
return ;
}
2003-10-17 12:43:59 +00:00
* start + + = * cur + + ;
2003-10-07 11:33:24 +00:00
} while ( 1 ) ;
2003-02-14 16:54:11 +00:00
}
}
/**
2004-10-07 13:14:19 +00:00
* xmlRelaxNGCleanupAttributes :
2003-02-14 16:54:11 +00:00
* @ ctxt : a Relax - NG parser context
* @ node : a Relax - NG node
*
* Check all the attributes on the given node
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGCleanupAttributes ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr node )
{
2003-02-14 16:54:11 +00:00
xmlAttrPtr cur , next ;
cur = node - > properties ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
next = cur - > next ;
if ( ( cur - > ns = = NULL ) | |
( xmlStrEqual ( cur - > ns - > href , xmlRelaxNGNs ) ) ) {
if ( xmlStrEqual ( cur - > name , BAD_CAST " name " ) ) {
if ( ( ! xmlStrEqual ( node - > name , BAD_CAST " element " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " attribute " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " ref " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " parentRef " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " param " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " define " ) ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_FORBIDDEN_ATTRIBUTE ,
" Attribute %s is not allowed on %s \n " ,
cur - > name , node - > name ) ;
}
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " type " ) ) {
if ( ( ! xmlStrEqual ( node - > name , BAD_CAST " value " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " data " ) ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_FORBIDDEN_ATTRIBUTE ,
" Attribute %s is not allowed on %s \n " ,
cur - > name , node - > name ) ;
}
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " href " ) ) {
if ( ( ! xmlStrEqual ( node - > name , BAD_CAST " externalRef " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " include " ) ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_FORBIDDEN_ATTRIBUTE ,
" Attribute %s is not allowed on %s \n " ,
cur - > name , node - > name ) ;
}
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " combine " ) ) {
if ( ( ! xmlStrEqual ( node - > name , BAD_CAST " start " ) ) & &
( ! xmlStrEqual ( node - > name , BAD_CAST " define " ) ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_FORBIDDEN_ATTRIBUTE ,
" Attribute %s is not allowed on %s \n " ,
cur - > name , node - > name ) ;
}
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " datatypeLibrary " ) ) {
xmlChar * val ;
xmlURIPtr uri ;
val = xmlNodeListGetString ( node - > doc , cur - > children , 1 ) ;
if ( val ! = NULL ) {
if ( val [ 0 ] ! = 0 ) {
uri = xmlParseURI ( ( const char * ) val ) ;
if ( uri = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_INVALID_URI ,
" Attribute %s contains invalid URI %s \n " ,
cur - > name , val ) ;
} else {
if ( uri - > scheme = = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_URI_NOT_ABSOLUTE ,
" Attribute %s URI %s is not absolute \n " ,
cur - > name , val ) ;
}
if ( uri - > fragment ! = NULL ) {
xmlRngPErr ( ctxt , node , XML_RNGP_URI_FRAGMENT ,
" Attribute %s URI %s has a fragment ID \n " ,
cur - > name , val ) ;
}
xmlFreeURI ( uri ) ;
}
}
xmlFree ( val ) ;
}
} else if ( ! xmlStrEqual ( cur - > name , BAD_CAST " ns " ) ) {
xmlRngPErr ( ctxt , node , XML_RNGP_UNKNOWN_ATTRIBUTE ,
" Unknown attribute %s on %s \n " , cur - > name ,
node - > name ) ;
}
}
cur = next ;
2003-02-14 16:54:11 +00:00
}
}
2003-10-07 11:33:24 +00:00
/**
* xmlRelaxNGCleanupTree :
* @ ctxt : a Relax - NG parser context
* @ root : an xmlNodePtr subtree
*
* Cleanup the subtree from unwanted nodes for parsing , resolve
* Include and externalRef lookups .
*/
static void
xmlRelaxNGCleanupTree ( xmlRelaxNGParserCtxtPtr ctxt , xmlNodePtr root )
{
xmlNodePtr cur , delete ;
delete = NULL ;
cur = root ;
while ( cur ! = NULL ) {
if ( delete ! = NULL ) {
xmlUnlinkNode ( delete ) ;
xmlFreeNode ( delete ) ;
delete = NULL ;
}
if ( cur - > type = = XML_ELEMENT_NODE ) {
/*
* Simplification 4.1 . Annotations
*/
if ( ( cur - > ns = = NULL ) | |
( ! xmlStrEqual ( cur - > ns - > href , xmlRelaxNGNs ) ) ) {
if ( ( cur - > parent ! = NULL ) & &
( cur - > parent - > type = = XML_ELEMENT_NODE ) & &
( ( xmlStrEqual ( cur - > parent - > name , BAD_CAST " name " ) ) | |
( xmlStrEqual ( cur - > parent - > name , BAD_CAST " value " ) ) | |
( xmlStrEqual ( cur - > parent - > name , BAD_CAST " param " ) ) ) ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_FOREIGN_ELEMENT ,
" element %s doesn't allow foreign elements \n " ,
cur - > parent - > name , NULL ) ;
}
delete = cur ;
goto skip_children ;
} else {
xmlRelaxNGCleanupAttributes ( ctxt , cur ) ;
if ( xmlStrEqual ( cur - > name , BAD_CAST " externalRef " ) ) {
xmlChar * href , * ns , * base , * URL ;
xmlRelaxNGDocumentPtr docu ;
xmlNodePtr tmp ;
2004-03-22 19:10:02 +00:00
xmlURIPtr uri ;
2003-10-07 11:33:24 +00:00
ns = xmlGetProp ( cur , BAD_CAST " ns " ) ;
if ( ns = = NULL ) {
tmp = cur - > parent ;
while ( ( tmp ! = NULL ) & &
( tmp - > type = = XML_ELEMENT_NODE ) ) {
ns = xmlGetProp ( tmp , BAD_CAST " ns " ) ;
if ( ns ! = NULL )
break ;
tmp = tmp - > parent ;
}
}
href = xmlGetProp ( cur , BAD_CAST " href " ) ;
if ( href = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_MISSING_HREF ,
" xmlRelaxNGParse: externalRef has no href attribute \n " ,
NULL , NULL ) ;
2005-06-30 13:04:44 +00:00
if ( ns ! = NULL )
xmlFree ( ns ) ;
2003-10-07 11:33:24 +00:00
delete = cur ;
goto skip_children ;
}
2004-03-22 19:10:02 +00:00
uri = xmlParseURI ( ( const char * ) href ) ;
if ( uri = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_HREF_ERROR ,
" Incorrect URI for externalRef %s \n " ,
href , NULL ) ;
2005-06-30 13:04:44 +00:00
if ( ns ! = NULL )
xmlFree ( ns ) ;
2004-03-22 19:10:02 +00:00
if ( href ! = NULL )
xmlFree ( href ) ;
delete = cur ;
goto skip_children ;
}
if ( uri - > fragment ! = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_HREF_ERROR ,
" Fragment forbidden in URI for externalRef %s \n " ,
href , NULL ) ;
2005-06-30 13:04:44 +00:00
if ( ns ! = NULL )
xmlFree ( ns ) ;
2004-03-22 19:10:02 +00:00
xmlFreeURI ( uri ) ;
if ( href ! = NULL )
xmlFree ( href ) ;
delete = cur ;
goto skip_children ;
}
xmlFreeURI ( uri ) ;
2003-10-07 11:33:24 +00:00
base = xmlNodeGetBase ( cur - > doc , cur ) ;
URL = xmlBuildURI ( href , base ) ;
if ( URL = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_HREF_ERROR ,
" Failed to compute URL for externalRef %s \n " ,
href , NULL ) ;
2005-06-30 13:04:44 +00:00
if ( ns ! = NULL )
xmlFree ( ns ) ;
2003-10-07 11:33:24 +00:00
if ( href ! = NULL )
xmlFree ( href ) ;
if ( base ! = NULL )
xmlFree ( base ) ;
delete = cur ;
goto skip_children ;
}
if ( href ! = NULL )
xmlFree ( href ) ;
if ( base ! = NULL )
xmlFree ( base ) ;
docu = xmlRelaxNGLoadExternalRef ( ctxt , URL , ns ) ;
if ( docu = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_EXTERNAL_REF_FAILURE ,
" Failed to load externalRef %s \n " , URL ,
NULL ) ;
2005-06-30 13:04:44 +00:00
if ( ns ! = NULL )
xmlFree ( ns ) ;
2003-10-07 11:33:24 +00:00
xmlFree ( URL ) ;
delete = cur ;
goto skip_children ;
}
if ( ns ! = NULL )
xmlFree ( ns ) ;
xmlFree ( URL ) ;
2004-02-22 22:13:27 +00:00
cur - > psvi = docu ;
2003-10-07 11:33:24 +00:00
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " include " ) ) {
xmlChar * href , * ns , * base , * URL ;
xmlRelaxNGIncludePtr incl ;
xmlNodePtr tmp ;
href = xmlGetProp ( cur , BAD_CAST " href " ) ;
if ( href = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_MISSING_HREF ,
" xmlRelaxNGParse: include has no href attribute \n " ,
NULL , NULL ) ;
delete = cur ;
goto skip_children ;
}
base = xmlNodeGetBase ( cur - > doc , cur ) ;
URL = xmlBuildURI ( href , base ) ;
if ( URL = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_HREF_ERROR ,
" Failed to compute URL for include %s \n " ,
href , NULL ) ;
if ( href ! = NULL )
xmlFree ( href ) ;
if ( base ! = NULL )
xmlFree ( base ) ;
delete = cur ;
goto skip_children ;
}
if ( href ! = NULL )
xmlFree ( href ) ;
if ( base ! = NULL )
xmlFree ( base ) ;
ns = xmlGetProp ( cur , BAD_CAST " ns " ) ;
if ( ns = = NULL ) {
tmp = cur - > parent ;
while ( ( tmp ! = NULL ) & &
( tmp - > type = = XML_ELEMENT_NODE ) ) {
ns = xmlGetProp ( tmp , BAD_CAST " ns " ) ;
if ( ns ! = NULL )
break ;
tmp = tmp - > parent ;
}
}
incl = xmlRelaxNGLoadInclude ( ctxt , URL , cur , ns ) ;
if ( ns ! = NULL )
xmlFree ( ns ) ;
if ( incl = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_INCLUDE_FAILURE ,
" Failed to load include %s \n " , URL ,
NULL ) ;
xmlFree ( URL ) ;
delete = cur ;
goto skip_children ;
}
xmlFree ( URL ) ;
2004-02-22 22:13:27 +00:00
cur - > psvi = incl ;
2003-10-07 11:33:24 +00:00
} else if ( ( xmlStrEqual ( cur - > name , BAD_CAST " element " ) ) | |
( xmlStrEqual ( cur - > name , BAD_CAST " attribute " ) ) )
{
xmlChar * name , * ns ;
xmlNodePtr text = NULL ;
/*
* Simplification 4.8 . name attribute of element
* and attribute elements
*/
name = xmlGetProp ( cur , BAD_CAST " name " ) ;
if ( name ! = NULL ) {
if ( cur - > children = = NULL ) {
text =
xmlNewChild ( cur , cur - > ns , BAD_CAST " name " ,
name ) ;
} else {
xmlNodePtr node ;
2004-10-26 16:06:51 +00:00
node = xmlNewDocNode ( cur - > doc , cur - > ns ,
BAD_CAST " name " , NULL ) ;
2003-10-07 11:33:24 +00:00
if ( node ! = NULL ) {
xmlAddPrevSibling ( cur - > children , node ) ;
2022-05-20 23:28:25 +02:00
text = xmlNewDocText ( node - > doc , name ) ;
2003-10-07 11:33:24 +00:00
xmlAddChild ( node , text ) ;
text = node ;
}
}
if ( text = = NULL ) {
xmlRngPErr ( ctxt , cur , XML_RNGP_CREATE_FAILURE ,
" Failed to create a name %s element \n " ,
name , NULL ) ;
}
xmlUnsetProp ( cur , BAD_CAST " name " ) ;
xmlFree ( name ) ;
ns = xmlGetProp ( cur , BAD_CAST " ns " ) ;
if ( ns ! = NULL ) {
if ( text ! = NULL ) {
xmlSetProp ( text , BAD_CAST " ns " , ns ) ;
/* xmlUnsetProp(cur, BAD_CAST "ns"); */
}
xmlFree ( ns ) ;
} else if ( xmlStrEqual ( cur - > name ,
BAD_CAST " attribute " ) ) {
xmlSetProp ( text , BAD_CAST " ns " , BAD_CAST " " ) ;
}
}
} else if ( ( xmlStrEqual ( cur - > name , BAD_CAST " name " ) ) | |
( xmlStrEqual ( cur - > name , BAD_CAST " nsName " ) ) | |
( xmlStrEqual ( cur - > name , BAD_CAST " value " ) ) ) {
/*
* Simplification 4.8 . name attribute of element
* and attribute elements
*/
if ( xmlHasProp ( cur , BAD_CAST " ns " ) = = NULL ) {
xmlNodePtr node ;
xmlChar * ns = NULL ;
node = cur - > parent ;
while ( ( node ! = NULL ) & &
( node - > type = = XML_ELEMENT_NODE ) ) {
ns = xmlGetProp ( node , BAD_CAST " ns " ) ;
if ( ns ! = NULL ) {
break ;
}
node = node - > parent ;
}
if ( ns = = NULL ) {
xmlSetProp ( cur , BAD_CAST " ns " , BAD_CAST " " ) ;
} else {
xmlSetProp ( cur , BAD_CAST " ns " , ns ) ;
xmlFree ( ns ) ;
}
}
if ( xmlStrEqual ( cur - > name , BAD_CAST " name " ) ) {
xmlChar * name , * local , * prefix ;
/*
* Simplification : 4.10 . QNames
*/
name = xmlNodeGetContent ( cur ) ;
if ( name ! = NULL ) {
local = xmlSplitQName2 ( name , & prefix ) ;
if ( local ! = NULL ) {
xmlNsPtr ns ;
ns = xmlSearchNs ( cur - > doc , cur , prefix ) ;
if ( ns = = NULL ) {
xmlRngPErr ( ctxt , cur ,
XML_RNGP_PREFIX_UNDEFINED ,
" xmlRelaxNGParse: no namespace for prefix %s \n " ,
prefix , NULL ) ;
} else {
xmlSetProp ( cur , BAD_CAST " ns " ,
ns - > href ) ;
xmlNodeSetContent ( cur , local ) ;
}
xmlFree ( local ) ;
xmlFree ( prefix ) ;
}
xmlFree ( name ) ;
}
}
/*
* 4.16
*/
if ( xmlStrEqual ( cur - > name , BAD_CAST " nsName " ) ) {
if ( ctxt - > flags & XML_RELAXNG_IN_NSEXCEPT ) {
xmlRngPErr ( ctxt , cur ,
XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME ,
" Found nsName/except//nsName forbidden construct \n " ,
NULL , NULL ) ;
}
}
} else if ( ( xmlStrEqual ( cur - > name , BAD_CAST " except " ) ) & &
( cur ! = root ) ) {
int oldflags = ctxt - > flags ;
/*
* 4.16
*/
if ( ( cur - > parent ! = NULL ) & &
( xmlStrEqual
( cur - > parent - > name , BAD_CAST " anyName " ) ) ) {
ctxt - > flags | = XML_RELAXNG_IN_ANYEXCEPT ;
xmlRelaxNGCleanupTree ( ctxt , cur ) ;
ctxt - > flags = oldflags ;
goto skip_children ;
} else if ( ( cur - > parent ! = NULL ) & &
( xmlStrEqual
( cur - > parent - > name , BAD_CAST " nsName " ) ) ) {
ctxt - > flags | = XML_RELAXNG_IN_NSEXCEPT ;
xmlRelaxNGCleanupTree ( ctxt , cur ) ;
ctxt - > flags = oldflags ;
goto skip_children ;
}
} else if ( xmlStrEqual ( cur - > name , BAD_CAST " anyName " ) ) {
/*
* 4.16
*/
if ( ctxt - > flags & XML_RELAXNG_IN_ANYEXCEPT ) {
xmlRngPErr ( ctxt , cur ,
XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME ,
" Found anyName/except//anyName forbidden construct \n " ,
NULL , NULL ) ;
} else if ( ctxt - > flags & XML_RELAXNG_IN_NSEXCEPT ) {
xmlRngPErr ( ctxt , cur ,
XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME ,
" Found nsName/except//anyName forbidden construct \n " ,
NULL , NULL ) ;
}
}
/*
2014-06-09 23:45:24 +02:00
* This is not an else since " include " is transformed
2003-10-07 11:33:24 +00:00
* into a div
*/
if ( xmlStrEqual ( cur - > name , BAD_CAST " div " ) ) {
xmlChar * ns ;
xmlNodePtr child , ins , tmp ;
/*
* implements rule 4.11
*/
ns = xmlGetProp ( cur , BAD_CAST " ns " ) ;
child = cur - > children ;
ins = cur ;
while ( child ! = NULL ) {
if ( ns ! = NULL ) {
if ( ! xmlHasProp ( child , BAD_CAST " ns " ) ) {
xmlSetProp ( child , BAD_CAST " ns " , ns ) ;
}
}
tmp = child - > next ;
xmlUnlinkNode ( child ) ;
ins = xmlAddNextSibling ( ins , child ) ;
child = tmp ;
}
if ( ns ! = NULL )
xmlFree ( ns ) ;
2004-06-07 14:15:54 +00:00
/*
2014-07-14 16:14:44 +08:00
* Since we are about to delete cur , if its nsDef is non - NULL we
2004-06-07 14:15:54 +00:00
* need to preserve it ( it contains the ns definitions for the
* children we just moved ) . We ' ll just stick it on to the end
* of cur - > parent ' s list , since it ' s never going to be re - serialized
* ( bug 143738 ) .
*/
2014-07-14 16:14:44 +08:00
if ( ( cur - > nsDef ! = NULL ) & & ( cur - > parent ! = NULL ) ) {
2004-06-07 14:15:54 +00:00
xmlNsPtr parDef = ( xmlNsPtr ) & cur - > parent - > nsDef ;
while ( parDef - > next ! = NULL )
parDef = parDef - > next ;
parDef - > next = cur - > nsDef ;
cur - > nsDef = NULL ;
}
2003-10-07 11:33:24 +00:00
delete = cur ;
goto skip_children ;
}
}
}
/*
* Simplification 4.2 whitespaces
*/
else if ( ( cur - > type = = XML_TEXT_NODE ) | |
( cur - > type = = XML_CDATA_SECTION_NODE ) ) {
if ( IS_BLANK_NODE ( cur ) ) {
2014-07-14 16:14:44 +08:00
if ( ( cur - > parent ! = NULL ) & &
( cur - > parent - > type = = XML_ELEMENT_NODE ) ) {
2003-10-07 11:33:24 +00:00
if ( ( ! xmlStrEqual ( cur - > parent - > name , BAD_CAST " value " ) )
& &
( ! xmlStrEqual
( cur - > parent - > name , BAD_CAST " param " ) ) )
delete = cur ;
} else {
delete = cur ;
goto skip_children ;
}
}
} else {
delete = cur ;
goto skip_children ;
}
/*
* Skip to next node
*/
if ( cur - > children ! = NULL ) {
if ( ( cur - > children - > type ! = XML_ENTITY_DECL ) & &
( cur - > children - > type ! = XML_ENTITY_REF_NODE ) & &
( cur - > children - > type ! = XML_ENTITY_NODE ) ) {
cur = cur - > children ;
continue ;
}
}
skip_children :
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
continue ;
}
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
do {
cur = cur - > parent ;
if ( cur = = NULL )
break ;
if ( cur = = root ) {
cur = NULL ;
break ;
}
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
break ;
}
} while ( cur ! = NULL ) ;
2003-03-15 21:30:25 +00:00
}
if ( delete ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlUnlinkNode ( delete ) ;
xmlFreeNode ( delete ) ;
delete = NULL ;
2003-03-15 21:30:25 +00:00
}
}
/**
* xmlRelaxNGCleanupDoc :
* @ ctxt : a Relax - NG parser context
* @ doc : an xmldocPtr document pointer
*
* Cleanup the document from unwanted nodes for parsing , resolve
* Include and externalRef lookups .
*
* Returns the cleaned up document or NULL in case of error
*/
static xmlDocPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGCleanupDoc ( xmlRelaxNGParserCtxtPtr ctxt , xmlDocPtr doc )
{
2003-03-15 21:30:25 +00:00
xmlNodePtr root ;
/*
* Extract the root
*/
2003-01-23 18:29:16 +00:00
root = xmlDocGetRootElement ( doc ) ;
if ( root = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , ( xmlNodePtr ) doc , XML_RNGP_EMPTY , " xmlRelaxNGParse: %s is empty \n " ,
ctxt - > URL , NULL ) ;
2003-01-23 18:29:16 +00:00
return ( NULL ) ;
}
2003-03-15 21:30:25 +00:00
xmlRelaxNGCleanupTree ( ctxt , root ) ;
2003-10-07 11:33:24 +00:00
return ( doc ) ;
2003-03-15 21:30:25 +00:00
}
/**
* xmlRelaxNGParse :
* @ ctxt : a Relax - NG parser context
*
* parse a schema definition resource and build an internal
2019-09-30 17:04:54 +02:00
* XML Schema structure which can be used to validate instances .
2003-03-15 21:30:25 +00:00
*
* Returns the internal XML RelaxNG structure built from the resource or
* NULL in case of error
*/
xmlRelaxNGPtr
xmlRelaxNGParse ( xmlRelaxNGParserCtxtPtr ctxt )
{
xmlRelaxNGPtr ret = NULL ;
xmlDocPtr doc ;
xmlNodePtr root ;
xmlRelaxNGInitTypes ( ) ;
if ( ctxt = = NULL )
return ( NULL ) ;
/*
* First step is to parse the input document into an DOM / Infoset
*/
if ( ctxt - > URL ! = NULL ) {
2004-01-13 20:42:02 +00:00
doc = xmlReadFile ( ( const char * ) ctxt - > URL , NULL , 0 ) ;
2003-10-07 11:33:24 +00:00
if ( doc = = NULL ) {
xmlRngPErr ( ctxt , NULL , XML_RNGP_PARSE_ERROR ,
" xmlRelaxNGParse: could not load %s \n " , ctxt - > URL ,
NULL ) ;
return ( NULL ) ;
}
2003-03-15 21:30:25 +00:00
} else if ( ctxt - > buffer ! = NULL ) {
2004-01-13 20:42:02 +00:00
doc = xmlReadMemory ( ctxt - > buffer , ctxt - > size , NULL , NULL , 0 ) ;
2003-10-07 11:33:24 +00:00
if ( doc = = NULL ) {
xmlRngPErr ( ctxt , NULL , XML_RNGP_PARSE_ERROR ,
" xmlRelaxNGParse: could not parse schemas \n " , NULL ,
NULL ) ;
return ( NULL ) ;
}
doc - > URL = xmlStrdup ( BAD_CAST " in_memory_buffer " ) ;
ctxt - > URL = xmlStrdup ( BAD_CAST " in_memory_buffer " ) ;
2003-04-17 09:09:19 +00:00
} else if ( ctxt - > document ! = NULL ) {
doc = ctxt - > document ;
2003-03-15 21:30:25 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , NULL , XML_RNGP_EMPTY ,
" xmlRelaxNGParse: nothing to parse \n " , NULL , NULL ) ;
return ( NULL ) ;
2003-02-24 17:17:58 +00:00
}
2003-03-15 21:30:25 +00:00
ctxt - > document = doc ;
2003-01-23 18:29:16 +00:00
/*
2003-03-15 21:30:25 +00:00
* Some preprocessing of the document content
2003-01-23 18:29:16 +00:00
*/
2003-03-15 21:30:25 +00:00
doc = xmlRelaxNGCleanupDoc ( ctxt , doc ) ;
if ( doc = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlFreeDoc ( ctxt - > document ) ;
ctxt - > document = NULL ;
return ( NULL ) ;
2003-03-15 21:30:25 +00:00
}
2003-01-28 20:58:15 +00:00
/*
2003-03-15 21:30:25 +00:00
* Then do the parsing for good
2003-01-28 20:58:15 +00:00
*/
2003-03-15 21:30:25 +00:00
root = xmlDocGetRootElement ( doc ) ;
if ( root = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngPErr ( ctxt , ( xmlNodePtr ) doc ,
XML_RNGP_EMPTY , " xmlRelaxNGParse: %s is empty \n " ,
2006-05-06 03:16:22 +00:00
( ctxt - > URL ? ctxt - > URL : BAD_CAST " schemas " ) , NULL ) ;
2012-09-11 13:26:36 +08:00
2006-04-13 07:33:44 +00:00
xmlFreeDoc ( ctxt - > document ) ;
ctxt - > document = NULL ;
2003-03-15 21:30:25 +00:00
return ( NULL ) ;
}
ret = xmlRelaxNGParseDocument ( ctxt , root ) ;
if ( ret = = NULL ) {
2006-04-13 07:33:44 +00:00
xmlFreeDoc ( ctxt - > document ) ;
ctxt - > document = NULL ;
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-28 20:58:15 +00:00
}
2003-01-23 18:29:16 +00:00
2003-03-16 17:52:32 +00:00
/*
* Check the ref / defines links
*/
/*
* try to preprocess interleaves
*/
if ( ctxt - > interleaves ! = NULL ) {
2017-11-09 16:42:47 +01:00
xmlHashScan ( ctxt - > interleaves , xmlRelaxNGComputeInterleaves , ctxt ) ;
2003-03-16 17:52:32 +00:00
}
2003-01-23 18:29:16 +00:00
/*
* if there was a parsing error return NULL
*/
if ( ctxt - > nbErrors > 0 ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGFree ( ret ) ;
ctxt - > document = NULL ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
2003-01-23 18:29:16 +00:00
}
2003-04-13 19:53:42 +00:00
/*
* try to compile ( parts of ) the schemas
*/
2003-04-16 15:58:05 +00:00
if ( ( ret - > topgrammar ! = NULL ) & & ( ret - > topgrammar - > start ! = NULL ) ) {
if ( ret - > topgrammar - > start - > type ! = XML_RELAXNG_START ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr def ;
2003-04-15 23:32:22 +00:00
2003-10-07 11:33:24 +00:00
def = xmlRelaxNGNewDefine ( ctxt , NULL ) ;
if ( def ! = NULL ) {
def - > type = XML_RELAXNG_START ;
def - > content = ret - > topgrammar - > start ;
ret - > topgrammar - > start = def ;
}
}
xmlRelaxNGTryCompile ( ctxt , ret - > topgrammar - > start ) ;
2003-04-15 23:32:22 +00:00
}
2003-04-13 19:53:42 +00:00
2003-01-23 18:29:16 +00:00
/*
* Transfer the pointer for cleanup at the schema level .
*/
ret - > doc = doc ;
2003-01-29 21:07:52 +00:00
ctxt - > document = NULL ;
ret - > documents = ctxt - > documents ;
ctxt - > documents = NULL ;
2003-10-07 11:33:24 +00:00
2003-02-02 14:35:17 +00:00
ret - > includes = ctxt - > includes ;
ctxt - > includes = NULL ;
2003-02-03 23:22:49 +00:00
ret - > defNr = ctxt - > defNr ;
ret - > defTab = ctxt - > defTab ;
ctxt - > defTab = NULL ;
2003-03-18 00:31:04 +00:00
if ( ctxt - > idref = = 1 )
2003-10-07 11:33:24 +00:00
ret - > idref = 1 ;
2003-01-23 18:29:16 +00:00
return ( ret ) ;
}
2003-10-07 11:33:24 +00:00
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGSetParserErrors :
* @ ctxt : a Relax - NG validation context
* @ err : the error callback
* @ warn : the warning callback
* @ ctx : contextual data for the callbacks
*
* Set the callback functions used to handle errors for a validation context
*/
void
xmlRelaxNGSetParserErrors ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidityErrorFunc err ,
xmlRelaxNGValidityWarningFunc warn , void * ctx )
{
2003-01-23 18:29:16 +00:00
if ( ctxt = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
ctxt - > error = err ;
ctxt - > warning = warn ;
2005-09-04 13:50:03 +00:00
ctxt - > serror = NULL ;
2003-01-23 18:29:16 +00:00
ctxt - > userData = ctx ;
}
2003-07-18 15:16:57 +00:00
/**
* xmlRelaxNGGetParserErrors :
* @ ctxt : a Relax - NG validation context
* @ err : the error callback result
* @ warn : the warning callback result
* @ ctx : contextual data for the callbacks result
*
* Get the callback information used to handle errors for a validation context
*
* Returns - 1 in case of failure , 0 otherwise .
*/
int
xmlRelaxNGGetParserErrors ( xmlRelaxNGParserCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidityErrorFunc * err ,
xmlRelaxNGValidityWarningFunc * warn , void * * ctx )
{
2003-07-18 15:16:57 +00:00
if ( ctxt = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
if ( err ! = NULL )
* err = ctxt - > error ;
if ( warn ! = NULL )
* warn = ctxt - > warning ;
if ( ctx ! = NULL )
* ctx = ctxt - > userData ;
return ( 0 ) ;
2003-07-18 15:16:57 +00:00
}
2006-04-28 16:30:48 +00:00
/**
* xmlRelaxNGSetParserStructuredErrors :
* @ ctxt : a Relax - NG parser context
* @ serror : the error callback
* @ ctx : contextual data for the callbacks
*
* Set the callback functions used to handle errors for a parsing context
*/
2006-01-09 16:28:20 +00:00
void
2006-04-28 16:30:48 +00:00
xmlRelaxNGSetParserStructuredErrors ( xmlRelaxNGParserCtxtPtr ctxt ,
2006-01-09 16:28:20 +00:00
xmlStructuredErrorFunc serror ,
void * ctx )
{
if ( ctxt = = NULL )
return ;
ctxt - > serror = serror ;
ctxt - > error = NULL ;
ctxt - > warning = NULL ;
ctxt - > userData = ctx ;
}
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_OUTPUT_ENABLED
2003-10-07 11:33:24 +00:00
2003-01-23 18:29:16 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Dump back a compiled form *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
static void xmlRelaxNGDumpDefine ( FILE * output ,
xmlRelaxNGDefinePtr define ) ;
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGDumpDefines :
* @ output : the file output
* @ defines : a list of define structures
*
* Dump a RelaxNG structure back
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGDumpDefines ( FILE * output , xmlRelaxNGDefinePtr defines )
{
2003-01-23 18:29:16 +00:00
while ( defines ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDumpDefine ( output , defines ) ;
defines = defines - > next ;
2003-01-23 18:29:16 +00:00
}
}
/**
* xmlRelaxNGDumpDefine :
* @ output : the file output
* @ define : a define structure
*
* Dump a RelaxNG structure back
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGDumpDefine ( FILE * output , xmlRelaxNGDefinePtr define )
{
2003-01-23 18:29:16 +00:00
if ( define = = NULL )
2003-10-07 11:33:24 +00:00
return ;
switch ( define - > type ) {
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_EMPTY :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <empty/> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_NOT_ALLOWED :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <notAllowed/> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_TEXT :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <text/> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_ELEMENT :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <element> \n " ) ;
if ( define - > name ! = NULL ) {
fprintf ( output , " <name " ) ;
if ( define - > ns ! = NULL )
fprintf ( output , " ns= \" %s \" " , define - > ns ) ;
fprintf ( output , " >%s</name> \n " , define - > name ) ;
}
xmlRelaxNGDumpDefines ( output , define - > attrs ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </element> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_LIST :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <list> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </list> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_ONEORMORE :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <oneOrMore> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </oneOrMore> \n " ) ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_ZEROORMORE :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <zeroOrMore> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </zeroOrMore> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_CHOICE :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <choice> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </choice> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_GROUP :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <group> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </group> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_INTERLEAVE :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <interleave> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </interleave> \n " ) ;
break ;
case XML_RELAXNG_OPTIONAL :
fprintf ( output , " <optional> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </optional> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_ATTRIBUTE :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <attribute> \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </attribute> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_DEF :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <define " ) ;
if ( define - > name ! = NULL )
fprintf ( output , " name= \" %s \" " , define - > name ) ;
fprintf ( output , " > \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </define> \n " ) ;
break ;
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_REF :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <ref " ) ;
if ( define - > name ! = NULL )
fprintf ( output , " name= \" %s \" " , define - > name ) ;
fprintf ( output , " > \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </ref> \n " ) ;
break ;
2003-02-03 23:22:49 +00:00
case XML_RELAXNG_PARENTREF :
2003-10-07 11:33:24 +00:00
fprintf ( output , " <parentRef " ) ;
if ( define - > name ! = NULL )
fprintf ( output , " name= \" %s \" " , define - > name ) ;
fprintf ( output , " > \n " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </parentRef> \n " ) ;
break ;
case XML_RELAXNG_EXTERNALREF :
fprintf ( output , " <externalRef> " ) ;
xmlRelaxNGDumpDefines ( output , define - > content ) ;
fprintf ( output , " </externalRef> \n " ) ;
break ;
2003-01-29 23:02:33 +00:00
case XML_RELAXNG_DATATYPE :
2003-01-23 18:29:16 +00:00
case XML_RELAXNG_VALUE :
2003-10-07 11:33:24 +00:00
TODO break ;
case XML_RELAXNG_START :
case XML_RELAXNG_EXCEPT :
case XML_RELAXNG_PARAM :
TODO break ;
case XML_RELAXNG_NOOP :
xmlRelaxNGDumpDefines ( output , define - > content ) ;
break ;
2003-01-23 18:29:16 +00:00
}
}
2003-10-07 11:33:24 +00:00
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGDumpGrammar :
* @ output : the file output
* @ grammar : a grammar structure
2012-09-11 13:26:36 +08:00
* @ top : is this a top grammar
2003-01-23 18:29:16 +00:00
*
* Dump a RelaxNG structure back
*/
static void
xmlRelaxNGDumpGrammar ( FILE * output , xmlRelaxNGGrammarPtr grammar , int top )
{
if ( grammar = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
fprintf ( output , " <grammar " ) ;
if ( top )
2003-10-07 11:33:24 +00:00
fprintf ( output , " xmlns= \" http://relaxng.org/ns/structure/1.0 \" " ) ;
switch ( grammar - > combine ) {
case XML_RELAXNG_COMBINE_UNDEFINED :
break ;
case XML_RELAXNG_COMBINE_CHOICE :
fprintf ( output , " combine= \" choice \" " ) ;
break ;
case XML_RELAXNG_COMBINE_INTERLEAVE :
fprintf ( output , " combine= \" interleave \" " ) ;
break ;
default :
fprintf ( output , " <!-- invalid combine value --> " ) ;
2003-01-23 18:29:16 +00:00
}
fprintf ( output , " > \n " ) ;
if ( grammar - > start = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " <!-- grammar had no start --> " ) ;
2003-01-23 18:29:16 +00:00
} else {
2003-10-07 11:33:24 +00:00
fprintf ( output , " <start> \n " ) ;
xmlRelaxNGDumpDefine ( output , grammar - > start ) ;
fprintf ( output , " </start> \n " ) ;
2003-01-23 18:29:16 +00:00
}
/* TODO ? Dump the defines ? */
fprintf ( output , " </grammar> \n " ) ;
}
/**
* xmlRelaxNGDump :
* @ output : the file output
* @ schema : a schema structure
*
* Dump a RelaxNG structure back
*/
void
xmlRelaxNGDump ( FILE * output , xmlRelaxNGPtr schema )
{
2004-11-05 17:22:25 +00:00
if ( output = = NULL )
return ;
2003-01-23 18:29:16 +00:00
if ( schema = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " RelaxNG empty or failed to compile \n " ) ;
return ;
2003-01-23 18:29:16 +00:00
}
fprintf ( output , " RelaxNG: " ) ;
if ( schema - > doc = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " no document \n " ) ;
2003-01-23 18:29:16 +00:00
} else if ( schema - > doc - > URL ! = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " %s \n " , schema - > doc - > URL ) ;
2003-01-23 18:29:16 +00:00
} else {
2003-10-07 11:33:24 +00:00
fprintf ( output , " \n " ) ;
2003-01-23 18:29:16 +00:00
}
if ( schema - > topgrammar = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " RelaxNG has no top grammar \n " ) ;
return ;
2003-01-23 18:29:16 +00:00
}
xmlRelaxNGDumpGrammar ( output , schema - > topgrammar , 1 ) ;
}
2003-02-16 15:44:18 +00:00
/**
* xmlRelaxNGDumpTree :
* @ output : the file output
* @ schema : a schema structure
*
* Dump the transformed RelaxNG tree .
*/
void
xmlRelaxNGDumpTree ( FILE * output , xmlRelaxNGPtr schema )
{
2004-11-05 17:22:25 +00:00
if ( output = = NULL )
return ;
2003-02-16 15:44:18 +00:00
if ( schema = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " RelaxNG empty or failed to compile \n " ) ;
return ;
2003-02-16 15:44:18 +00:00
}
if ( schema - > doc = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( output , " no document \n " ) ;
2003-02-16 15:44:18 +00:00
} else {
2003-10-07 11:33:24 +00:00
xmlDocDump ( output , schema - > doc ) ;
2003-02-16 15:44:18 +00:00
}
}
2003-09-29 13:20:24 +00:00
# endif /* LIBXML_OUTPUT_ENABLED */
2003-02-16 15:44:18 +00:00
2003-01-23 18:29:16 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Validation of compiled content *
* *
2003-01-23 18:29:16 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
static int xmlRelaxNGValidateDefinition ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define ) ;
2003-04-14 16:11:26 +00:00
/**
* xmlRelaxNGValidateCompiledCallback :
* @ 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 .
*/
2003-10-07 11:33:24 +00:00
static void
2003-04-14 16:11:26 +00:00
xmlRelaxNGValidateCompiledCallback ( xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
const xmlChar * token ,
void * transdata , void * inputdata )
{
2003-04-14 16:11:26 +00:00
xmlRelaxNGValidCtxtPtr ctxt = ( xmlRelaxNGValidCtxtPtr ) inputdata ;
xmlRelaxNGDefinePtr define = ( xmlRelaxNGDefinePtr ) transdata ;
int ret ;
# ifdef DEBUG_COMPILE
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" Compiled callback for: '%s' \n " , token ) ;
2003-04-14 16:11:26 +00:00
# endif
if ( ctxt = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( stderr , " callback on %s missing context \n " , token ) ;
return ;
2003-04-14 16:11:26 +00:00
}
if ( define = = NULL ) {
if ( token [ 0 ] = = ' # ' )
2003-10-07 11:33:24 +00:00
return ;
fprintf ( stderr , " callback on %s missing define \n " , token ) ;
if ( ( ctxt ! = NULL ) & & ( ctxt - > errNo = = XML_RELAXNG_OK ) )
ctxt - > errNo = XML_RELAXNG_ERR_INTERNAL ;
return ;
2003-04-14 16:11:26 +00:00
}
if ( ( ctxt = = NULL ) | | ( define = = NULL ) ) {
2003-10-07 11:33:24 +00:00
fprintf ( stderr , " callback on %s missing info \n " , token ) ;
if ( ( ctxt ! = NULL ) & & ( ctxt - > errNo = = XML_RELAXNG_OK ) )
ctxt - > errNo = XML_RELAXNG_ERR_INTERNAL ;
return ;
2003-04-14 16:11:26 +00:00
} else if ( define - > type ! = XML_RELAXNG_ELEMENT ) {
2003-10-07 11:33:24 +00:00
fprintf ( stderr , " callback on %s define is not element \n " , token ) ;
if ( ctxt - > errNo = = XML_RELAXNG_OK )
ctxt - > errNo = XML_RELAXNG_ERR_INTERNAL ;
return ;
2003-04-14 16:11:26 +00:00
}
ret = xmlRelaxNGValidateDefinition ( ctxt , define ) ;
2003-08-26 13:56:48 +00:00
if ( ret ! = 0 )
ctxt - > perr = ret ;
2003-04-14 16:11:26 +00:00
}
/**
* xmlRelaxNGValidateCompiledContent :
* @ ctxt : the RelaxNG validation context
* @ regexp : the regular expression as compiled
* @ content : list of children to test against the regexp
*
* Validate the content model of an element or start using the regexp
*
* Returns 0 in case of success , - 1 in case of error .
*/
static int
xmlRelaxNGValidateCompiledContent ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRegexpPtr regexp , xmlNodePtr content )
{
2003-04-14 16:11:26 +00:00
xmlRegExecCtxtPtr exec ;
xmlNodePtr cur ;
2003-04-17 09:36:38 +00:00
int ret = 0 ;
2006-03-09 18:41:40 +00:00
int oldperr ;
2003-04-14 16:11:26 +00:00
if ( ( ctxt = = NULL ) | | ( regexp = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2006-03-09 18:41:40 +00:00
oldperr = ctxt - > perr ;
2003-10-07 11:33:24 +00:00
exec = xmlRegNewExecCtxt ( regexp ,
2003-04-14 16:11:26 +00:00
xmlRelaxNGValidateCompiledCallback , ctxt ) ;
2003-08-26 13:56:48 +00:00
ctxt - > perr = 0 ;
2003-04-14 16:11:26 +00:00
cur = content ;
while ( cur ! = NULL ) {
ctxt - > state - > seq = cur ;
2003-10-07 11:33:24 +00:00
switch ( cur - > type ) {
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
if ( xmlIsBlankNode ( cur ) )
break ;
ret = xmlRegExecPushString ( exec , BAD_CAST " #text " , ctxt ) ;
if ( ret < 0 ) {
VALID_ERR2 ( XML_RELAXNG_ERR_TEXTWRONG ,
cur - > parent - > name ) ;
}
break ;
case XML_ELEMENT_NODE :
if ( cur - > ns ! = NULL ) {
ret = xmlRegExecPushString2 ( exec , cur - > name ,
cur - > ns - > href , ctxt ) ;
} else {
ret = xmlRegExecPushString ( exec , cur - > name , ctxt ) ;
}
if ( ret < 0 ) {
VALID_ERR2 ( XML_RELAXNG_ERR_ELEMWRONG , cur - > name ) ;
}
break ;
default :
break ;
}
if ( ret < 0 )
break ;
/*
* Switch to next element
*/
cur = cur - > next ;
2003-04-14 16:11:26 +00:00
}
ret = xmlRegExecPushString ( exec , NULL , NULL ) ;
if ( ret = = 1 ) {
ret = 0 ;
2003-10-07 11:33:24 +00:00
ctxt - > state - > seq = NULL ;
2003-04-14 16:11:26 +00:00
} else if ( ret = = 0 ) {
/*
2003-10-07 11:33:24 +00:00
* TODO : get some of the names needed to exit the current state of exec
*/
VALID_ERR2 ( XML_RELAXNG_ERR_NOELEM , BAD_CAST " " ) ;
ret = - 1 ;
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
2003-04-14 16:11:26 +00:00
} else {
ret = - 1 ;
}
xmlRegFreeExecCtxt ( exec ) ;
2003-08-26 13:56:48 +00:00
/*
* There might be content model errors outside of the pure
* regexp validation , e . g . for attribute values .
*/
if ( ( ret = = 0 ) & & ( ctxt - > perr ! = 0 ) ) {
ret = ctxt - > perr ;
}
ctxt - > perr = oldperr ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-04-14 16:11:26 +00:00
}
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Progressive validation of when possible *
* *
2003-04-14 16:11:26 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
static int xmlRelaxNGValidateAttributeList ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr defines ) ;
static int xmlRelaxNGValidateElementEnd ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-11-14 16:20:34 +00:00
int dolog ) ;
2003-08-27 14:15:15 +00:00
static void xmlRelaxNGLogBestError ( xmlRelaxNGValidCtxtPtr ctxt ) ;
2003-04-15 23:32:22 +00:00
/**
* 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
2003-10-07 11:33:24 +00:00
xmlRelaxNGElemPush ( xmlRelaxNGValidCtxtPtr ctxt , xmlRegExecCtxtPtr exec )
{
2003-04-15 23:32:22 +00:00
if ( ctxt - > elemTab = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > elemMax = 10 ;
ctxt - > elemTab = ( xmlRegExecCtxtPtr * ) xmlMalloc ( ctxt - > elemMax *
sizeof
( xmlRegExecCtxtPtr ) ) ;
2003-04-15 23:32:22 +00:00
if ( ctxt - > elemTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
return ( - 1 ) ;
}
2003-04-15 23:32:22 +00:00
}
if ( ctxt - > elemNr > = ctxt - > elemMax ) {
2003-10-07 11:33:24 +00:00
ctxt - > elemMax * = 2 ;
2003-04-15 23:32:22 +00:00
ctxt - > elemTab = ( xmlRegExecCtxtPtr * ) xmlRealloc ( ctxt - > elemTab ,
2003-10-07 11:33:24 +00:00
ctxt - > elemMax *
sizeof
( xmlRegExecCtxtPtr ) ) ;
2003-04-15 23:32:22 +00:00
if ( ctxt - > elemTab = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
return ( - 1 ) ;
}
2003-04-15 23:32:22 +00:00
}
ctxt - > elemTab [ ctxt - > elemNr + + ] = exec ;
ctxt - > elem = exec ;
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-04-15 23:32:22 +00:00
}
/**
* 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
2003-10-07 11:33:24 +00:00
xmlRelaxNGElemPop ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-04-15 23:32:22 +00:00
xmlRegExecCtxtPtr ret ;
2003-10-07 11:33:24 +00:00
if ( ctxt - > elemNr < = 0 )
return ( NULL ) ;
2003-04-15 23:32:22 +00:00
ctxt - > elemNr - - ;
ret = ctxt - > elemTab [ ctxt - > elemNr ] ;
ctxt - > elemTab [ ctxt - > elemNr ] = NULL ;
2003-10-07 11:33:24 +00:00
if ( ctxt - > elemNr > 0 )
2003-04-15 23:32:22 +00:00
ctxt - > elem = ctxt - > elemTab [ ctxt - > elemNr - 1 ] ;
else
2003-10-07 11:33:24 +00:00
ctxt - > elem = NULL ;
return ( ret ) ;
2003-04-15 23:32:22 +00:00
}
/**
* 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 .
2020-03-08 17:19:42 +01:00
* some of the in / out information are passed via the context in @ inputdata .
2003-04-15 23:32:22 +00:00
*/
2003-10-07 11:33:24 +00:00
static void
xmlRelaxNGValidateProgressiveCallback ( xmlRegExecCtxtPtr exec
ATTRIBUTE_UNUSED ,
const xmlChar * token ,
void * transdata , void * inputdata )
{
2003-04-15 23:32:22 +00:00
xmlRelaxNGValidCtxtPtr ctxt = ( xmlRelaxNGValidCtxtPtr ) inputdata ;
xmlRelaxNGDefinePtr define = ( xmlRelaxNGDefinePtr ) transdata ;
2003-04-16 15:58:05 +00:00
xmlRelaxNGValidStatePtr state , oldstate ;
2006-03-09 18:41:40 +00:00
xmlNodePtr node ;
2003-05-09 22:26:28 +00:00
int ret = 0 , oldflags ;
2003-04-15 23:32:22 +00:00
# ifdef DEBUG_PROGRESSIVE
xmlGenericError ( xmlGenericErrorContext ,
2003-10-07 11:33:24 +00:00
" Progressive callback for: '%s' \n " , token ) ;
2003-04-15 23:32:22 +00:00
# endif
if ( ctxt = = NULL ) {
2003-10-07 11:33:24 +00:00
fprintf ( stderr , " callback on %s missing context \n " , token ) ;
return ;
2003-04-15 23:32:22 +00:00
}
2006-03-09 18:41:40 +00:00
node = ctxt - > pnode ;
2003-04-15 23:32:22 +00:00
ctxt - > pstate = 1 ;
if ( define = = NULL ) {
if ( token [ 0 ] = = ' # ' )
2003-10-07 11:33:24 +00:00
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 ;
2003-04-15 23:32:22 +00:00
}
if ( ( ctxt = = NULL ) | | ( define = = NULL ) ) {
2003-10-07 11:33:24 +00:00
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 ;
2003-04-15 23:32:22 +00:00
} else if ( define - > type ! = XML_RELAXNG_ELEMENT ) {
2003-10-07 11:33:24 +00:00
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 ;
2003-04-15 23:32:22 +00:00
}
if ( node - > type ! = XML_ELEMENT_NODE ) {
2003-10-07 11:33:24 +00:00
VALID_ERR ( XML_RELAXNG_ERR_NOTELEM ) ;
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
ctxt - > pstate = - 1 ;
return ;
2003-04-15 23:32:22 +00:00
}
if ( define - > contModel = = NULL ) {
/*
2003-10-07 11:33:24 +00:00
* this node cannot be validated in a streamable fashion
*/
2003-04-15 23:32:22 +00:00
# ifdef DEBUG_PROGRESSIVE
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Element '%s' validation is not streamable \n " ,
token ) ;
2003-04-15 23:32:22 +00:00
# endif
2003-10-07 11:33:24 +00:00
ctxt - > pstate = 0 ;
ctxt - > pdef = define ;
return ;
2003-04-15 23:32:22 +00:00
}
exec = xmlRegNewExecCtxt ( define - > contModel ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateProgressiveCallback , ctxt ) ;
2003-04-15 23:32:22 +00:00
if ( exec = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > pstate = - 1 ;
return ;
2003-04-15 23:32:22 +00:00
}
xmlRelaxNGElemPush ( ctxt , exec ) ;
/*
* Validate the attributes part of the content .
*/
state = xmlRelaxNGNewValidState ( ctxt , node ) ;
if ( state = = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > pstate = - 1 ;
return ;
2003-04-15 23:32:22 +00:00
}
2003-04-16 15:58:05 +00:00
oldstate = ctxt - > state ;
2003-04-15 23:32:22 +00:00
ctxt - > state = state ;
if ( define - > attrs ! = NULL ) {
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGValidateAttributeList ( ctxt , define - > attrs ) ;
if ( ret ! = 0 ) {
ctxt - > pstate = - 1 ;
VALID_ERR2 ( XML_RELAXNG_ERR_ATTRVALID , node - > name ) ;
}
2003-04-15 23:32:22 +00:00
}
2003-04-16 15:58:05 +00:00
if ( ctxt - > state ! = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > state - > seq = NULL ;
ret = xmlRelaxNGValidateElementEnd ( ctxt , 1 ) ;
if ( ret ! = 0 ) {
ctxt - > pstate = - 1 ;
}
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
2003-04-16 15:58:05 +00:00
} else if ( ctxt - > states ! = NULL ) {
2003-10-07 11:33:24 +00:00
int tmp = - 1 , i ;
2003-04-16 15:58:05 +00:00
oldflags = ctxt - > flags ;
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
state = ctxt - > states - > tabState [ i ] ;
ctxt - > state = state ;
ctxt - > state - > seq = NULL ;
if ( xmlRelaxNGValidateElementEnd ( ctxt , 0 ) = = 0 ) {
tmp = 0 ;
break ;
}
}
if ( tmp ! = 0 ) {
/*
* validation error , log the message for the " best " one
*/
ctxt - > flags | = FLAGS_IGNORABLE ;
xmlRelaxNGLogBestError ( ctxt ) ;
}
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
xmlRelaxNGFreeValidState ( ctxt , ctxt - > states - > tabState [ i ] ) ;
}
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
if ( ( ret = = 0 ) & & ( tmp = = - 1 ) )
ctxt - > pstate = - 1 ;
ctxt - > flags = oldflags ;
2003-04-15 23:32:22 +00:00
}
2003-04-16 15:58:05 +00:00
if ( ctxt - > pstate = = - 1 ) {
2003-10-07 11:33:24 +00:00
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 ) {
xmlRelaxNGDumpValidError ( ctxt ) ;
}
2003-04-16 15:58:05 +00:00
}
ctxt - > state = oldstate ;
2003-04-15 23:32:22 +00:00
}
/**
* 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
2003-04-17 09:09:19 +00:00
xmlRelaxNGValidatePushElement ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlDocPtr doc ATTRIBUTE_UNUSED ,
2003-04-15 23:32:22 +00:00
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 ) {
2003-10-07 11:33:24 +00:00
ctxt - > pdef = define ;
2003-04-15 23:32:22 +00:00
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 )
2003-10-07 11:33:24 +00:00
ret = 0 ;
2003-04-15 23:32:22 +00:00
else if ( ctxt - > pstate < 0 )
2003-10-07 11:33:24 +00:00
ret = - 1 ;
else
ret = 1 ;
2003-04-15 23:32:22 +00:00
}
# ifdef DEBUG_PROGRESSIVE
if ( ret < 0 )
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " PushElem %s failed \n " ,
elem - > name ) ;
2003-04-15 23:32:22 +00:00
# endif
return ( ret ) ;
}
/**
* xmlRelaxNGValidatePushCData :
* @ ctxt : the RelaxNG validation context
* @ data : some character data read
2012-09-28 08:59:33 +02:00
* @ len : the length of the data
2003-04-15 23:32:22 +00:00
*
* 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 ,
2003-10-07 11:33:24 +00:00
const xmlChar * data , int len ATTRIBUTE_UNUSED )
2003-04-15 23:32:22 +00:00
{
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 ) {
2003-10-18 16:20:14 +00:00
if ( ! IS_BLANK_CH ( * data ) )
2003-04-15 23:32:22 +00:00
break ;
data + + ;
}
if ( * data = = 0 )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-04-15 23:32:22 +00:00
ret = xmlRegExecPushString ( ctxt - > elem , BAD_CAST " #text " , ctxt ) ;
if ( ret < 0 ) {
2003-04-17 09:09:19 +00:00
VALID_ERR2 ( XML_RELAXNG_ERR_TEXTWRONG , BAD_CAST " TODO " ) ;
2003-04-15 23:32:22 +00:00
# ifdef DEBUG_PROGRESSIVE
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " CDATA failed \n " ) ;
2003-04-15 23:32:22 +00:00
# endif
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-04-15 23:32:22 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-04-15 23:32:22 +00:00
}
/**
* 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 ,
2003-10-07 11:33:24 +00:00
xmlNodePtr elem )
{
2003-04-15 23:32:22 +00:00
int ret ;
xmlRegExecCtxtPtr exec ;
2003-10-07 11:33:24 +00:00
if ( ( ctxt = = NULL ) | | ( ctxt - > elem = = NULL ) | | ( elem = = NULL ) )
return ( - 1 ) ;
2003-04-15 23:32:22 +00:00
# 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 ) {
/*
2003-10-07 11:33:24 +00:00
* TODO : get some of the names needed to exit the current state of exec
*/
VALID_ERR2 ( XML_RELAXNG_ERR_NOELEM , BAD_CAST " " ) ;
ret = - 1 ;
2003-04-15 23:32:22 +00:00
} else if ( ret < 0 ) {
ret = - 1 ;
} else {
ret = 1 ;
}
xmlRegFreeExecCtxt ( exec ) ;
# ifdef DEBUG_PROGRESSIVE
if ( ret < 0 )
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " PopElem %s failed \n " ,
elem - > name ) ;
2003-04-15 23:32:22 +00:00
# endif
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-04-15 23:32:22 +00:00
}
/**
* 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
2003-04-17 09:09:19 +00:00
xmlRelaxNGValidateFullElement ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlDocPtr doc ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
xmlNodePtr elem )
{
2003-04-15 23:32:22 +00:00
int ret ;
xmlRelaxNGValidStatePtr state ;
2003-10-07 11:33:24 +00:00
if ( ( ctxt = = NULL ) | | ( ctxt - > pdef = = NULL ) | | ( elem = = NULL ) )
return ( - 1 ) ;
2003-04-15 23:32:22 +00:00
# ifdef DEBUG_PROGRESSIVE
xmlGenericError ( xmlGenericErrorContext , " FullElem %s \n " , elem - > name ) ;
# endif
state = xmlRelaxNGNewValidState ( ctxt , elem - > parent ) ;
if ( state = = NULL ) {
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-04-15 23:32:22 +00:00
}
state - > seq = elem ;
ctxt - > state = state ;
ctxt - > errNo = XML_RELAXNG_OK ;
ret = xmlRelaxNGValidateDefinition ( ctxt , ctxt - > pdef ) ;
2003-10-07 11:33:24 +00:00
if ( ( ret ! = 0 ) | | ( ctxt - > errNo ! = XML_RELAXNG_OK ) )
ret = - 1 ;
else
ret = 1 ;
2009-08-14 16:16:31 +02:00
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
2003-04-15 23:32:22 +00:00
ctxt - > state = NULL ;
# ifdef DEBUG_PROGRESSIVE
if ( ret < 0 )
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext , " FullElem %s failed \n " ,
elem - > name ) ;
2003-04-15 23:32:22 +00:00
# endif
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-04-15 23:32:22 +00:00
}
2003-04-14 16:11:26 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Generic interpreted validation implementation *
* *
2003-04-14 16:11:26 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
static int xmlRelaxNGValidateValue ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define ) ;
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGSkipIgnored :
* @ ctxt : a schema validation context
* @ node : the top node .
*
* Skip ignorable nodes in that context
*
* Returns the new sibling or NULL in case of error .
*/
static xmlNodePtr
xmlRelaxNGSkipIgnored ( xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED ,
2003-10-07 11:33:24 +00:00
xmlNodePtr node )
{
2003-01-23 18:29:16 +00:00
/*
* TODO complete and handle entities
*/
while ( ( node ! = NULL ) & &
2003-10-07 11:33:24 +00:00
( ( node - > type = = XML_COMMENT_NODE ) | |
( node - > type = = XML_PI_NODE ) | |
2004-03-15 02:43:56 +00:00
( node - > type = = XML_XINCLUDE_START ) | |
( node - > type = = XML_XINCLUDE_END ) | |
2003-10-07 11:33:24 +00:00
( ( ( node - > type = = XML_TEXT_NODE ) | |
( node - > type = = XML_CDATA_SECTION_NODE ) ) & &
( ( ctxt - > flags & FLAGS_MIXED_CONTENT ) | |
( IS_BLANK_NODE ( node ) ) ) ) ) ) {
node = node - > next ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( node ) ;
2003-01-23 18:29:16 +00:00
}
2003-01-26 00:52:04 +00:00
/**
* xmlRelaxNGNormalize :
* @ ctxt : a schema validation context
* @ str : the string to normalize
*
* Implements the normalizeWhiteSpace ( s ) function from
* section 6.2 .9 of the spec
*
* Returns the new string or NULL in case of error .
*/
static xmlChar *
2003-10-07 11:33:24 +00:00
xmlRelaxNGNormalize ( xmlRelaxNGValidCtxtPtr ctxt , const xmlChar * str )
{
2003-01-26 00:52:04 +00:00
xmlChar * ret , * p ;
const xmlChar * tmp ;
int len ;
2003-10-07 11:33:24 +00:00
2003-01-26 00:52:04 +00:00
if ( str = = NULL )
2003-10-07 11:33:24 +00:00
return ( NULL ) ;
2003-01-26 00:52:04 +00:00
tmp = str ;
2003-10-07 11:33:24 +00:00
while ( * tmp ! = 0 )
tmp + + ;
2003-01-26 00:52:04 +00:00
len = tmp - str ;
2022-09-01 03:14:13 +02:00
ret = ( xmlChar * ) xmlMallocAtomic ( len + 1 ) ;
2003-01-26 00:52:04 +00:00
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
return ( NULL ) ;
2003-01-26 00:52:04 +00:00
}
p = ret ;
2003-10-18 16:20:14 +00:00
while ( IS_BLANK_CH ( * str ) )
2003-10-07 11:33:24 +00:00
str + + ;
2003-01-26 00:52:04 +00:00
while ( * str ! = 0 ) {
2003-10-18 16:20:14 +00:00
if ( IS_BLANK_CH ( * str ) ) {
while ( IS_BLANK_CH ( * str ) )
2003-10-07 11:33:24 +00:00
str + + ;
if ( * str = = 0 )
break ;
* p + + = ' ' ;
} else
* p + + = * str + + ;
2003-01-26 00:52:04 +00:00
}
* p = 0 ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-26 00:52:04 +00:00
}
2003-01-25 18:01:32 +00:00
/**
* xmlRelaxNGValidateDatatype :
* @ ctxt : a Relax - NG validation context
* @ value : the string value
* @ type : the datatype definition
2003-03-18 00:31:04 +00:00
* @ node : the node
2003-01-25 18:01:32 +00:00
*
2019-09-30 17:04:54 +02:00
* Validate the given value against the datatype
2003-01-25 18:01:32 +00:00
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateDatatype ( xmlRelaxNGValidCtxtPtr ctxt ,
const xmlChar * value ,
xmlRelaxNGDefinePtr define , xmlNodePtr node )
{
2003-02-27 17:42:22 +00:00
int ret , tmp ;
2003-01-25 18:01:32 +00:00
xmlRelaxNGTypeLibraryPtr lib ;
2003-02-27 17:42:22 +00:00
void * result = NULL ;
xmlRelaxNGDefinePtr cur ;
2003-01-25 18:01:32 +00:00
if ( ( define = = NULL ) | | ( define - > data = = NULL ) ) {
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
}
lib = ( xmlRelaxNGTypeLibraryPtr ) define - > data ;
2003-02-27 17:42:22 +00:00
if ( lib - > check ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( define - > attrs ! = NULL ) & &
( define - > attrs - > type = = XML_RELAXNG_PARAM ) ) {
ret =
lib - > check ( lib - > data , define - > name , value , & result , node ) ;
} else {
ret = lib - > check ( lib - > data , define - > name , value , NULL , node ) ;
}
} else
ret = - 1 ;
2003-01-25 18:01:32 +00:00
if ( ret < 0 ) {
2003-10-07 11:33:24 +00:00
VALID_ERR2 ( XML_RELAXNG_ERR_TYPE , define - > name ) ;
if ( ( result ! = NULL ) & & ( lib ! = NULL ) & & ( lib - > freef ! = NULL ) )
lib - > freef ( lib - > data , result ) ;
return ( - 1 ) ;
2003-01-25 18:01:32 +00:00
} else if ( ret = = 1 ) {
2003-10-07 11:33:24 +00:00
ret = 0 ;
2003-03-18 00:31:04 +00:00
} else if ( ret = = 2 ) {
2003-10-07 11:33:24 +00:00
VALID_ERR2P ( XML_RELAXNG_ERR_DUPID , value ) ;
2003-01-25 18:01:32 +00:00
} else {
2003-10-07 11:33:24 +00:00
VALID_ERR3P ( XML_RELAXNG_ERR_TYPEVAL , define - > name , value ) ;
ret = - 1 ;
2003-01-25 18:01:32 +00:00
}
2003-03-16 17:52:32 +00:00
cur = define - > attrs ;
2003-02-27 17:42:22 +00:00
while ( ( ret = = 0 ) & & ( cur ! = NULL ) & & ( cur - > type = = XML_RELAXNG_PARAM ) ) {
2003-10-07 11:33:24 +00:00
if ( lib - > facet ! = NULL ) {
tmp = lib - > facet ( lib - > data , define - > name , cur - > name ,
cur - > value , value , result ) ;
2003-02-27 17:42:22 +00:00
if ( tmp ! = 0 )
2003-10-07 11:33:24 +00:00
ret = - 1 ;
}
cur = cur - > next ;
2003-02-27 17:42:22 +00:00
}
2003-02-17 17:25:42 +00:00
if ( ( ret = = 0 ) & & ( define - > content ! = NULL ) ) {
2003-10-07 11:33:24 +00:00
const xmlChar * oldvalue , * oldendvalue ;
2003-02-17 17:25:42 +00:00
2003-10-07 11:33:24 +00:00
oldvalue = ctxt - > state - > value ;
oldendvalue = ctxt - > state - > endvalue ;
ctxt - > state - > value = ( xmlChar * ) value ;
ctxt - > state - > endvalue = NULL ;
ret = xmlRelaxNGValidateValue ( ctxt , define - > content ) ;
ctxt - > state - > value = ( xmlChar * ) oldvalue ;
ctxt - > state - > endvalue = ( xmlChar * ) oldendvalue ;
2003-02-17 17:25:42 +00:00
}
2003-02-27 17:42:22 +00:00
if ( ( result ! = NULL ) & & ( lib ! = NULL ) & & ( lib - > freef ! = NULL ) )
2003-10-07 11:33:24 +00:00
lib - > freef ( lib - > data , result ) ;
return ( ret ) ;
2003-01-25 18:01:32 +00:00
}
2003-01-27 12:35:42 +00:00
/**
* xmlRelaxNGNextValue :
* @ ctxt : a Relax - NG validation context
*
* Skip to the next value when validating within a list
*
* Returns 0 if the operation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGNextValue ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-01-27 12:35:42 +00:00
xmlChar * cur ;
cur = ctxt - > state - > value ;
if ( ( cur = = NULL ) | | ( ctxt - > state - > endvalue = = NULL ) ) {
2003-10-07 11:33:24 +00:00
ctxt - > state - > value = NULL ;
ctxt - > state - > endvalue = NULL ;
return ( 0 ) ;
2003-01-27 12:35:42 +00:00
}
2003-10-07 11:33:24 +00:00
while ( * cur ! = 0 )
cur + + ;
while ( ( cur ! = ctxt - > state - > endvalue ) & & ( * cur = = 0 ) )
cur + + ;
2003-01-27 12:35:42 +00:00
if ( cur = = ctxt - > state - > endvalue )
2003-10-07 11:33:24 +00:00
ctxt - > state - > value = NULL ;
2003-01-27 12:35:42 +00:00
else
2003-10-07 11:33:24 +00:00
ctxt - > state - > value = cur ;
return ( 0 ) ;
2003-01-27 12:35:42 +00:00
}
/**
* xmlRelaxNGValidateValueList :
* @ ctxt : a Relax - NG validation context
* @ defines : the list of definitions to verify
*
* Validate the given set of definitions for the current value
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateValueList ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr defines )
{
2003-01-27 12:35:42 +00:00
int ret = 0 ;
while ( defines ! = NULL ) {
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGValidateValue ( ctxt , defines ) ;
if ( ret ! = 0 )
break ;
defines = defines - > next ;
2003-01-27 12:35:42 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-27 12:35:42 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGValidateValue :
* @ ctxt : a Relax - NG validation context
* @ define : the definition to verify
*
* Validate the given definition for the current value
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateValue ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define )
{
2003-01-26 00:52:04 +00:00
int ret = 0 , oldflags ;
2003-01-23 18:29:16 +00:00
xmlChar * value ;
value = ctxt - > state - > value ;
switch ( define - > type ) {
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_EMPTY : {
if ( ( value ! = NULL ) & & ( value [ 0 ] ! = 0 ) ) {
int idx = 0 ;
2003-10-18 16:20:14 +00:00
while ( IS_BLANK_CH ( value [ idx ] ) )
2003-10-07 11:33:24 +00:00
idx + + ;
if ( value [ idx ] ! = 0 )
ret = - 1 ;
}
break ;
}
case XML_RELAXNG_TEXT :
break ;
case XML_RELAXNG_VALUE : {
if ( ! xmlStrEqual ( value , define - > value ) ) {
if ( define - > name ! = NULL ) {
xmlRelaxNGTypeLibraryPtr lib ;
lib = ( xmlRelaxNGTypeLibraryPtr ) define - > data ;
if ( ( lib ! = NULL ) & & ( lib - > comp ! = NULL ) ) {
ret = lib - > comp ( lib - > data , define - > name ,
define - > value , define - > node ,
( void * ) define - > attrs ,
value , ctxt - > state - > node ) ;
} else
ret = - 1 ;
if ( ret < 0 ) {
VALID_ERR2 ( XML_RELAXNG_ERR_TYPECMP ,
define - > name ) ;
return ( - 1 ) ;
} else if ( ret = = 1 ) {
ret = 0 ;
} else {
ret = - 1 ;
}
} else {
xmlChar * nval , * nvalue ;
/*
* TODO : trivial optimizations are possible by
* computing at compile - time
*/
nval = xmlRelaxNGNormalize ( ctxt , define - > value ) ;
nvalue = xmlRelaxNGNormalize ( ctxt , value ) ;
if ( ( nval = = NULL ) | | ( nvalue = = NULL ) | |
( ! xmlStrEqual ( nval , nvalue ) ) )
ret = - 1 ;
if ( nval ! = NULL )
xmlFree ( nval ) ;
if ( nvalue ! = NULL )
xmlFree ( nvalue ) ;
}
}
if ( ret = = 0 )
xmlRelaxNGNextValue ( ctxt ) ;
break ;
}
case XML_RELAXNG_DATATYPE : {
ret = xmlRelaxNGValidateDatatype ( ctxt , value , define ,
ctxt - > state - > seq ) ;
if ( ret = = 0 )
xmlRelaxNGNextValue ( ctxt ) ;
break ;
}
case XML_RELAXNG_CHOICE : {
xmlRelaxNGDefinePtr list = define - > content ;
xmlChar * oldvalue ;
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
oldvalue = ctxt - > state - > value ;
while ( list ! = NULL ) {
ret = xmlRelaxNGValidateValue ( ctxt , list ) ;
if ( ret = = 0 ) {
break ;
}
ctxt - > state - > value = oldvalue ;
list = list - > next ;
}
ctxt - > flags = oldflags ;
if ( ret ! = 0 ) {
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
} else {
if ( ctxt - > errNr > 0 )
xmlRelaxNGPopErrors ( ctxt , 0 ) ;
}
break ;
}
case XML_RELAXNG_LIST : {
xmlRelaxNGDefinePtr list = define - > content ;
xmlChar * oldvalue , * oldend , * val , * cur ;
2003-02-17 17:25:42 +00:00
# ifdef DEBUG_LIST
2003-10-07 11:33:24 +00:00
int nb_values = 0 ;
2003-02-17 17:25:42 +00:00
# endif
2003-01-27 12:35:42 +00:00
2003-10-07 11:33:24 +00:00
oldvalue = ctxt - > state - > value ;
oldend = ctxt - > state - > endvalue ;
val = xmlStrdup ( oldvalue ) ;
if ( val = = NULL ) {
val = xmlStrdup ( BAD_CAST " " ) ;
}
if ( val = = NULL ) {
VALID_ERR ( XML_RELAXNG_ERR_NOSTATE ) ;
return ( - 1 ) ;
}
cur = val ;
while ( * cur ! = 0 ) {
2003-10-18 16:20:14 +00:00
if ( IS_BLANK_CH ( * cur ) ) {
2003-10-07 11:33:24 +00:00
* cur = 0 ;
cur + + ;
2003-02-17 17:25:42 +00:00
# ifdef DEBUG_LIST
2003-10-07 11:33:24 +00:00
nb_values + + ;
2003-02-17 17:25:42 +00:00
# endif
2003-10-18 16:20:14 +00:00
while ( IS_BLANK_CH ( * cur ) )
2003-10-07 11:33:24 +00:00
* cur + + = 0 ;
} else
cur + + ;
}
2003-02-17 17:25:42 +00:00
# ifdef DEBUG_LIST
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" list value: '%s' found %d items \n " ,
oldvalue , nb_values ) ;
nb_values = 0 ;
# endif
ctxt - > state - > endvalue = cur ;
cur = val ;
while ( ( * cur = = 0 ) & & ( cur ! = ctxt - > state - > endvalue ) )
cur + + ;
ctxt - > state - > value = cur ;
while ( list ! = NULL ) {
if ( ctxt - > state - > value = = ctxt - > state - > endvalue )
ctxt - > state - > value = NULL ;
ret = xmlRelaxNGValidateValue ( ctxt , list ) ;
if ( ret ! = 0 ) {
2003-03-16 17:52:32 +00:00
# ifdef DEBUG_LIST
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Failed to validate value: '%s' with %d rule \n " ,
ctxt - > state - > value , nb_values ) ;
2003-03-16 17:52:32 +00:00
# endif
2003-10-07 11:33:24 +00:00
break ;
}
2003-03-16 17:52:32 +00:00
# ifdef DEBUG_LIST
2003-10-07 11:33:24 +00:00
nb_values + + ;
2003-03-16 17:52:32 +00:00
# endif
2003-10-07 11:33:24 +00:00
list = list - > next ;
}
if ( ( ret = = 0 ) & & ( ctxt - > state - > value ! = NULL ) & &
( ctxt - > state - > value ! = ctxt - > state - > endvalue ) ) {
VALID_ERR2 ( XML_RELAXNG_ERR_LISTEXTRA ,
ctxt - > state - > value ) ;
ret = - 1 ;
}
xmlFree ( val ) ;
ctxt - > state - > value = oldvalue ;
ctxt - > state - > endvalue = oldend ;
break ;
}
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_ONEORMORE :
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGValidateValueList ( ctxt , define - > content ) ;
if ( ret ! = 0 ) {
break ;
}
2017-10-21 13:49:31 +02:00
/* Falls through. */
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_ZEROORMORE : {
xmlChar * cur , * temp ;
2011-11-10 18:08:33 +08:00
if ( ( ctxt - > state - > value = = NULL ) | |
( * ctxt - > state - > value = = 0 ) ) {
ret = 0 ;
break ;
}
2003-10-07 11:33:24 +00:00
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
cur = ctxt - > state - > value ;
temp = NULL ;
while ( ( cur ! = NULL ) & & ( cur ! = ctxt - > state - > endvalue ) & &
( temp ! = cur ) ) {
temp = cur ;
ret =
xmlRelaxNGValidateValueList ( ctxt , define - > content ) ;
if ( ret ! = 0 ) {
ctxt - > state - > value = temp ;
ret = 0 ;
break ;
}
cur = ctxt - > state - > value ;
}
ctxt - > flags = oldflags ;
2006-03-09 18:41:40 +00:00
if ( ctxt - > errNr > 0 )
xmlRelaxNGPopErrors ( ctxt , 0 ) ;
2003-10-07 11:33:24 +00:00
break ;
}
2011-11-10 18:08:33 +08:00
case XML_RELAXNG_OPTIONAL : {
xmlChar * temp ;
if ( ( ctxt - > state - > value = = NULL ) | |
( * ctxt - > state - > value = = 0 ) ) {
ret = 0 ;
break ;
}
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
temp = ctxt - > state - > value ;
ret = xmlRelaxNGValidateValue ( ctxt , define - > content ) ;
ctxt - > flags = oldflags ;
if ( ret ! = 0 ) {
ctxt - > state - > value = temp ;
if ( ctxt - > errNr > 0 )
xmlRelaxNGPopErrors ( ctxt , 0 ) ;
ret = 0 ;
break ;
}
if ( ctxt - > errNr > 0 )
xmlRelaxNGPopErrors ( ctxt , 0 ) ;
break ;
}
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_EXCEPT : {
xmlRelaxNGDefinePtr list ;
list = define - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGValidateValue ( ctxt , list ) ;
if ( ret = = 0 ) {
ret = - 1 ;
break ;
} else
ret = 0 ;
list = list - > next ;
}
break ;
}
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_DEF :
2003-10-07 11:33:24 +00:00
case XML_RELAXNG_GROUP : {
xmlRelaxNGDefinePtr list ;
list = define - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGValidateValue ( ctxt , list ) ;
if ( ret ! = 0 ) {
ret = - 1 ;
break ;
} else
ret = 0 ;
list = list - > next ;
}
break ;
}
2003-02-27 21:30:32 +00:00
case XML_RELAXNG_REF :
case XML_RELAXNG_PARENTREF :
2008-06-02 16:04:12 +00:00
if ( define - > content = = NULL ) {
2009-08-14 18:52:10 +02:00
VALID_ERR ( XML_RELAXNG_ERR_NODEFINE ) ;
ret = - 1 ;
} else {
ret = xmlRelaxNGValidateValue ( ctxt , define - > content ) ;
}
2003-10-07 11:33:24 +00:00
break ;
default :
TODO ret = - 1 ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGValidateValueContent :
* @ ctxt : a Relax - NG validation context
* @ defines : the list of definitions to verify
*
* Validate the given definitions for the current value
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateValueContent ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr defines )
{
2003-01-23 18:29:16 +00:00
int ret = 0 ;
while ( defines ! = NULL ) {
2003-10-07 11:33:24 +00:00
ret = xmlRelaxNGValidateValue ( ctxt , defines ) ;
if ( ret ! = 0 )
break ;
defines = defines - > next ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGAttributeMatch :
* @ ctxt : a Relax - NG validation context
* @ define : the definition to check
* @ prop : the attribute
*
* Check if the attribute matches the definition nameClass
*
* Returns 1 if the attribute matches , 0 if no , or - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGAttributeMatch ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define , xmlAttrPtr prop )
{
2003-03-16 17:52:32 +00:00
int ret ;
if ( define - > name ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ! xmlStrEqual ( define - > name , prop - > name ) )
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
}
if ( define - > ns ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( define - > ns [ 0 ] = = 0 ) {
if ( prop - > ns ! = NULL )
return ( 0 ) ;
} else {
if ( ( prop - > ns = = NULL ) | |
( ! xmlStrEqual ( define - > ns , prop - > ns - > href ) ) )
return ( 0 ) ;
}
2003-03-16 17:52:32 +00:00
}
if ( define - > nameClass = = NULL )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-03-16 17:52:32 +00:00
define = define - > nameClass ;
if ( define - > type = = XML_RELAXNG_EXCEPT ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr list ;
list = define - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGAttributeMatch ( ctxt , list , prop ) ;
if ( ret = = 1 )
return ( 0 ) ;
if ( ret < 0 )
return ( ret ) ;
list = list - > next ;
}
2013-10-23 14:51:33 -04:00
} else if ( define - > type = = XML_RELAXNG_CHOICE ) {
xmlRelaxNGDefinePtr list ;
list = define - > nameClass ;
while ( list ! = NULL ) {
ret = xmlRelaxNGAttributeMatch ( ctxt , list , prop ) ;
if ( ret = = 1 )
return ( 1 ) ;
if ( ret < 0 )
return ( ret ) ;
list = list - > next ;
}
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
} else {
2003-10-07 11:33:24 +00:00
TODO }
return ( 1 ) ;
2003-03-16 17:52:32 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGValidateAttribute :
* @ ctxt : a Relax - NG validation context
* @ define : the definition to verify
*
* Validate the given attribute definition for that node
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateAttribute ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define )
{
2003-01-23 18:29:16 +00:00
int ret = 0 , i ;
xmlChar * value , * oldvalue ;
xmlAttrPtr prop = NULL , tmp ;
2003-03-18 00:31:04 +00:00
xmlNodePtr oldseq ;
2003-01-23 18:29:16 +00:00
2003-02-03 10:57:45 +00:00
if ( ctxt - > state - > nbAttrLeft < = 0 )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-01-23 18:29:16 +00:00
if ( define - > name ! = NULL ) {
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < ctxt - > state - > nbAttrs ; i + + ) {
tmp = ctxt - > state - > attrs [ i ] ;
if ( ( tmp ! = NULL ) & & ( xmlStrEqual ( define - > name , tmp - > name ) ) ) {
if ( ( ( ( define - > ns = = NULL ) | | ( define - > ns [ 0 ] = = 0 ) ) & &
( tmp - > ns = = NULL ) ) | |
( ( tmp - > ns ! = NULL ) & &
( xmlStrEqual ( define - > ns , tmp - > ns - > href ) ) ) ) {
prop = tmp ;
break ;
}
}
}
if ( prop ! = NULL ) {
value = xmlNodeListGetString ( prop - > doc , prop - > children , 1 ) ;
oldvalue = ctxt - > state - > value ;
oldseq = ctxt - > state - > seq ;
ctxt - > state - > seq = ( xmlNodePtr ) prop ;
ctxt - > state - > value = value ;
ctxt - > state - > endvalue = NULL ;
ret = xmlRelaxNGValidateValueContent ( ctxt , define - > content ) ;
if ( ctxt - > state - > value ! = NULL )
value = ctxt - > state - > value ;
if ( value ! = NULL )
xmlFree ( value ) ;
ctxt - > state - > value = oldvalue ;
ctxt - > state - > seq = oldseq ;
if ( ret = = 0 ) {
/*
* flag the attribute as processed
*/
ctxt - > state - > attrs [ i ] = NULL ;
ctxt - > state - > nbAttrLeft - - ;
}
} else {
ret = - 1 ;
}
2003-01-23 18:29:16 +00:00
# ifdef DEBUG
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlRelaxNGValidateAttribute(%s): %d \n " ,
define - > name , ret ) ;
2003-02-03 08:52:58 +00:00
# endif
2003-02-03 13:17:57 +00:00
} else {
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < ctxt - > state - > nbAttrs ; i + + ) {
tmp = ctxt - > state - > attrs [ i ] ;
if ( ( tmp ! = NULL ) & &
( xmlRelaxNGAttributeMatch ( ctxt , define , tmp ) = = 1 ) ) {
prop = tmp ;
break ;
}
}
if ( prop ! = NULL ) {
value = xmlNodeListGetString ( prop - > doc , prop - > children , 1 ) ;
oldvalue = ctxt - > state - > value ;
oldseq = ctxt - > state - > seq ;
ctxt - > state - > seq = ( xmlNodePtr ) prop ;
ctxt - > state - > value = value ;
ret = xmlRelaxNGValidateValueContent ( ctxt , define - > content ) ;
if ( ctxt - > state - > value ! = NULL )
value = ctxt - > state - > value ;
if ( value ! = NULL )
xmlFree ( value ) ;
ctxt - > state - > value = oldvalue ;
ctxt - > state - > seq = oldseq ;
if ( ret = = 0 ) {
/*
* flag the attribute as processed
*/
ctxt - > state - > attrs [ i ] = NULL ;
ctxt - > state - > nbAttrLeft - - ;
}
} else {
ret = - 1 ;
}
2003-02-03 08:52:58 +00:00
# ifdef DEBUG
2003-10-07 11:33:24 +00:00
if ( define - > ns ! = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlRelaxNGValidateAttribute(nsName ns = %s): %d \n " ,
define - > ns , ret ) ;
} else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlRelaxNGValidateAttribute(anyName): %d \n " ,
ret ) ;
}
2003-02-03 08:52:58 +00:00
# endif
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-03-15 21:30:25 +00:00
}
2003-03-16 17:52:32 +00:00
/**
* xmlRelaxNGValidateAttributeList :
* @ ctxt : a Relax - NG validation context
* @ define : the list of definition to verify
*
* Validate the given node against the list of attribute definitions
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateAttributeList ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr defines )
{
2003-04-16 15:58:05 +00:00
int ret = 0 , res ;
int needmore = 0 ;
xmlRelaxNGDefinePtr cur ;
cur = defines ;
while ( cur ! = NULL ) {
if ( cur - > type = = XML_RELAXNG_ATTRIBUTE ) {
2003-10-07 11:33:24 +00:00
if ( xmlRelaxNGValidateAttribute ( ctxt , cur ) ! = 0 )
ret = - 1 ;
} else
needmore = 1 ;
2003-04-16 15:58:05 +00:00
cur = cur - > next ;
2003-03-16 17:52:32 +00:00
}
2003-04-16 15:58:05 +00:00
if ( ! needmore )
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-04-16 15:58:05 +00:00
cur = defines ;
while ( cur ! = NULL ) {
if ( cur - > type ! = XML_RELAXNG_ATTRIBUTE ) {
2003-10-07 11:33:24 +00:00
if ( ( ctxt - > state ! = NULL ) | | ( ctxt - > states ! = NULL ) ) {
res = xmlRelaxNGValidateDefinition ( ctxt , cur ) ;
if ( res < 0 )
ret = - 1 ;
} else {
VALID_ERR ( XML_RELAXNG_ERR_NOSTATE ) ;
return ( - 1 ) ;
}
if ( res = = - 1 ) /* continues on -2 */
break ;
}
2003-04-16 15:58:05 +00:00
cur = cur - > next ;
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-03-16 17:52:32 +00:00
}
2003-03-15 21:30:25 +00:00
/**
* xmlRelaxNGNodeMatchesList :
* @ node : the node
* @ list : a NULL terminated array of definitions
*
* Check if a node can be matched by one of the definitions
*
* Returns 1 if matches 0 otherwise
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGNodeMatchesList ( xmlNodePtr node , xmlRelaxNGDefinePtr * list )
{
2003-03-15 21:30:25 +00:00
xmlRelaxNGDefinePtr cur ;
2003-03-21 12:43:18 +00:00
int i = 0 , tmp ;
2003-03-15 21:30:25 +00:00
if ( ( node = = NULL ) | | ( list = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-15 21:30:25 +00:00
cur = list [ i + + ] ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( node - > type = = XML_ELEMENT_NODE ) & &
( cur - > type = = XML_RELAXNG_ELEMENT ) ) {
tmp = xmlRelaxNGElementMatch ( NULL , cur , node ) ;
if ( tmp = = 1 )
return ( 1 ) ;
} else if ( ( ( node - > type = = XML_TEXT_NODE ) | |
( node - > type = = XML_CDATA_SECTION_NODE ) ) & &
2019-01-01 19:58:07 +01:00
( ( cur - > type = = XML_RELAXNG_DATATYPE ) | |
2018-11-22 18:09:51 +01:00
( cur - > type = = XML_RELAXNG_LIST ) | |
2019-01-01 19:58:07 +01:00
( cur - > type = = XML_RELAXNG_TEXT ) | |
2018-11-22 18:09:51 +01:00
( cur - > type = = XML_RELAXNG_VALUE ) ) ) {
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
}
cur = list [ i + + ] ;
2003-03-15 21:30:25 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-03-15 21:30:25 +00:00
}
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGValidateInterleave :
2003-03-15 21:30:25 +00:00
* @ ctxt : a Relax - NG validation context
* @ define : the definition to verify
*
2003-03-16 17:52:32 +00:00
* Validate an interleave definition for a node .
2003-03-15 21:30:25 +00:00
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateInterleave ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define )
{
2003-08-01 15:55:39 +00:00
int ret = 0 , i , nbgroups ;
2003-03-16 17:52:32 +00:00
int errNr = ctxt - > errNr ;
2003-03-19 21:02:29 +00:00
int oldflags ;
2003-03-16 17:52:32 +00:00
xmlRelaxNGValidStatePtr oldstate ;
xmlRelaxNGPartitionPtr partitions ;
xmlRelaxNGInterleaveGroupPtr group = NULL ;
xmlNodePtr cur , start , last = NULL , lastchg = NULL , lastelem ;
xmlNodePtr * list = NULL , * lasts = NULL ;
if ( define - > data ! = NULL ) {
2003-10-07 11:33:24 +00:00
partitions = ( xmlRelaxNGPartitionPtr ) define - > data ;
nbgroups = partitions - > nbgroups ;
2003-03-16 17:52:32 +00:00
} else {
2003-10-07 11:33:24 +00:00
VALID_ERR ( XML_RELAXNG_ERR_INTERNODATA ) ;
return ( - 1 ) ;
2003-03-15 21:30:25 +00:00
}
2003-03-19 21:02:29 +00:00
/*
* Optimizations for MIXED
*/
oldflags = ctxt - > flags ;
2003-03-21 16:53:17 +00:00
if ( define - > dflags & IS_MIXED ) {
2003-10-07 11:33:24 +00:00
ctxt - > flags | = FLAGS_MIXED_CONTENT ;
if ( nbgroups = = 2 ) {
/*
* this is a pure < mixed > case
*/
if ( ctxt - > state ! = NULL )
ctxt - > state - > seq = xmlRelaxNGSkipIgnored ( ctxt ,
ctxt - > state - > seq ) ;
if ( partitions - > groups [ 0 ] - > rule - > type = = XML_RELAXNG_TEXT )
ret = xmlRelaxNGValidateDefinition ( ctxt ,
partitions - > groups [ 1 ] - >
rule ) ;
else
ret = xmlRelaxNGValidateDefinition ( ctxt ,
partitions - > groups [ 0 ] - >
rule ) ;
if ( ret = = 0 ) {
if ( ctxt - > state ! = NULL )
ctxt - > state - > seq = xmlRelaxNGSkipIgnored ( ctxt ,
ctxt - > state - >
seq ) ;
}
ctxt - > flags = oldflags ;
return ( ret ) ;
}
2003-03-19 21:02:29 +00:00
}
2003-03-15 21:30:25 +00:00
2003-03-16 17:52:32 +00:00
/*
* Build arrays to store the first and last node of the chain
* pertaining to each group
*/
list = ( xmlNodePtr * ) xmlMalloc ( nbgroups * sizeof ( xmlNodePtr ) ) ;
if ( list = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
return ( - 1 ) ;
2003-03-15 21:30:25 +00:00
}
2003-03-16 17:52:32 +00:00
memset ( list , 0 , nbgroups * sizeof ( xmlNodePtr ) ) ;
lasts = ( xmlNodePtr * ) xmlMalloc ( nbgroups * sizeof ( xmlNodePtr ) ) ;
if ( lasts = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
return ( - 1 ) ;
2003-03-15 21:30:25 +00:00
}
2003-03-16 17:52:32 +00:00
memset ( lasts , 0 , nbgroups * sizeof ( xmlNodePtr ) ) ;
2003-03-15 21:30:25 +00:00
2003-03-16 17:52:32 +00:00
/*
* Walk the sequence of children finding the right group and
* sorting them in sequences .
*/
cur = ctxt - > state - > seq ;
cur = xmlRelaxNGSkipIgnored ( ctxt , cur ) ;
start = cur ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
ctxt - > state - > seq = cur ;
if ( ( partitions - > triage ! = NULL ) & &
2003-03-21 01:24:45 +00:00
( partitions - > flags & IS_DETERMINIST ) ) {
2003-10-07 11:33:24 +00:00
void * tmp = NULL ;
if ( ( cur - > type = = XML_TEXT_NODE ) | |
( cur - > type = = XML_CDATA_SECTION_NODE ) ) {
tmp = xmlHashLookup2 ( partitions - > triage , BAD_CAST " #text " ,
NULL ) ;
} else if ( cur - > type = = XML_ELEMENT_NODE ) {
if ( cur - > ns ! = NULL ) {
tmp = xmlHashLookup2 ( partitions - > triage , cur - > name ,
cur - > ns - > href ) ;
if ( tmp = = NULL )
tmp = xmlHashLookup2 ( partitions - > triage ,
BAD_CAST " #any " ,
cur - > ns - > href ) ;
} else
tmp =
xmlHashLookup2 ( partitions - > triage , cur - > name ,
NULL ) ;
if ( tmp = = NULL )
tmp =
xmlHashLookup2 ( partitions - > triage , BAD_CAST " #any " ,
NULL ) ;
}
if ( tmp = = NULL ) {
i = nbgroups ;
} else {
2017-10-09 13:37:42 +02:00
i = ( ( ptrdiff_t ) tmp ) - 1 ;
2003-10-07 11:33:24 +00:00
if ( partitions - > flags & IS_NEEDCHECK ) {
group = partitions - > groups [ i ] ;
if ( ! xmlRelaxNGNodeMatchesList ( cur , group - > defs ) )
i = nbgroups ;
}
}
} else {
for ( i = 0 ; i < nbgroups ; i + + ) {
group = partitions - > groups [ i ] ;
if ( group = = NULL )
continue ;
if ( xmlRelaxNGNodeMatchesList ( cur , group - > defs ) )
break ;
}
}
/*
* We break as soon as an element not matched is found
*/
if ( i > = nbgroups ) {
break ;
}
if ( lasts [ i ] ! = NULL ) {
lasts [ i ] - > next = cur ;
lasts [ i ] = cur ;
} else {
list [ i ] = cur ;
lasts [ i ] = cur ;
}
if ( cur - > next ! = NULL )
lastchg = cur - > next ;
else
lastchg = cur ;
cur = xmlRelaxNGSkipIgnored ( ctxt , cur - > next ) ;
2003-03-15 21:30:25 +00:00
}
2003-03-16 17:52:32 +00:00
if ( ret ! = 0 ) {
2003-10-07 11:33:24 +00:00
VALID_ERR ( XML_RELAXNG_ERR_INTERSEQ ) ;
ret = - 1 ;
goto done ;
2003-03-16 17:52:32 +00:00
}
lastelem = cur ;
oldstate = ctxt - > state ;
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < nbgroups ; i + + ) {
ctxt - > state = xmlRelaxNGCopyValidState ( ctxt , oldstate ) ;
2014-07-14 16:01:10 +08:00
if ( ctxt - > state = = NULL ) {
ret = - 1 ;
break ;
}
2003-10-07 11:33:24 +00:00
group = partitions - > groups [ i ] ;
if ( lasts [ i ] ! = NULL ) {
last = lasts [ i ] - > next ;
lasts [ i ] - > next = NULL ;
}
ctxt - > state - > seq = list [ i ] ;
ret = xmlRelaxNGValidateDefinition ( ctxt , group - > rule ) ;
if ( ret ! = 0 )
break ;
if ( ctxt - > state ! = NULL ) {
cur = ctxt - > state - > seq ;
cur = xmlRelaxNGSkipIgnored ( ctxt , cur ) ;
xmlRelaxNGFreeValidState ( ctxt , oldstate ) ;
oldstate = ctxt - > state ;
ctxt - > state = NULL ;
2019-08-08 23:33:48 +02:00
if ( cur ! = NULL
/* there's a nasty violation of context-free unambiguities,
since in open - name - class context , interleave in the
production shall finish without caring about anything
else that is OK to follow in that case - - it would
otherwise get marked as " extra content " and would
hence fail the validation , hence this perhaps
dirty attempt to rectify such a situation */
& & ( define - > parent - > type ! = XML_RELAXNG_DEF
| | ! xmlStrEqual ( define - > parent - > name ,
( const xmlChar * ) " open-name-class " ) ) ) {
2003-10-07 11:33:24 +00:00
VALID_ERR2 ( XML_RELAXNG_ERR_INTEREXTRA , cur - > name ) ;
ret = - 1 ;
ctxt - > state = oldstate ;
goto done ;
}
} else if ( ctxt - > states ! = NULL ) {
int j ;
int found = 0 ;
2006-02-19 15:27:17 +00:00
int best = - 1 ;
int lowattr = - 1 ;
/*
* PBM : what happen if there is attributes checks in the interleaves
*/
2003-10-07 11:33:24 +00:00
for ( j = 0 ; j < ctxt - > states - > nbState ; j + + ) {
cur = ctxt - > states - > tabState [ j ] - > seq ;
cur = xmlRelaxNGSkipIgnored ( ctxt , cur ) ;
if ( cur = = NULL ) {
2006-02-19 15:27:17 +00:00
if ( found = = 0 ) {
lowattr = ctxt - > states - > tabState [ j ] - > nbAttrLeft ;
best = j ;
}
2003-10-07 11:33:24 +00:00
found = 1 ;
2006-02-19 15:27:17 +00:00
if ( ctxt - > states - > tabState [ j ] - > nbAttrLeft < = lowattr ) {
/* try to keep the latest one to mach old heuristic */
lowattr = ctxt - > states - > tabState [ j ] - > nbAttrLeft ;
best = j ;
}
if ( lowattr = = 0 )
break ;
} else if ( found = = 0 ) {
if ( lowattr = = - 1 ) {
lowattr = ctxt - > states - > tabState [ j ] - > nbAttrLeft ;
best = j ;
} else
if ( ctxt - > states - > tabState [ j ] - > nbAttrLeft < = lowattr ) {
/* try to keep the latest one to mach old heuristic */
lowattr = ctxt - > states - > tabState [ j ] - > nbAttrLeft ;
best = j ;
}
}
2003-10-07 11:33:24 +00:00
}
2006-02-19 15:27:17 +00:00
/*
* BIG PBM : here we pick only one restarting point : - (
*/
2003-10-07 11:33:24 +00:00
if ( ctxt - > states - > nbState > 0 ) {
xmlRelaxNGFreeValidState ( ctxt , oldstate ) ;
2006-02-19 15:27:17 +00:00
if ( best ! = - 1 ) {
oldstate = ctxt - > states - > tabState [ best ] ;
ctxt - > states - > tabState [ best ] = NULL ;
} else {
oldstate =
ctxt - > states - > tabState [ ctxt - > states - > nbState - 1 ] ;
ctxt - > states - > tabState [ ctxt - > states - > nbState - 1 ] = NULL ;
2009-08-14 16:16:31 +02:00
ctxt - > states - > nbState - - ;
2006-02-19 15:27:17 +00:00
}
2003-10-07 11:33:24 +00:00
}
2006-02-19 15:27:17 +00:00
for ( j = 0 ; j < ctxt - > states - > nbState ; j + + ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeValidState ( ctxt , ctxt - > states - > tabState [ j ] ) ;
}
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
if ( found = = 0 ) {
2009-09-07 11:19:33 +02:00
if ( cur = = NULL ) {
2010-03-15 10:06:36 +01:00
VALID_ERR2 ( XML_RELAXNG_ERR_INTEREXTRA ,
( const xmlChar * ) " noname " ) ;
2009-09-07 11:19:33 +02:00
} else {
VALID_ERR2 ( XML_RELAXNG_ERR_INTEREXTRA , cur - > name ) ;
}
2003-10-07 11:33:24 +00:00
ret = - 1 ;
ctxt - > state = oldstate ;
goto done ;
}
} else {
ret = - 1 ;
break ;
}
if ( lasts [ i ] ! = NULL ) {
lasts [ i ] - > next = last ;
}
2003-03-16 17:52:32 +00:00
}
if ( ctxt - > state ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
2003-03-16 17:52:32 +00:00
ctxt - > state = oldstate ;
ctxt - > state - > seq = lastelem ;
if ( ret ! = 0 ) {
2003-10-07 11:33:24 +00:00
VALID_ERR ( XML_RELAXNG_ERR_INTERSEQ ) ;
ret = - 1 ;
goto done ;
2003-03-16 17:52:32 +00:00
}
2003-03-15 21:30:25 +00:00
2003-10-07 11:33:24 +00:00
done :
2003-03-19 21:02:29 +00:00
ctxt - > flags = oldflags ;
2003-03-16 17:52:32 +00:00
/*
* builds the next links chain from the prev one
*/
cur = lastchg ;
while ( cur ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( cur = = start ) | | ( cur - > prev = = NULL ) )
break ;
cur - > prev - > next = cur ;
cur = cur - > prev ;
2003-01-23 18:29:16 +00:00
}
2003-03-16 17:52:32 +00:00
if ( ret = = 0 ) {
2003-10-07 11:33:24 +00:00
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
2003-03-15 21:30:25 +00:00
}
2003-01-23 18:29:16 +00:00
2003-03-16 17:52:32 +00:00
xmlFree ( list ) ;
xmlFree ( lasts ) ;
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-03-15 21:30:25 +00:00
}
2003-01-28 20:58:15 +00:00
2003-03-15 21:30:25 +00:00
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGValidateDefinitionList :
2003-03-15 21:30:25 +00:00
* @ ctxt : a Relax - NG validation context
2003-03-16 17:52:32 +00:00
* @ define : the list of definition to verify
2003-03-15 21:30:25 +00:00
*
2003-03-16 17:52:32 +00:00
* Validate the given node content against the ( list ) of definitions
2003-03-15 21:30:25 +00:00
*
2003-03-16 17:52:32 +00:00
* Returns 0 if the validation succeeded or an error code .
2003-03-15 21:30:25 +00:00
*/
2003-03-16 17:52:32 +00:00
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateDefinitionList ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr defines )
{
2003-03-16 17:52:32 +00:00
int ret = 0 , res ;
2003-01-28 20:58:15 +00:00
2003-03-17 15:37:12 +00:00
if ( defines = = NULL ) {
2003-10-07 11:33:24 +00:00
VALID_ERR2 ( XML_RELAXNG_ERR_INTERNAL ,
BAD_CAST " NULL definition list " ) ;
return ( - 1 ) ;
2003-03-17 15:37:12 +00:00
}
2003-03-16 17:52:32 +00:00
while ( defines ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ( ctxt - > state ! = NULL ) | | ( ctxt - > states ! = NULL ) ) {
res = xmlRelaxNGValidateDefinition ( ctxt , defines ) ;
if ( res < 0 )
ret = - 1 ;
} else {
VALID_ERR ( XML_RELAXNG_ERR_NOSTATE ) ;
return ( - 1 ) ;
}
if ( res = = - 1 ) /* continues on -2 */
break ;
defines = defines - > next ;
2003-03-16 17:52:32 +00:00
}
2003-01-28 20:58:15 +00:00
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-03-15 21:30:25 +00:00
}
2003-02-24 11:47:13 +00:00
2003-03-15 21:30:25 +00:00
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGElementMatch :
2003-03-15 21:30:25 +00:00
* @ ctxt : a Relax - NG validation context
2003-03-16 17:52:32 +00:00
* @ define : the definition to check
* @ elem : the element
2003-03-15 21:30:25 +00:00
*
2003-03-16 17:52:32 +00:00
* Check if the element matches the definition nameClass
2003-03-15 21:30:25 +00:00
*
2003-03-16 17:52:32 +00:00
* Returns 1 if the element matches , 0 if no , or - 1 in case of error
2003-03-15 21:30:25 +00:00
*/
2003-03-16 17:52:32 +00:00
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGElementMatch ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define , xmlNodePtr elem )
{
2003-03-21 21:22:48 +00:00
int ret = 0 , oldflags = 0 ;
2003-01-28 20:58:15 +00:00
2003-03-16 17:52:32 +00:00
if ( define - > name ! = NULL ) {
2003-10-07 11:33:24 +00:00
if ( ! xmlStrEqual ( elem - > name , define - > name ) ) {
VALID_ERR3 ( XML_RELAXNG_ERR_ELEMNAME , define - > name , elem - > name ) ;
return ( 0 ) ;
}
2003-03-16 17:52:32 +00:00
}
if ( ( define - > ns ! = NULL ) & & ( define - > ns [ 0 ] ! = 0 ) ) {
2003-10-07 11:33:24 +00:00
if ( elem - > ns = = NULL ) {
VALID_ERR2 ( XML_RELAXNG_ERR_ELEMNONS , elem - > name ) ;
return ( 0 ) ;
} else if ( ! xmlStrEqual ( elem - > ns - > href , define - > ns ) ) {
VALID_ERR3 ( XML_RELAXNG_ERR_ELEMWRONGNS ,
elem - > name , define - > ns ) ;
return ( 0 ) ;
}
2003-03-16 17:52:32 +00:00
} else if ( ( elem - > ns ! = NULL ) & & ( define - > ns ! = NULL ) & &
2003-10-07 11:33:24 +00:00
( define - > name = = NULL ) ) {
VALID_ERR2 ( XML_RELAXNG_ERR_ELEMEXTRANS , elem - > name ) ;
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
} else if ( ( elem - > ns ! = NULL ) & & ( define - > name ! = NULL ) ) {
2003-10-07 11:33:24 +00:00
VALID_ERR2 ( XML_RELAXNG_ERR_ELEMEXTRANS , define - > name ) ;
return ( 0 ) ;
2003-03-16 17:52:32 +00:00
}
2003-01-28 20:58:15 +00:00
2003-03-16 17:52:32 +00:00
if ( define - > nameClass = = NULL )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
2003-01-23 18:29:16 +00:00
2003-03-16 17:52:32 +00:00
define = define - > nameClass ;
if ( define - > type = = XML_RELAXNG_EXCEPT ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr list ;
if ( ctxt ! = NULL ) {
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
}
list = define - > content ;
while ( list ! = NULL ) {
ret = xmlRelaxNGElementMatch ( ctxt , list , elem ) ;
if ( ret = = 1 ) {
if ( ctxt ! = NULL )
ctxt - > flags = oldflags ;
return ( 0 ) ;
}
if ( ret < 0 ) {
if ( ctxt ! = NULL )
ctxt - > flags = oldflags ;
return ( ret ) ;
}
list = list - > next ;
}
ret = 1 ;
if ( ctxt ! = NULL ) {
ctxt - > flags = oldflags ;
}
2003-03-16 17:52:32 +00:00
} else if ( define - > type = = XML_RELAXNG_CHOICE ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGDefinePtr list ;
if ( ctxt ! = NULL ) {
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
}
list = define - > nameClass ;
while ( list ! = NULL ) {
ret = xmlRelaxNGElementMatch ( ctxt , list , elem ) ;
if ( ret = = 1 ) {
if ( ctxt ! = NULL )
ctxt - > flags = oldflags ;
return ( 1 ) ;
}
if ( ret < 0 ) {
if ( ctxt ! = NULL )
ctxt - > flags = oldflags ;
return ( ret ) ;
}
list = list - > next ;
}
if ( ctxt ! = NULL ) {
if ( ret ! = 0 ) {
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
} else {
if ( ctxt - > errNr > 0 )
xmlRelaxNGPopErrors ( ctxt , 0 ) ;
}
}
ret = 0 ;
if ( ctxt ! = NULL ) {
ctxt - > flags = oldflags ;
}
2003-03-15 21:30:25 +00:00
} else {
2003-10-07 11:33:24 +00:00
TODO ret = - 1 ;
2003-01-23 18:29:16 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
2003-03-16 17:52:32 +00:00
2003-08-27 14:15:15 +00:00
/**
* xmlRelaxNGBestState :
* @ ctxt : a Relax - NG validation context
*
* Find the " best " state in the ctxt - > states list of states to report
* errors about . I . e . a state with no element left in the child list
* or the one with the less attributes left .
2019-09-30 17:04:54 +02:00
* This is called only if a validation error was detected
2003-08-27 14:15:15 +00:00
*
* Returns the index of the " best " state or - 1 in case of error
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGBestState ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-08-27 14:15:15 +00:00
xmlRelaxNGValidStatePtr state ;
int i , tmp ;
int best = - 1 ;
int value = 1000000 ;
if ( ( ctxt = = NULL ) | | ( ctxt - > states = = NULL ) | |
( ctxt - > states - > nbState < = 0 ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-08-27 14:15:15 +00:00
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
2003-08-27 14:15:15 +00:00
state = ctxt - > states - > tabState [ i ] ;
2003-10-07 11:33:24 +00:00
if ( state = = NULL )
continue ;
if ( state - > seq ! = NULL ) {
if ( ( best = = - 1 ) | | ( value > 100000 ) ) {
value = 100000 ;
best = i ;
}
} else {
tmp = state - > nbAttrLeft ;
if ( ( best = = - 1 ) | | ( value > tmp ) ) {
value = tmp ;
best = i ;
}
}
2003-08-27 14:15:15 +00:00
}
2003-10-07 11:33:24 +00:00
return ( best ) ;
2003-08-27 14:15:15 +00:00
}
/**
* xmlRelaxNGLogBestError :
* @ ctxt : a Relax - NG validation context
*
* Find the " best " state in the ctxt - > states list of states to report
* errors about and log it .
*/
static void
2003-10-07 11:33:24 +00:00
xmlRelaxNGLogBestError ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-08-27 14:15:15 +00:00
int best ;
if ( ( ctxt = = NULL ) | | ( ctxt - > states = = NULL ) | |
( ctxt - > states - > nbState < = 0 ) )
2003-10-07 11:33:24 +00:00
return ;
2003-08-27 14:15:15 +00:00
best = xmlRelaxNGBestState ( ctxt ) ;
if ( ( best > = 0 ) & & ( best < ctxt - > states - > nbState ) ) {
2003-10-07 11:33:24 +00:00
ctxt - > state = ctxt - > states - > tabState [ best ] ;
2003-08-27 14:15:15 +00:00
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateElementEnd ( ctxt , 1 ) ;
2003-08-27 14:15:15 +00:00
}
}
2003-02-17 17:25:42 +00:00
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGValidateElementEnd :
2003-02-17 17:25:42 +00:00
* @ ctxt : a Relax - NG validation context
2003-11-14 16:20:34 +00:00
* @ dolog : indicate that error logging should be done
2003-02-17 17:25:42 +00:00
*
2003-03-16 17:52:32 +00:00
* Validate the end of the element , implements check that
* there is nothing left not consumed in the element content
* or in the attribute list .
2003-02-17 17:25:42 +00:00
*
2003-03-16 17:52:32 +00:00
* Returns 0 if the validation succeeded or an error code .
2003-02-17 17:25:42 +00:00
*/
2003-03-16 17:52:32 +00:00
static int
2003-11-14 16:20:34 +00:00
xmlRelaxNGValidateElementEnd ( xmlRelaxNGValidCtxtPtr ctxt , int dolog )
2003-10-07 11:33:24 +00:00
{
2003-08-27 14:15:15 +00:00
int i ;
2003-03-16 17:52:32 +00:00
xmlRelaxNGValidStatePtr state ;
2003-02-17 17:25:42 +00:00
2003-03-16 17:52:32 +00:00
state = ctxt - > state ;
if ( state - > seq ! = NULL ) {
2003-10-07 11:33:24 +00:00
state - > seq = xmlRelaxNGSkipIgnored ( ctxt , state - > seq ) ;
if ( state - > seq ! = NULL ) {
2003-11-14 16:20:34 +00:00
if ( dolog ) {
2003-10-07 11:33:24 +00:00
VALID_ERR3 ( XML_RELAXNG_ERR_EXTRACONTENT ,
state - > node - > name , state - > seq - > name ) ;
}
return ( - 1 ) ;
}
2003-03-16 17:52:32 +00:00
}
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < state - > nbAttrs ; i + + ) {
if ( state - > attrs [ i ] ! = NULL ) {
2003-11-14 16:20:34 +00:00
if ( dolog ) {
2003-10-07 11:33:24 +00:00
VALID_ERR3 ( XML_RELAXNG_ERR_INVALIDATTR ,
state - > attrs [ i ] - > name , state - > node - > name ) ;
}
return ( - 1 - i ) ;
}
2003-02-17 17:25:42 +00:00
}
2003-10-07 11:33:24 +00:00
return ( 0 ) ;
2003-02-17 17:25:42 +00:00
}
2003-01-23 18:29:16 +00:00
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGValidateState :
2003-01-23 18:29:16 +00:00
* @ ctxt : a Relax - NG validation context
* @ define : the definition to verify
*
2003-03-16 17:52:32 +00:00
* Validate the current state against the definition
2003-01-23 18:29:16 +00:00
*
2003-03-16 17:52:32 +00:00
* Returns 0 if the validation succeeded or an error code .
2003-01-23 18:29:16 +00:00
*/
2003-03-16 17:52:32 +00:00
static int
2003-04-14 16:11:26 +00:00
xmlRelaxNGValidateState ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define )
{
2003-03-16 17:52:32 +00:00
xmlNodePtr node ;
int ret = 0 , i , tmp , oldflags , errNr ;
2003-03-21 01:24:45 +00:00
xmlRelaxNGValidStatePtr oldstate = NULL , state ;
2003-03-15 21:30:25 +00:00
2003-03-16 17:52:32 +00:00
if ( define = = NULL ) {
2003-04-14 16:11:26 +00:00
VALID_ERR ( XML_RELAXNG_ERR_NODEFINE ) ;
return ( - 1 ) ;
2003-03-16 17:52:32 +00:00
}
if ( ctxt - > state ! = NULL ) {
2003-04-14 16:11:26 +00:00
node = ctxt - > state - > seq ;
2003-03-16 17:52:32 +00:00
} else {
2003-04-14 16:11:26 +00:00
node = NULL ;
2003-03-16 17:52:32 +00:00
}
2003-02-09 14:22:17 +00:00
# ifdef DEBUG
2003-04-14 16:11:26 +00:00
for ( i = 0 ; i < ctxt - > depth ; i + + )
xmlGenericError ( xmlGenericErrorContext , " " ) ;
2003-03-16 17:52:32 +00:00
xmlGenericError ( xmlGenericErrorContext ,
2003-04-14 16:11:26 +00:00
" Start validating %s " , xmlRelaxNGDefName ( define ) ) ;
2003-03-16 17:52:32 +00:00
if ( define - > name ! = NULL )
2003-04-14 16:11:26 +00:00
xmlGenericError ( xmlGenericErrorContext , " %s " , define - > name ) ;
2003-03-16 17:52:32 +00:00
if ( ( node ! = NULL ) & & ( node - > name ! = NULL ) )
2003-04-14 16:11:26 +00:00
xmlGenericError ( xmlGenericErrorContext , " on %s \n " , node - > name ) ;
2003-03-16 17:52:32 +00:00
else
2003-04-14 16:11:26 +00:00
xmlGenericError ( xmlGenericErrorContext , " \n " ) ;
2003-02-09 14:22:17 +00:00
# endif
2003-03-16 17:52:32 +00:00
ctxt - > depth + + ;
2003-01-23 18:29:16 +00:00
switch ( define - > type ) {
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_EMPTY :
2003-04-14 16:11:26 +00:00
ret = 0 ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_NOT_ALLOWED :
2003-04-14 16:11:26 +00:00
ret = - 1 ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_TEXT :
2003-04-14 16:11:26 +00:00
while ( ( node ! = NULL ) & &
( ( node - > type = = XML_TEXT_NODE ) | |
( node - > type = = XML_COMMENT_NODE ) | |
( node - > type = = XML_PI_NODE ) | |
( node - > type = = XML_CDATA_SECTION_NODE ) ) )
node = node - > next ;
ctxt - > state - > seq = node ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_ELEMENT :
2003-04-14 16:11:26 +00:00
errNr = ctxt - > errNr ;
node = xmlRelaxNGSkipIgnored ( ctxt , node ) ;
if ( node = = NULL ) {
VALID_ERR2 ( XML_RELAXNG_ERR_NOELEM , define - > name ) ;
ret = - 1 ;
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
break ;
}
if ( node - > type ! = XML_ELEMENT_NODE ) {
VALID_ERR ( XML_RELAXNG_ERR_NOTELEM ) ;
ret = - 1 ;
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
break ;
}
/*
* This node was already validated successfully against
* this definition .
*/
2004-02-22 22:13:27 +00:00
if ( node - > psvi = = define ) {
2003-04-14 16:11:26 +00:00
ctxt - > state - > seq = xmlRelaxNGSkipIgnored ( ctxt , node - > next ) ;
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
if ( ctxt - > errNr ! = 0 ) {
while ( ( ctxt - > err ! = NULL ) & &
( ( ( ctxt - > err - > err = = XML_RELAXNG_ERR_ELEMNAME )
& & ( xmlStrEqual ( ctxt - > err - > arg2 , node - > name ) ) )
| |
( ( ctxt - > err - > err = =
XML_RELAXNG_ERR_ELEMEXTRANS )
& & ( xmlStrEqual ( ctxt - > err - > arg1 , node - > name ) ) )
| | ( ctxt - > err - > err = = XML_RELAXNG_ERR_NOELEM )
| | ( ctxt - > err - > err = =
XML_RELAXNG_ERR_NOTELEM ) ) )
xmlRelaxNGValidErrorPop ( ctxt ) ;
}
break ;
}
ret = xmlRelaxNGElementMatch ( ctxt , define , node ) ;
if ( ret < = 0 ) {
ret = - 1 ;
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
break ;
}
ret = 0 ;
if ( ctxt - > errNr ! = 0 ) {
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
while ( ( ctxt - > err ! = NULL ) & &
( ( ( ctxt - > err - > err = = XML_RELAXNG_ERR_ELEMNAME ) & &
( xmlStrEqual ( ctxt - > err - > arg2 , node - > name ) ) ) | |
( ( ctxt - > err - > err = = XML_RELAXNG_ERR_ELEMEXTRANS ) & &
( xmlStrEqual ( ctxt - > err - > arg1 , node - > name ) ) ) | |
( ctxt - > err - > err = = XML_RELAXNG_ERR_NOELEM ) | |
( ctxt - > err - > err = = XML_RELAXNG_ERR_NOTELEM ) ) )
xmlRelaxNGValidErrorPop ( ctxt ) ;
}
errNr = ctxt - > errNr ;
oldflags = ctxt - > flags ;
if ( ctxt - > flags & FLAGS_MIXED_CONTENT ) {
ctxt - > flags - = FLAGS_MIXED_CONTENT ;
}
state = xmlRelaxNGNewValidState ( ctxt , node ) ;
if ( state = = NULL ) {
ret = - 1 ;
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
break ;
}
oldstate = ctxt - > state ;
ctxt - > state = state ;
if ( define - > attrs ! = NULL ) {
tmp = xmlRelaxNGValidateAttributeList ( ctxt , define - > attrs ) ;
if ( tmp ! = 0 ) {
ret = - 1 ;
VALID_ERR2 ( XML_RELAXNG_ERR_ATTRVALID , node - > name ) ;
}
}
if ( define - > contModel ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidStatePtr nstate , tmpstate = ctxt - > state ;
xmlRelaxNGStatesPtr tmpstates = ctxt - > states ;
xmlNodePtr nseq ;
2003-04-16 15:58:05 +00:00
2003-10-07 11:33:24 +00:00
nstate = xmlRelaxNGNewValidState ( ctxt , node ) ;
ctxt - > state = nstate ;
ctxt - > states = NULL ;
2003-04-16 15:58:05 +00:00
2003-04-14 16:11:26 +00:00
tmp = xmlRelaxNGValidateCompiledContent ( ctxt ,
define - > contModel ,
ctxt - > state - > seq ) ;
2003-10-07 11:33:24 +00:00
nseq = ctxt - > state - > seq ;
ctxt - > state = tmpstate ;
ctxt - > states = tmpstates ;
xmlRelaxNGFreeValidState ( ctxt , nstate ) ;
2003-04-16 15:58:05 +00:00
2003-04-14 16:11:26 +00:00
# ifdef DEBUG_COMPILE
2003-10-07 11:33:24 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" Validating content of '%s' : %d \n " ,
define - > name , tmp ) ;
2003-04-14 16:11:26 +00:00
# endif
2003-04-16 15:58:05 +00:00
if ( tmp ! = 0 )
2003-10-07 11:33:24 +00:00
ret = - 1 ;
2003-04-16 15:58:05 +00:00
if ( ctxt - > states ! = NULL ) {
tmp = - 1 ;
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
state = ctxt - > states - > tabState [ i ] ;
ctxt - > state = state ;
2003-10-07 11:33:24 +00:00
ctxt - > state - > seq = nseq ;
2003-04-16 15:58:05 +00:00
2003-08-27 14:15:15 +00:00
if ( xmlRelaxNGValidateElementEnd ( ctxt , 0 ) = = 0 ) {
2003-04-16 15:58:05 +00:00
tmp = 0 ;
2003-10-07 11:33:24 +00:00
break ;
}
}
if ( tmp ! = 0 ) {
/*
* validation error , log the message for the " best " one
*/
ctxt - > flags | = FLAGS_IGNORABLE ;
xmlRelaxNGLogBestError ( ctxt ) ;
2003-08-27 14:15:15 +00:00
}
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
xmlRelaxNGFreeValidState ( ctxt ,
2003-10-07 11:33:24 +00:00
ctxt - > states - >
tabState [ i ] ) ;
2003-04-16 15:58:05 +00:00
}
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > flags = oldflags ;
ctxt - > states = NULL ;
if ( ( ret = = 0 ) & & ( tmp = = - 1 ) )
ret = - 1 ;
} else {
state = ctxt - > state ;
2007-06-12 09:24:46 +00:00
if ( ctxt - > state ! = NULL )
ctxt - > state - > seq = nseq ;
2003-04-16 15:58:05 +00:00
if ( ret = = 0 )
2003-08-27 14:15:15 +00:00
ret = xmlRelaxNGValidateElementEnd ( ctxt , 1 ) ;
2003-04-16 15:58:05 +00:00
xmlRelaxNGFreeValidState ( ctxt , state ) ;
}
2003-04-14 16:11:26 +00:00
} else {
if ( define - > content ! = NULL ) {
tmp = xmlRelaxNGValidateDefinitionList ( ctxt ,
2003-10-07 11:33:24 +00:00
define - >
content ) ;
2003-04-14 16:11:26 +00:00
if ( tmp ! = 0 ) {
ret = - 1 ;
if ( ctxt - > state = = NULL ) {
ctxt - > state = oldstate ;
VALID_ERR2 ( XML_RELAXNG_ERR_CONTENTVALID ,
node - > name ) ;
ctxt - > state = NULL ;
} else {
VALID_ERR2 ( XML_RELAXNG_ERR_CONTENTVALID ,
node - > name ) ;
}
}
}
if ( ctxt - > states ! = NULL ) {
tmp = - 1 ;
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
state = ctxt - > states - > tabState [ i ] ;
ctxt - > state = state ;
2003-08-27 14:15:15 +00:00
if ( xmlRelaxNGValidateElementEnd ( ctxt , 0 ) = = 0 ) {
2003-04-14 16:11:26 +00:00
tmp = 0 ;
2003-10-07 11:33:24 +00:00
break ;
}
}
if ( tmp ! = 0 ) {
/*
* validation error , log the message for the " best " one
*/
ctxt - > flags | = FLAGS_IGNORABLE ;
xmlRelaxNGLogBestError ( ctxt ) ;
2003-08-27 14:15:15 +00:00
}
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
xmlRelaxNGFreeValidState ( ctxt ,
2009-08-14 16:16:31 +02:00
ctxt - > states - > tabState [ i ] ) ;
ctxt - > states - > tabState [ i ] = NULL ;
2003-04-14 16:11:26 +00:00
}
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > flags = oldflags ;
ctxt - > states = NULL ;
if ( ( ret = = 0 ) & & ( tmp = = - 1 ) )
ret = - 1 ;
} else {
state = ctxt - > state ;
if ( ret = = 0 )
2003-08-27 14:15:15 +00:00
ret = xmlRelaxNGValidateElementEnd ( ctxt , 1 ) ;
2003-04-14 16:11:26 +00:00
xmlRelaxNGFreeValidState ( ctxt , state ) ;
}
}
if ( ret = = 0 ) {
2004-02-22 22:13:27 +00:00
node - > psvi = define ;
2003-04-14 16:11:26 +00:00
}
ctxt - > flags = oldflags ;
ctxt - > state = oldstate ;
if ( oldstate ! = NULL )
oldstate - > seq = xmlRelaxNGSkipIgnored ( ctxt , node - > next ) ;
if ( ret ! = 0 ) {
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 ) {
xmlRelaxNGDumpValidError ( ctxt ) ;
ret = 0 ;
2006-10-13 16:30:56 +00:00
#if 0
2003-04-14 16:11:26 +00:00
} else {
ret = - 2 ;
2006-10-13 16:30:56 +00:00
# endif
2003-04-14 16:11:26 +00:00
}
} else {
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
}
2003-03-16 17:52:32 +00:00
# ifdef DEBUG
2003-04-14 16:11:26 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlRelaxNGValidateDefinition(): validated %s : %d " ,
node - > name , ret ) ;
if ( oldstate = = NULL )
xmlGenericError ( xmlGenericErrorContext , " : no state \n " ) ;
else if ( oldstate - > seq = = NULL )
xmlGenericError ( xmlGenericErrorContext , " : done \n " ) ;
else if ( oldstate - > seq - > type = = XML_ELEMENT_NODE )
xmlGenericError ( xmlGenericErrorContext , " : next elem %s \n " ,
oldstate - > seq - > name ) ;
else
xmlGenericError ( xmlGenericErrorContext , " : next %s %d \n " ,
oldstate - > seq - > name , oldstate - > seq - > type ) ;
2003-03-16 17:52:32 +00:00
# endif
2003-04-14 16:11:26 +00:00
break ;
case XML_RELAXNG_OPTIONAL : {
errNr = ctxt - > errNr ;
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
oldstate = xmlRelaxNGCopyValidState ( ctxt , ctxt - > state ) ;
ret =
xmlRelaxNGValidateDefinitionList ( ctxt ,
define - > content ) ;
if ( ret ! = 0 ) {
if ( ctxt - > state ! = NULL )
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = oldstate ;
ctxt - > flags = oldflags ;
ret = 0 ;
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
break ;
}
if ( ctxt - > states ! = NULL ) {
xmlRelaxNGAddStates ( ctxt , ctxt - > states , oldstate ) ;
} else {
ctxt - > states = xmlRelaxNGNewStates ( ctxt , 1 ) ;
if ( ctxt - > states = = NULL ) {
xmlRelaxNGFreeValidState ( ctxt , oldstate ) ;
ctxt - > flags = oldflags ;
ret = - 1 ;
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
break ;
}
xmlRelaxNGAddStates ( ctxt , ctxt - > states , oldstate ) ;
xmlRelaxNGAddStates ( ctxt , ctxt - > states , ctxt - > state ) ;
ctxt - > state = NULL ;
}
ctxt - > flags = oldflags ;
ret = 0 ;
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
break ;
}
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_ONEORMORE :
2003-04-14 16:11:26 +00:00
errNr = ctxt - > errNr ;
ret = xmlRelaxNGValidateDefinitionList ( ctxt , define - > content ) ;
if ( ret ! = 0 ) {
break ;
}
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
2017-10-21 13:49:31 +02:00
/* Falls through. */
2003-04-14 16:11:26 +00:00
case XML_RELAXNG_ZEROORMORE : {
int progress ;
xmlRelaxNGStatesPtr states = NULL , res = NULL ;
int base , j ;
errNr = ctxt - > errNr ;
res = xmlRelaxNGNewStates ( ctxt , 1 ) ;
if ( res = = NULL ) {
ret = - 1 ;
break ;
}
/*
* All the input states are also exit states
*/
if ( ctxt - > state ! = NULL ) {
xmlRelaxNGAddStates ( ctxt , res ,
xmlRelaxNGCopyValidState ( ctxt ,
ctxt - >
state ) ) ;
} else {
for ( j = 0 ; j < ctxt - > states - > nbState ; j + + ) {
xmlRelaxNGAddStates ( ctxt , res ,
2009-08-14 16:16:31 +02:00
xmlRelaxNGCopyValidState ( ctxt ,
ctxt - > states - > tabState [ j ] ) ) ;
2003-04-14 16:11:26 +00:00
}
}
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
do {
progress = 0 ;
base = res - > nbState ;
if ( ctxt - > states ! = NULL ) {
states = ctxt - > states ;
for ( i = 0 ; i < states - > nbState ; i + + ) {
ctxt - > state = states - > tabState [ i ] ;
ctxt - > states = NULL ;
ret = xmlRelaxNGValidateDefinitionList ( ctxt ,
define - >
content ) ;
if ( ret = = 0 ) {
if ( ctxt - > state ! = NULL ) {
tmp = xmlRelaxNGAddStates ( ctxt , res ,
ctxt - > state ) ;
ctxt - > state = NULL ;
if ( tmp = = 1 )
progress = 1 ;
} else if ( ctxt - > states ! = NULL ) {
for ( j = 0 ; j < ctxt - > states - > nbState ;
j + + ) {
tmp =
xmlRelaxNGAddStates ( ctxt , res ,
2009-08-14 16:16:31 +02:00
ctxt - > states - > tabState [ j ] ) ;
2003-04-14 16:11:26 +00:00
if ( tmp = = 1 )
progress = 1 ;
}
xmlRelaxNGFreeStates ( ctxt ,
ctxt - > states ) ;
ctxt - > states = NULL ;
}
} else {
if ( ctxt - > state ! = NULL ) {
xmlRelaxNGFreeValidState ( ctxt ,
ctxt - > state ) ;
ctxt - > state = NULL ;
}
}
}
} else {
ret = xmlRelaxNGValidateDefinitionList ( ctxt ,
define - >
content ) ;
if ( ret ! = 0 ) {
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = NULL ;
} else {
base = res - > nbState ;
if ( ctxt - > state ! = NULL ) {
tmp = xmlRelaxNGAddStates ( ctxt , res ,
ctxt - > state ) ;
ctxt - > state = NULL ;
if ( tmp = = 1 )
progress = 1 ;
} else if ( ctxt - > states ! = NULL ) {
for ( j = 0 ; j < ctxt - > states - > nbState ; j + + ) {
tmp = xmlRelaxNGAddStates ( ctxt , res ,
2009-08-14 16:16:31 +02:00
ctxt - > states - > tabState [ j ] ) ;
2003-04-14 16:11:26 +00:00
if ( tmp = = 1 )
progress = 1 ;
}
if ( states = = NULL ) {
states = ctxt - > states ;
} else {
xmlRelaxNGFreeStates ( ctxt ,
ctxt - > states ) ;
}
ctxt - > states = NULL ;
}
}
}
if ( progress ) {
/*
* Collect all the new nodes added at that step
* and make them the new node set
*/
if ( res - > nbState - base = = 1 ) {
ctxt - > state = xmlRelaxNGCopyValidState ( ctxt ,
res - >
tabState
[ base ] ) ;
} else {
if ( states = = NULL ) {
xmlRelaxNGNewStates ( ctxt ,
res - > nbState - base ) ;
2006-03-09 18:41:40 +00:00
states = ctxt - > states ;
if ( states = = NULL ) {
progress = 0 ;
break ;
}
2003-04-14 16:11:26 +00:00
}
states - > nbState = 0 ;
for ( i = base ; i < res - > nbState ; i + + )
xmlRelaxNGAddStates ( ctxt , states ,
xmlRelaxNGCopyValidState
2009-08-14 16:16:31 +02:00
( ctxt , res - > tabState [ i ] ) ) ;
2003-04-14 16:11:26 +00:00
ctxt - > states = states ;
}
}
} while ( progress = = 1 ) ;
if ( states ! = NULL ) {
xmlRelaxNGFreeStates ( ctxt , states ) ;
}
ctxt - > states = res ;
ctxt - > flags = oldflags ;
2003-08-26 13:56:48 +00:00
#if 0
/*
2003-10-07 11:33:24 +00:00
* errors may have to be propagated back . . .
*/
2003-04-14 16:11:26 +00:00
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
2003-08-26 13:56:48 +00:00
# endif
2003-04-14 16:11:26 +00:00
ret = 0 ;
break ;
}
case XML_RELAXNG_CHOICE : {
xmlRelaxNGDefinePtr list = NULL ;
xmlRelaxNGStatesPtr states = NULL ;
node = xmlRelaxNGSkipIgnored ( ctxt , node ) ;
errNr = ctxt - > errNr ;
2005-01-15 12:38:10 +00:00
if ( ( define - > dflags & IS_TRIABLE ) & & ( define - > data ! = NULL ) & &
( node ! = NULL ) ) {
/*
* node = = NULL can ' t be optimized since IS_TRIABLE
* doesn ' t account for choice which may lead to
* only attributes .
*/
2003-04-14 16:11:26 +00:00
xmlHashTablePtr triage =
( xmlHashTablePtr ) define - > data ;
/*
* Something we can optimize cleanly there is only one
2019-09-30 17:04:54 +02:00
* possible branch out !
2003-04-14 16:11:26 +00:00
*/
if ( ( node - > type = = XML_TEXT_NODE ) | |
( node - > type = = XML_CDATA_SECTION_NODE ) ) {
list =
xmlHashLookup2 ( triage , BAD_CAST " #text " , NULL ) ;
} else if ( node - > type = = XML_ELEMENT_NODE ) {
if ( node - > ns ! = NULL ) {
list = xmlHashLookup2 ( triage , node - > name ,
node - > ns - > href ) ;
if ( list = = NULL )
list =
xmlHashLookup2 ( triage , BAD_CAST " #any " ,
node - > ns - > href ) ;
} else
list =
xmlHashLookup2 ( triage , node - > name , NULL ) ;
if ( list = = NULL )
list =
xmlHashLookup2 ( triage , BAD_CAST " #any " ,
NULL ) ;
}
if ( list = = NULL ) {
ret = - 1 ;
2004-03-21 11:21:14 +00:00
VALID_ERR2 ( XML_RELAXNG_ERR_ELEMWRONG , node - > name ) ;
2003-04-14 16:11:26 +00:00
break ;
}
ret = xmlRelaxNGValidateDefinition ( ctxt , list ) ;
if ( ret = = 0 ) {
}
break ;
}
list = define - > content ;
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
while ( list ! = NULL ) {
oldstate = xmlRelaxNGCopyValidState ( ctxt , ctxt - > state ) ;
ret = xmlRelaxNGValidateDefinition ( ctxt , list ) ;
if ( ret = = 0 ) {
if ( states = = NULL ) {
states = xmlRelaxNGNewStates ( ctxt , 1 ) ;
}
if ( ctxt - > state ! = NULL ) {
xmlRelaxNGAddStates ( ctxt , states , ctxt - > state ) ;
} else if ( ctxt - > states ! = NULL ) {
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
xmlRelaxNGAddStates ( ctxt , states ,
ctxt - > states - >
tabState [ i ] ) ;
}
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
}
} else {
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
}
ctxt - > state = oldstate ;
list = list - > next ;
}
if ( states ! = NULL ) {
xmlRelaxNGFreeValidState ( ctxt , oldstate ) ;
ctxt - > states = states ;
ctxt - > state = NULL ;
ret = 0 ;
} else {
ctxt - > states = NULL ;
}
ctxt - > flags = oldflags ;
if ( ret ! = 0 ) {
if ( ( ctxt - > flags & FLAGS_IGNORABLE ) = = 0 ) {
xmlRelaxNGDumpValidError ( ctxt ) ;
}
} else {
if ( ctxt - > errNr > errNr )
xmlRelaxNGPopErrors ( ctxt , errNr ) ;
}
break ;
}
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_DEF :
case XML_RELAXNG_GROUP :
2003-04-14 16:11:26 +00:00
ret = xmlRelaxNGValidateDefinitionList ( ctxt , define - > content ) ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_INTERLEAVE :
2003-04-14 16:11:26 +00:00
ret = xmlRelaxNGValidateInterleave ( ctxt , define ) ;
break ;
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_ATTRIBUTE :
2003-04-14 16:11:26 +00:00
ret = xmlRelaxNGValidateAttribute ( ctxt , define ) ;
break ;
2003-04-15 23:32:22 +00:00
case XML_RELAXNG_START :
2003-04-14 16:11:26 +00:00
case XML_RELAXNG_NOOP :
2003-03-16 17:52:32 +00:00
case XML_RELAXNG_REF :
2003-04-14 16:11:26 +00:00
case XML_RELAXNG_EXTERNALREF :
2003-03-17 15:37:12 +00:00
case XML_RELAXNG_PARENTREF :
2003-04-14 16:11:26 +00:00
ret = xmlRelaxNGValidateDefinition ( ctxt , define - > content ) ;
break ;
case XML_RELAXNG_DATATYPE : {
xmlNodePtr child ;
xmlChar * content = NULL ;
child = node ;
while ( child ! = NULL ) {
if ( child - > type = = XML_ELEMENT_NODE ) {
VALID_ERR2 ( XML_RELAXNG_ERR_DATAELEM ,
node - > parent - > name ) ;
ret = - 1 ;
break ;
} else if ( ( child - > type = = XML_TEXT_NODE ) | |
( child - > type = = XML_CDATA_SECTION_NODE ) ) {
content = xmlStrcat ( content , child - > content ) ;
}
/* TODO: handle entities ... */
child = child - > next ;
}
if ( ret = = - 1 ) {
if ( content ! = NULL )
xmlFree ( content ) ;
break ;
}
if ( content = = NULL ) {
content = xmlStrdup ( BAD_CAST " " ) ;
if ( content = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
2003-04-14 16:11:26 +00:00
ret = - 1 ;
break ;
}
}
ret = xmlRelaxNGValidateDatatype ( ctxt , content , define ,
ctxt - > state - > seq ) ;
if ( ret = = - 1 ) {
VALID_ERR2 ( XML_RELAXNG_ERR_DATATYPE , define - > name ) ;
} else if ( ret = = 0 ) {
ctxt - > state - > seq = NULL ;
}
if ( content ! = NULL )
xmlFree ( content ) ;
break ;
}
case XML_RELAXNG_VALUE : {
xmlChar * content = NULL ;
xmlChar * oldvalue ;
xmlNodePtr child ;
child = node ;
while ( child ! = NULL ) {
if ( child - > type = = XML_ELEMENT_NODE ) {
VALID_ERR2 ( XML_RELAXNG_ERR_VALELEM ,
node - > parent - > name ) ;
ret = - 1 ;
break ;
} else if ( ( child - > type = = XML_TEXT_NODE ) | |
( child - > type = = XML_CDATA_SECTION_NODE ) ) {
content = xmlStrcat ( content , child - > content ) ;
}
/* TODO: handle entities ... */
child = child - > next ;
}
if ( ret = = - 1 ) {
if ( content ! = NULL )
xmlFree ( content ) ;
break ;
}
if ( content = = NULL ) {
content = xmlStrdup ( BAD_CAST " " ) ;
if ( content = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
2003-04-14 16:11:26 +00:00
ret = - 1 ;
break ;
}
}
oldvalue = ctxt - > state - > value ;
ctxt - > state - > value = content ;
ret = xmlRelaxNGValidateValue ( ctxt , define ) ;
ctxt - > state - > value = oldvalue ;
if ( ret = = - 1 ) {
VALID_ERR2 ( XML_RELAXNG_ERR_VALUE , define - > name ) ;
} else if ( ret = = 0 ) {
ctxt - > state - > seq = NULL ;
}
if ( content ! = NULL )
xmlFree ( content ) ;
break ;
}
case XML_RELAXNG_LIST : {
xmlChar * content ;
xmlNodePtr child ;
xmlChar * oldvalue , * oldendvalue ;
int len ;
/*
* Make sure it ' s only text nodes
*/
content = NULL ;
child = node ;
while ( child ! = NULL ) {
if ( child - > type = = XML_ELEMENT_NODE ) {
VALID_ERR2 ( XML_RELAXNG_ERR_LISTELEM ,
node - > parent - > name ) ;
ret = - 1 ;
break ;
} else if ( ( child - > type = = XML_TEXT_NODE ) | |
( child - > type = = XML_CDATA_SECTION_NODE ) ) {
content = xmlStrcat ( content , child - > content ) ;
}
/* TODO: handle entities ... */
child = child - > next ;
}
if ( ret = = - 1 ) {
if ( content ! = NULL )
xmlFree ( content ) ;
break ;
}
if ( content = = NULL ) {
content = xmlStrdup ( BAD_CAST " " ) ;
if ( content = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( ctxt , " validating \n " ) ;
2003-04-14 16:11:26 +00:00
ret = - 1 ;
break ;
}
}
len = xmlStrlen ( content ) ;
oldvalue = ctxt - > state - > value ;
oldendvalue = ctxt - > state - > endvalue ;
ctxt - > state - > value = content ;
ctxt - > state - > endvalue = content + len ;
ret = xmlRelaxNGValidateValue ( ctxt , define ) ;
ctxt - > state - > value = oldvalue ;
ctxt - > state - > endvalue = oldendvalue ;
if ( ret = = - 1 ) {
VALID_ERR ( XML_RELAXNG_ERR_LIST ) ;
} else if ( ( ret = = 0 ) & & ( node ! = NULL ) ) {
ctxt - > state - > seq = node - > next ;
}
if ( content ! = NULL )
xmlFree ( content ) ;
break ;
}
case XML_RELAXNG_EXCEPT :
case XML_RELAXNG_PARAM :
TODO ret = - 1 ;
break ;
2003-03-15 21:30:25 +00:00
}
2003-03-16 17:52:32 +00:00
ctxt - > depth - - ;
2003-03-15 21:30:25 +00:00
# ifdef DEBUG
2003-04-14 16:11:26 +00:00
for ( i = 0 ; i < ctxt - > depth ; i + + )
xmlGenericError ( xmlGenericErrorContext , " " ) ;
2003-03-16 17:52:32 +00:00
xmlGenericError ( xmlGenericErrorContext ,
2003-04-14 16:11:26 +00:00
" Validating %s " , xmlRelaxNGDefName ( define ) ) ;
2003-03-16 17:52:32 +00:00
if ( define - > name ! = NULL )
2003-04-14 16:11:26 +00:00
xmlGenericError ( xmlGenericErrorContext , " %s " , define - > name ) ;
2003-03-16 17:52:32 +00:00
if ( ret = = 0 )
2019-09-30 17:04:54 +02:00
xmlGenericError ( xmlGenericErrorContext , " succeeded \n " ) ;
2003-03-16 17:52:32 +00:00
else
2003-04-14 16:11:26 +00:00
xmlGenericError ( xmlGenericErrorContext , " failed \n " ) ;
2003-03-15 21:30:25 +00:00
# endif
2003-04-14 16:11:26 +00:00
return ( ret ) ;
2003-03-15 21:30:25 +00:00
}
/**
2003-03-16 17:52:32 +00:00
* xmlRelaxNGValidateDefinition :
2003-03-15 21:30:25 +00:00
* @ ctxt : a Relax - NG validation context
* @ define : the definition to verify
*
2003-03-16 17:52:32 +00:00
* Validate the current node lists against the definition
2003-03-15 21:30:25 +00:00
*
2003-03-16 17:52:32 +00:00
* Returns 0 if the validation succeeded or an error code .
2003-03-15 21:30:25 +00:00
*/
2003-03-16 17:52:32 +00:00
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateDefinition ( xmlRelaxNGValidCtxtPtr ctxt ,
xmlRelaxNGDefinePtr define )
{
2003-03-16 17:52:32 +00:00
xmlRelaxNGStatesPtr states , res ;
int i , j , k , ret , oldflags ;
2003-03-15 21:30:25 +00:00
2003-03-16 17:52:32 +00:00
/*
* We should NOT have both ctxt - > state and ctxt - > states
*/
if ( ( ctxt - > state ! = NULL ) & & ( ctxt - > states ! = NULL ) ) {
2003-10-07 11:33:24 +00:00
TODO xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = NULL ;
2003-03-15 21:30:25 +00:00
}
2003-03-16 17:52:32 +00:00
if ( ( ctxt - > states = = NULL ) | | ( ctxt - > states - > nbState = = 1 ) ) {
2003-10-07 11:33:24 +00:00
if ( ctxt - > states ! = NULL ) {
ctxt - > state = ctxt - > states - > tabState [ 0 ] ;
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
}
ret = xmlRelaxNGValidateState ( ctxt , define ) ;
if ( ( ctxt - > state ! = NULL ) & & ( ctxt - > states ! = NULL ) ) {
TODO xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = NULL ;
}
if ( ( ctxt - > states ! = NULL ) & & ( ctxt - > states - > nbState = = 1 ) ) {
ctxt - > state = ctxt - > states - > tabState [ 0 ] ;
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
}
return ( ret ) ;
2003-03-16 17:52:32 +00:00
}
states = ctxt - > states ;
ctxt - > states = NULL ;
res = NULL ;
j = 0 ;
oldflags = ctxt - > flags ;
ctxt - > flags | = FLAGS_IGNORABLE ;
2003-10-07 11:33:24 +00:00
for ( i = 0 ; i < states - > nbState ; i + + ) {
ctxt - > state = states - > tabState [ i ] ;
ctxt - > states = NULL ;
ret = xmlRelaxNGValidateState ( ctxt , define ) ;
/*
* We should NOT have both ctxt - > state and ctxt - > states
*/
if ( ( ctxt - > state ! = NULL ) & & ( ctxt - > states ! = NULL ) ) {
TODO xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = NULL ;
}
if ( ret = = 0 ) {
if ( ctxt - > states = = NULL ) {
if ( res ! = NULL ) {
/* add the state to the container */
xmlRelaxNGAddStates ( ctxt , res , ctxt - > state ) ;
ctxt - > state = NULL ;
} else {
/* add the state directly in states */
states - > tabState [ j + + ] = ctxt - > state ;
ctxt - > state = NULL ;
}
} else {
if ( res = = NULL ) {
/* make it the new container and copy other results */
res = ctxt - > states ;
ctxt - > states = NULL ;
for ( k = 0 ; k < j ; k + + )
xmlRelaxNGAddStates ( ctxt , res ,
states - > tabState [ k ] ) ;
} else {
/* add all the new results to res and reff the container */
for ( k = 0 ; k < ctxt - > states - > nbState ; k + + )
xmlRelaxNGAddStates ( ctxt , res ,
ctxt - > states - > tabState [ k ] ) ;
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
}
}
} else {
if ( ctxt - > state ! = NULL ) {
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = NULL ;
} else if ( ctxt - > states ! = NULL ) {
for ( k = 0 ; k < ctxt - > states - > nbState ; k + + )
xmlRelaxNGFreeValidState ( ctxt ,
ctxt - > states - > tabState [ k ] ) ;
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
}
}
2003-01-23 18:29:16 +00:00
}
2003-03-16 17:52:32 +00:00
ctxt - > flags = oldflags ;
if ( res ! = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeStates ( ctxt , states ) ;
ctxt - > states = res ;
ret = 0 ;
2003-03-16 17:52:32 +00:00
} else if ( j > 1 ) {
2003-10-07 11:33:24 +00:00
states - > nbState = j ;
ctxt - > states = states ;
ret = 0 ;
2003-03-16 17:52:32 +00:00
} else if ( j = = 1 ) {
2003-10-07 11:33:24 +00:00
ctxt - > state = states - > tabState [ 0 ] ;
xmlRelaxNGFreeStates ( ctxt , states ) ;
ret = 0 ;
2003-03-16 17:52:32 +00:00
} else {
2003-10-07 11:33:24 +00:00
ret = - 1 ;
xmlRelaxNGFreeStates ( ctxt , states ) ;
if ( ctxt - > states ! = NULL ) {
xmlRelaxNGFreeStates ( ctxt , ctxt - > states ) ;
ctxt - > states = NULL ;
}
2003-03-16 17:52:32 +00:00
}
if ( ( ctxt - > state ! = NULL ) & & ( ctxt - > states ! = NULL ) ) {
2003-10-07 11:33:24 +00:00
TODO xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
ctxt - > state = NULL ;
2003-03-15 21:30:25 +00:00
}
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
/**
* xmlRelaxNGValidateDocument :
* @ ctxt : a Relax - NG validation context
* @ doc : the document
*
* Validate the given document
*
* Returns 0 if the validation succeeded or an error code .
*/
static int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateDocument ( xmlRelaxNGValidCtxtPtr ctxt , xmlDocPtr doc )
{
2003-01-23 18:29:16 +00:00
int ret ;
xmlRelaxNGPtr schema ;
xmlRelaxNGGrammarPtr grammar ;
xmlRelaxNGValidStatePtr state ;
2003-03-16 17:52:32 +00:00
xmlNodePtr node ;
2003-01-23 18:29:16 +00:00
if ( ( ctxt = = NULL ) | | ( ctxt - > schema = = NULL ) | | ( doc = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-01-23 18:29:16 +00:00
2003-03-31 16:09:37 +00:00
ctxt - > errNo = XML_RELAXNG_OK ;
2003-01-23 18:29:16 +00:00
schema = ctxt - > schema ;
grammar = schema - > topgrammar ;
if ( grammar = = NULL ) {
2003-10-07 11:33:24 +00:00
VALID_ERR ( XML_RELAXNG_ERR_NOGRAMMAR ) ;
return ( - 1 ) ;
2003-01-23 18:29:16 +00:00
}
state = xmlRelaxNGNewValidState ( ctxt , NULL ) ;
ctxt - > state = state ;
ret = xmlRelaxNGValidateDefinition ( ctxt , grammar - > start ) ;
2003-03-16 17:52:32 +00:00
if ( ( ctxt - > state ! = NULL ) & & ( state - > seq ! = NULL ) ) {
2003-10-07 11:33:24 +00:00
state = ctxt - > state ;
node = state - > seq ;
node = xmlRelaxNGSkipIgnored ( ctxt , node ) ;
if ( node ! = NULL ) {
if ( ret ! = - 1 ) {
VALID_ERR ( XML_RELAXNG_ERR_EXTRADATA ) ;
ret = - 1 ;
}
}
2003-03-16 17:52:32 +00:00
} else if ( ctxt - > states ! = NULL ) {
2003-10-07 11:33:24 +00:00
int i ;
int tmp = - 1 ;
for ( i = 0 ; i < ctxt - > states - > nbState ; i + + ) {
state = ctxt - > states - > tabState [ i ] ;
node = state - > seq ;
node = xmlRelaxNGSkipIgnored ( ctxt , node ) ;
if ( node = = NULL )
tmp = 0 ;
xmlRelaxNGFreeValidState ( ctxt , state ) ;
}
if ( tmp = = - 1 ) {
if ( ret ! = - 1 ) {
VALID_ERR ( XML_RELAXNG_ERR_EXTRADATA ) ;
ret = - 1 ;
}
}
2003-01-23 18:29:16 +00:00
}
2003-03-21 01:24:45 +00:00
if ( ctxt - > state ! = NULL ) {
xmlRelaxNGFreeValidState ( ctxt , ctxt - > state ) ;
2003-10-07 11:33:24 +00:00
ctxt - > state = NULL ;
2003-03-21 01:24:45 +00:00
}
2003-10-07 11:33:24 +00:00
if ( ret ! = 0 )
xmlRelaxNGDumpValidError ( ctxt ) ;
2003-03-21 21:22:48 +00:00
# ifdef DEBUG
else if ( ctxt - > errNr ! = 0 ) {
2003-10-07 11:33:24 +00:00
ctxt - > error ( ctxt - > userData ,
" %d Extra error messages left on stack ! \n " ,
ctxt - > errNr ) ;
xmlRelaxNGDumpValidError ( ctxt ) ;
2003-03-21 21:22:48 +00:00
}
# endif
2004-02-25 11:52:31 +00:00
# ifdef LIBXML_VALID_ENABLED
2003-03-18 00:31:04 +00:00
if ( ctxt - > idref = = 1 ) {
2003-10-07 11:33:24 +00:00
xmlValidCtxt vctxt ;
2003-03-18 00:31:04 +00:00
2003-10-07 11:33:24 +00:00
memset ( & vctxt , 0 , sizeof ( xmlValidCtxt ) ) ;
vctxt . valid = 1 ;
vctxt . error = ctxt - > error ;
vctxt . warning = ctxt - > warning ;
vctxt . userData = ctxt - > userData ;
2003-03-18 00:31:04 +00:00
2003-10-07 11:33:24 +00:00
if ( xmlValidateDocumentFinal ( & vctxt , doc ) ! = 1 )
ret = - 1 ;
2003-03-18 00:31:04 +00:00
}
2004-02-25 11:52:31 +00:00
# endif /* LIBXML_VALID_ENABLED */
2003-03-31 16:09:37 +00:00
if ( ( ret = = 0 ) & & ( ctxt - > errNo ! = XML_RELAXNG_OK ) )
2003-10-07 11:33:24 +00:00
ret = - 1 ;
2003-01-23 18:29:16 +00:00
2003-10-07 11:33:24 +00:00
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
2009-08-21 17:34:17 +02:00
/**
* xmlRelaxNGCleanPSVI :
* @ node : an input element or document
*
* Call this routine to speed up XPath computation on static documents .
* This stamps all the element nodes with the document order
* Like for line information , the order is kept in the element - > content
* field , the value stored is actually - the node number ( starting at - 1 )
* to be able to differentiate from line numbers .
*
* Returns the number of elements found in the document or - 1 in case
* of error .
*/
static void
xmlRelaxNGCleanPSVI ( xmlNodePtr node ) {
xmlNodePtr cur ;
if ( ( node = = NULL ) | |
( ( node - > type ! = XML_ELEMENT_NODE ) & &
( node - > type ! = XML_DOCUMENT_NODE ) & &
( node - > type ! = XML_HTML_DOCUMENT_NODE ) ) )
return ;
if ( node - > type = = XML_ELEMENT_NODE )
node - > psvi = NULL ;
cur = node - > children ;
while ( cur ! = NULL ) {
if ( cur - > type = = XML_ELEMENT_NODE ) {
cur - > psvi = NULL ;
if ( cur - > children ! = NULL ) {
cur = cur - > children ;
continue ;
}
}
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
continue ;
}
do {
cur = cur - > parent ;
if ( cur = = NULL )
break ;
if ( cur = = node ) {
cur = NULL ;
break ;
}
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
break ;
}
} while ( cur ! = NULL ) ;
}
return ;
}
2003-03-16 17:52:32 +00:00
/************************************************************************
2012-09-11 13:26:36 +08:00
* *
* Validation interfaces *
* *
2003-03-16 17:52:32 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-07 11:33:24 +00:00
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGNewValidCtxt :
* @ schema : a precompiled XML RelaxNGs
*
* Create an XML RelaxNGs validation context based on the given schema
*
* Returns the validation context or NULL in case of error
*/
xmlRelaxNGValidCtxtPtr
2003-10-07 11:33:24 +00:00
xmlRelaxNGNewValidCtxt ( xmlRelaxNGPtr schema )
{
2003-01-23 18:29:16 +00:00
xmlRelaxNGValidCtxtPtr ret ;
ret = ( xmlRelaxNGValidCtxtPtr ) xmlMalloc ( sizeof ( xmlRelaxNGValidCtxt ) ) ;
if ( ret = = NULL ) {
2003-10-07 11:33:24 +00:00
xmlRngVErrMemory ( NULL , " building context \n " ) ;
2003-01-23 18:29:16 +00:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlRelaxNGValidCtxt ) ) ;
ret - > schema = schema ;
2003-02-10 14:28:44 +00:00
ret - > error = xmlGenericError ;
ret - > userData = xmlGenericErrorContext ;
2003-03-07 18:32:59 +00:00
ret - > errNr = 0 ;
ret - > errMax = 0 ;
ret - > err = NULL ;
ret - > errTab = NULL ;
2005-09-04 13:50:03 +00:00
if ( schema ! = NULL )
ret - > idref = schema - > idref ;
2003-03-19 10:36:09 +00:00
ret - > states = NULL ;
ret - > freeState = NULL ;
ret - > freeStates = NULL ;
2003-03-31 16:09:37 +00:00
ret - > errNo = XML_RELAXNG_OK ;
2003-01-23 18:29:16 +00:00
return ( ret ) ;
}
/**
* xmlRelaxNGFreeValidCtxt :
* @ ctxt : the schema validation context
*
* Free the resources associated to the schema validation context
*/
void
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeValidCtxt ( xmlRelaxNGValidCtxtPtr ctxt )
{
2003-03-19 10:36:09 +00:00
int k ;
2003-01-23 18:29:16 +00:00
if ( ctxt = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-03-16 17:52:32 +00:00
if ( ctxt - > states ! = NULL )
2003-10-07 11:33:24 +00:00
xmlRelaxNGFreeStates ( NULL , ctxt - > states ) ;
2003-03-19 10:36:09 +00:00
if ( ctxt - > freeState ! = NULL ) {
2003-10-07 11:33:24 +00:00
for ( k = 0 ; k < ctxt - > freeState - > nbState ; k + + ) {
xmlRelaxNGFreeValidState ( NULL , ctxt - > freeState - > tabState [ k ] ) ;
}
xmlRelaxNGFreeStates ( NULL , ctxt - > freeState ) ;
2003-03-19 10:36:09 +00:00
}
if ( ctxt - > freeStates ! = NULL ) {
2003-10-07 11:33:24 +00:00
for ( k = 0 ; k < ctxt - > freeStatesNr ; k + + ) {
xmlRelaxNGFreeStates ( NULL , ctxt - > freeStates [ k ] ) ;
}
xmlFree ( ctxt - > freeStates ) ;
2003-03-19 10:36:09 +00:00
}
2003-03-07 18:32:59 +00:00
if ( ctxt - > errTab ! = NULL )
2003-10-07 11:33:24 +00:00
xmlFree ( ctxt - > errTab ) ;
2003-04-15 23:32:22 +00:00
if ( ctxt - > elemTab ! = NULL ) {
xmlRegExecCtxtPtr exec ;
2003-10-07 11:33:24 +00:00
exec = xmlRelaxNGElemPop ( ctxt ) ;
while ( exec ! = NULL ) {
xmlRegFreeExecCtxt ( exec ) ;
exec = xmlRelaxNGElemPop ( ctxt ) ;
}
xmlFree ( ctxt - > elemTab ) ;
2003-04-15 23:32:22 +00:00
}
2003-01-23 18:29:16 +00:00
xmlFree ( ctxt ) ;
}
/**
* xmlRelaxNGSetValidErrors :
* @ ctxt : a Relax - NG validation context
* @ err : the error function
* @ warn : the warning function
* @ ctx : the functions context
*
2020-03-08 17:19:42 +01:00
* Set the error and warning callback information
2003-01-23 18:29:16 +00:00
*/
void
xmlRelaxNGSetValidErrors ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidityErrorFunc err ,
xmlRelaxNGValidityWarningFunc warn , void * ctx )
{
2003-01-23 18:29:16 +00:00
if ( ctxt = = NULL )
2003-10-07 11:33:24 +00:00
return ;
2003-01-23 18:29:16 +00:00
ctxt - > error = err ;
ctxt - > warning = warn ;
ctxt - > userData = ctx ;
2005-09-04 13:50:03 +00:00
ctxt - > serror = NULL ;
2003-01-23 18:29:16 +00:00
}
2005-07-13 23:07:49 +00:00
/**
* xmlRelaxNGSetValidStructuredErrors :
* @ ctxt : a Relax - NG validation context
* @ serror : the structured error function
* @ ctx : the functions context
*
* Set the structured error callback
*/
void
xmlRelaxNGSetValidStructuredErrors ( xmlRelaxNGValidCtxtPtr ctxt ,
2005-09-04 13:50:03 +00:00
xmlStructuredErrorFunc serror , void * ctx )
2005-07-13 23:07:49 +00:00
{
if ( ctxt = = NULL )
return ;
2005-09-04 13:50:03 +00:00
ctxt - > serror = serror ;
2005-07-13 23:07:49 +00:00
ctxt - > error = NULL ;
ctxt - > warning = NULL ;
ctxt - > userData = ctx ;
}
2003-07-18 15:16:57 +00:00
/**
* xmlRelaxNGGetValidErrors :
* @ ctxt : a Relax - NG validation context
* @ err : the error function result
* @ warn : the warning function result
* @ ctx : the functions context result
*
2020-03-08 17:19:42 +01:00
* Get the error and warning callback information
2003-07-18 15:16:57 +00:00
*
* Returns - 1 in case of error and 0 otherwise
*/
int
xmlRelaxNGGetValidErrors ( xmlRelaxNGValidCtxtPtr ctxt ,
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidityErrorFunc * err ,
xmlRelaxNGValidityWarningFunc * warn , void * * ctx )
{
2003-07-18 15:16:57 +00:00
if ( ctxt = = NULL )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
if ( err ! = NULL )
* err = ctxt - > error ;
if ( warn ! = NULL )
* warn = ctxt - > warning ;
if ( ctx ! = NULL )
* ctx = ctxt - > userData ;
return ( 0 ) ;
2003-07-18 15:16:57 +00:00
}
2003-01-23 18:29:16 +00:00
/**
* xmlRelaxNGValidateDoc :
* @ ctxt : a Relax - NG validation context
* @ doc : a parsed document tree
*
* Validate a document tree in memory .
*
* Returns 0 if the document is valid , a positive error code
* number otherwise and - 1 in case of internal or API error .
*/
int
2003-10-07 11:33:24 +00:00
xmlRelaxNGValidateDoc ( xmlRelaxNGValidCtxtPtr ctxt , xmlDocPtr doc )
{
2003-01-23 18:29:16 +00:00
int ret ;
if ( ( ctxt = = NULL ) | | ( doc = = NULL ) )
2003-10-07 11:33:24 +00:00
return ( - 1 ) ;
2003-01-23 18:29:16 +00:00
ctxt - > doc = doc ;
ret = xmlRelaxNGValidateDocument ( ctxt , doc ) ;
2009-08-21 17:34:17 +02:00
/*
* Remove all left PSVI
*/
xmlRelaxNGCleanPSVI ( ( xmlNodePtr ) doc ) ;
2003-02-05 13:19:53 +00:00
/*
* TODO : build error codes
*/
if ( ret = = - 1 )
2003-10-07 11:33:24 +00:00
return ( 1 ) ;
return ( ret ) ;
2003-01-23 18:29:16 +00:00
}
# endif /* LIBXML_SCHEMAS_ENABLED */