2001-02-23 20:55:21 +03:00
/*
* valid . c : part of the code use to do the DTD handling and the validity
* checking
*
* See Copyright for the status of this software .
*
2001-06-24 16:13:24 +04:00
* daniel @ veillard . com
2001-02-23 20:55:21 +03:00
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# include <string.h>
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
# include <libxml/xmlmemory.h>
# include <libxml/hash.h>
2004-08-16 04:39:03 +04:00
# include <libxml/uri.h>
2001-02-23 20:55:21 +03:00
# include <libxml/valid.h>
# include <libxml/parser.h>
# include <libxml/parserInternals.h>
# include <libxml/xmlerror.h>
# include <libxml/list.h>
2001-10-17 19:58:35 +04:00
# include <libxml/globals.h>
2001-02-23 20:55:21 +03:00
2003-09-28 22:58:27 +04:00
static xmlElementPtr xmlGetDtdElementDesc2 ( xmlDtdPtr dtd , const xmlChar * name ,
int create ) ;
2001-05-15 12:53:16 +04:00
/* #define DEBUG_VALID_ALGO */
2002-09-18 20:29:02 +04:00
/* #define DEBUG_REGEXP_ALGO */
2001-05-15 12:53:16 +04:00
2002-09-18 01:50:03 +04:00
# define TODO \
xmlGenericError ( xmlGenericErrorContext , \
" Unimplemented block at %s:%d \n " , \
__FILE__ , __LINE__ ) ;
2001-02-23 20:55:21 +03:00
2003-10-03 02:28:19 +04:00
/************************************************************************
* *
* Error handling routines *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
2003-10-06 01:33:18 +04:00
* xmlVErrMemory :
2003-10-03 02:28:19 +04:00
* @ ctxt : an XML validation parser context
* @ extra : extra informations
*
* Handle an out of memory error
*/
static void
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( xmlValidCtxtPtr ctxt , const char * extra )
2003-10-03 02:28:19 +04:00
{
2003-10-04 02:21:51 +04:00
xmlGenericErrorFunc channel = NULL ;
xmlParserCtxtPtr pctxt = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
channel = ctxt - > error ;
data = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
/* Use the special values to detect if it is part of a parsing
context */
if ( ( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_0 ) | |
( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_1 ) ) {
2006-08-22 18:45:40 +04:00
long delta = ( char * ) ctxt - ( char * ) ctxt - > userData ;
if ( ( delta > 0 ) & & ( delta < 250 ) )
pctxt = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
}
2003-10-04 02:21:51 +04:00
}
2003-10-03 02:28:19 +04:00
if ( extra )
2003-10-11 15:26:42 +04:00
__xmlRaiseError ( NULL , channel , data ,
2003-10-28 18:44:17 +03:00
pctxt , NULL , XML_FROM_VALID , XML_ERR_NO_MEMORY ,
2003-10-04 02:21:51 +04:00
XML_ERR_FATAL , NULL , 0 , extra , NULL , NULL , 0 , 0 ,
" Memory allocation failed : %s \n " , extra ) ;
2003-10-03 02:28:19 +04:00
else
2003-10-11 15:26:42 +04:00
__xmlRaiseError ( NULL , channel , data ,
2003-10-28 18:44:17 +03:00
pctxt , NULL , XML_FROM_VALID , XML_ERR_NO_MEMORY ,
2003-10-04 02:21:51 +04:00
XML_ERR_FATAL , NULL , 0 , NULL , NULL , NULL , 0 , 0 ,
" Memory allocation failed \n " ) ;
2003-10-03 02:28:19 +04:00
}
/**
* xmlErrValid :
* @ ctxt : an XML validation parser context
2003-10-04 02:21:51 +04:00
* @ error : the error number
2003-10-03 02:28:19 +04:00
* @ extra : extra informations
*
* Handle a validation error
*/
static void
2003-12-08 13:25:02 +03:00
xmlErrValid ( xmlValidCtxtPtr ctxt , xmlParserErrors error ,
2003-10-04 02:21:51 +04:00
const char * msg , const char * extra )
2003-10-03 02:28:19 +04:00
{
2003-10-04 02:21:51 +04:00
xmlGenericErrorFunc channel = NULL ;
xmlParserCtxtPtr pctxt = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
channel = ctxt - > error ;
data = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
/* Use the special values to detect if it is part of a parsing
context */
if ( ( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_0 ) | |
( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_1 ) ) {
2006-08-22 18:45:40 +04:00
long delta = ( char * ) ctxt - ( char * ) ctxt - > userData ;
if ( ( delta > 0 ) & & ( delta < 250 ) )
pctxt = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
}
2003-10-04 02:21:51 +04:00
}
2003-10-03 02:28:19 +04:00
if ( extra )
2003-10-11 15:26:42 +04:00
__xmlRaiseError ( NULL , channel , data ,
2003-10-28 18:44:17 +03:00
pctxt , NULL , XML_FROM_VALID , error ,
2003-10-04 02:21:51 +04:00
XML_ERR_ERROR , NULL , 0 , extra , NULL , NULL , 0 , 0 ,
msg , extra ) ;
2003-10-03 02:28:19 +04:00
else
2003-10-11 15:26:42 +04:00
__xmlRaiseError ( NULL , channel , data ,
2003-10-28 18:44:17 +03:00
pctxt , NULL , XML_FROM_VALID , error ,
2003-10-04 02:21:51 +04:00
XML_ERR_ERROR , NULL , 0 , NULL , NULL , NULL , 0 , 0 ,
msg ) ;
}
2004-02-25 14:52:31 +03:00
# if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2003-10-04 02:21:51 +04:00
/**
2004-02-25 14:52:31 +03:00
* xmlErrValidNode :
2003-10-04 02:21:51 +04:00
* @ ctxt : an XML validation parser context
* @ node : the node raising the error
* @ error : the error number
* @ str1 : extra informations
2004-02-25 14:52:31 +03:00
* @ str2 : extra informations
2003-10-04 02:21:51 +04:00
* @ str3 : extra informations
*
* Handle a validation error , provide contextual informations
*/
static void
2004-02-25 14:52:31 +03:00
xmlErrValidNode ( xmlValidCtxtPtr ctxt ,
2003-10-04 02:21:51 +04:00
xmlNodePtr node , xmlParserErrors error ,
const char * msg , const xmlChar * str1 ,
2004-02-25 14:52:31 +03:00
const xmlChar * str2 , const xmlChar * str3 )
2003-10-04 02:21:51 +04:00
{
2003-10-10 18:10:40 +04:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-04 02:21:51 +04:00
xmlGenericErrorFunc channel = NULL ;
xmlParserCtxtPtr pctxt = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
channel = ctxt - > error ;
data = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
/* Use the special values to detect if it is part of a parsing
context */
if ( ( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_0 ) | |
( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_1 ) ) {
2006-08-22 18:45:40 +04:00
long delta = ( char * ) ctxt - ( char * ) ctxt - > userData ;
if ( ( delta > 0 ) & & ( delta < 250 ) )
pctxt = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
}
2003-10-04 02:21:51 +04:00
}
2003-10-28 18:44:17 +03:00
__xmlRaiseError ( schannel , channel , data , pctxt , node , XML_FROM_VALID , error ,
2003-10-04 02:21:51 +04:00
XML_ERR_ERROR , NULL , 0 ,
( const char * ) str1 ,
2004-02-25 14:52:31 +03:00
( const char * ) str1 ,
( const char * ) str3 , 0 , 0 , msg , str1 , str2 , str3 ) ;
2003-10-04 02:21:51 +04:00
}
2004-02-25 14:52:31 +03:00
# endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
# ifdef LIBXML_VALID_ENABLED
2003-10-04 02:21:51 +04:00
/**
2004-02-25 14:52:31 +03:00
* xmlErrValidNodeNr :
2003-10-04 02:21:51 +04:00
* @ ctxt : an XML validation parser context
* @ node : the node raising the error
* @ error : the error number
* @ str1 : extra informations
2004-02-25 14:52:31 +03:00
* @ int2 : extra informations
2003-10-04 02:21:51 +04:00
* @ str3 : extra informations
*
* Handle a validation error , provide contextual informations
*/
static void
2004-02-25 14:52:31 +03:00
xmlErrValidNodeNr ( xmlValidCtxtPtr ctxt ,
2003-10-04 02:21:51 +04:00
xmlNodePtr node , xmlParserErrors error ,
const char * msg , const xmlChar * str1 ,
2004-02-25 14:52:31 +03:00
int int2 , const xmlChar * str3 )
2003-10-04 02:21:51 +04:00
{
2003-10-10 18:10:40 +04:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-04 02:21:51 +04:00
xmlGenericErrorFunc channel = NULL ;
xmlParserCtxtPtr pctxt = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
channel = ctxt - > error ;
data = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
/* Use the special values to detect if it is part of a parsing
context */
if ( ( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_0 ) | |
( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_1 ) ) {
2006-08-22 18:45:40 +04:00
long delta = ( char * ) ctxt - ( char * ) ctxt - > userData ;
if ( ( delta > 0 ) & & ( delta < 250 ) )
pctxt = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
}
2003-10-04 02:21:51 +04:00
}
2003-10-28 18:44:17 +03:00
__xmlRaiseError ( schannel , channel , data , pctxt , node , XML_FROM_VALID , error ,
2003-10-04 02:21:51 +04:00
XML_ERR_ERROR , NULL , 0 ,
( const char * ) str1 ,
2004-02-25 14:52:31 +03:00
( const char * ) str3 ,
NULL , int2 , 0 , msg , str1 , int2 , str3 ) ;
2003-10-04 02:21:51 +04:00
}
2004-02-25 14:52:31 +03:00
2003-10-04 02:21:51 +04:00
/**
* xmlErrValidWarning :
* @ ctxt : an XML validation parser context
* @ node : the node raising the error
* @ error : the error number
2004-02-06 10:36:04 +03:00
* @ str1 : extra information
* @ str2 : extra information
* @ str3 : extra information
2003-10-04 02:21:51 +04:00
*
2004-02-06 10:36:04 +03:00
* Handle a validation error , provide contextual information
2003-10-04 02:21:51 +04:00
*/
static void
2004-02-06 10:36:04 +03:00
xmlErrValidWarning ( xmlValidCtxtPtr ctxt ,
2003-10-04 02:21:51 +04:00
xmlNodePtr node , xmlParserErrors error ,
const char * msg , const xmlChar * str1 ,
const xmlChar * str2 , const xmlChar * str3 )
{
2003-10-10 18:10:40 +04:00
xmlStructuredErrorFunc schannel = NULL ;
2003-10-04 02:21:51 +04:00
xmlGenericErrorFunc channel = NULL ;
xmlParserCtxtPtr pctxt = NULL ;
void * data = NULL ;
if ( ctxt ! = NULL ) {
2004-12-18 03:01:21 +03:00
channel = ctxt - > warning ;
2003-10-04 02:21:51 +04:00
data = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
/* Use the special values to detect if it is part of a parsing
context */
if ( ( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_0 ) | |
( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_1 ) ) {
2006-08-22 18:45:40 +04:00
long delta = ( char * ) ctxt - ( char * ) ctxt - > userData ;
if ( ( delta > 0 ) & & ( delta < 250 ) )
pctxt = ctxt - > userData ;
2004-10-29 16:10:55 +04:00
}
2003-10-04 02:21:51 +04:00
}
2003-10-28 18:44:17 +03:00
__xmlRaiseError ( schannel , channel , data , pctxt , node , XML_FROM_VALID , error ,
2003-10-04 02:21:51 +04:00
XML_ERR_WARNING , NULL , 0 ,
( const char * ) str1 ,
( const char * ) str1 ,
( const char * ) str3 , 0 , 0 , msg , str1 , str2 , str3 ) ;
2003-10-03 02:28:19 +04:00
}
2002-12-20 03:16:24 +03:00
2003-10-04 02:21:51 +04:00
2002-12-20 03:16:24 +03:00
# ifdef LIBXML_REGEXP_ENABLED
/*
* If regexp are enabled we can do continuous validation without the
* need of a tree to validate the content model . this is done in each
* callbacks .
* Each xmlValidState represent the validation state associated to the
* set of nodes currently open from the document root to the current element .
*/
typedef struct _xmlValidState {
xmlElementPtr elemDecl ; /* pointer to the content model */
xmlNodePtr node ; /* pointer to the current node */
xmlRegExecCtxtPtr exec ; /* regexp runtime */
} _xmlValidState ;
static int
vstateVPush ( xmlValidCtxtPtr ctxt , xmlElementPtr elemDecl , xmlNodePtr node ) {
2003-04-24 20:06:47 +04:00
if ( ( ctxt - > vstateMax = = 0 ) | | ( ctxt - > vstateTab = = NULL ) ) {
2002-12-20 03:16:24 +03:00
ctxt - > vstateMax = 10 ;
ctxt - > vstateTab = ( xmlValidState * ) xmlMalloc ( ctxt - > vstateMax *
sizeof ( ctxt - > vstateTab [ 0 ] ) ) ;
if ( ctxt - > vstateTab = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2002-12-20 03:16:24 +03:00
return ( - 1 ) ;
}
}
if ( ctxt - > vstateNr > = ctxt - > vstateMax ) {
2003-04-24 20:06:47 +04:00
xmlValidState * tmp ;
tmp = ( xmlValidState * ) xmlRealloc ( ctxt - > vstateTab ,
2 * ctxt - > vstateMax * sizeof ( ctxt - > vstateTab [ 0 ] ) ) ;
if ( tmp = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " realloc failed " ) ;
2002-12-20 03:16:24 +03:00
return ( - 1 ) ;
}
2003-04-24 20:06:47 +04:00
ctxt - > vstateMax * = 2 ;
ctxt - > vstateTab = tmp ;
2002-12-20 03:16:24 +03:00
}
ctxt - > vstate = & ctxt - > vstateTab [ ctxt - > vstateNr ] ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . elemDecl = elemDecl ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . node = node ;
if ( ( elemDecl ! = NULL ) & & ( elemDecl - > etype = = XML_ELEMENT_TYPE_ELEMENT ) ) {
if ( elemDecl - > contModel = = NULL )
xmlValidBuildContentModel ( ctxt , elemDecl ) ;
if ( elemDecl - > contModel ! = NULL ) {
ctxt - > vstateTab [ ctxt - > vstateNr ] . exec =
xmlRegNewExecCtxt ( elemDecl - > contModel , NULL , NULL ) ;
} else {
ctxt - > vstateTab [ ctxt - > vstateNr ] . exec = NULL ;
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elemDecl ,
XML_ERR_INTERNAL_ERROR ,
" Failed to build content model regexp for %s \n " ,
node - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
}
}
return ( ctxt - > vstateNr + + ) ;
}
static int
vstateVPop ( xmlValidCtxtPtr ctxt ) {
xmlElementPtr elemDecl ;
2002-12-27 22:37:04 +03:00
if ( ctxt - > vstateNr < 1 ) return ( - 1 ) ;
2002-12-20 03:16:24 +03:00
ctxt - > vstateNr - - ;
elemDecl = ctxt - > vstateTab [ ctxt - > vstateNr ] . elemDecl ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . elemDecl = NULL ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . node = NULL ;
if ( ( elemDecl ! = NULL ) & & ( elemDecl - > etype = = XML_ELEMENT_TYPE_ELEMENT ) ) {
xmlRegFreeExecCtxt ( ctxt - > vstateTab [ ctxt - > vstateNr ] . exec ) ;
}
ctxt - > vstateTab [ ctxt - > vstateNr ] . exec = NULL ;
if ( ctxt - > vstateNr > = 1 )
ctxt - > vstate = & ctxt - > vstateTab [ ctxt - > vstateNr - 1 ] ;
else
ctxt - > vstate = NULL ;
return ( ctxt - > vstateNr ) ;
}
# else /* not LIBXML_REGEXP_ENABLED */
2001-04-20 17:03:48 +04:00
/*
2002-11-30 14:22:59 +03:00
* If regexp are not enabled , it uses a home made algorithm less
* complex and easier to
2001-12-31 19:16:02 +03:00
* debug / maintain than a generic NFA - > DFA state based algo . The
2001-04-20 17:03:48 +04:00
* only restriction is on the deepness of the tree limited by the
* size of the occurs bitfield
*
* this is the content of a saved state for rollbacks
*/
# define ROLLBACK_OR 0
# define ROLLBACK_PARENT 1
2001-10-12 02:55:55 +04:00
typedef struct _xmlValidState {
2001-04-20 17:03:48 +04:00
xmlElementContentPtr cont ; /* pointer to the content model subtree */
xmlNodePtr node ; /* pointer to the current node in the list */
2001-12-31 19:16:02 +03:00
long occurs ; /* bitfield for multiple occurrences */
2001-04-20 17:03:48 +04:00
unsigned char depth ; /* current depth in the overall tree */
unsigned char state ; /* ROLLBACK_XXX */
} _xmlValidState ;
2002-04-29 19:50:14 +04:00
# define MAX_RECURSE 25000
2001-04-20 17:03:48 +04:00
# define MAX_DEPTH ((sizeof(_xmlValidState.occurs)) * 8)
# define CONT ctxt->vstate->cont
# define NODE ctxt->vstate->node
# define DEPTH ctxt->vstate->depth
# define OCCURS ctxt->vstate->occurs
# define STATE ctxt->vstate->state
2001-12-31 19:37:34 +03:00
# define OCCURRENCE (ctxt->vstate->occurs & (1 << DEPTH))
# define PARENT_OCCURRENCE (ctxt->vstate->occurs & ((1 << DEPTH) - 1))
2001-04-20 17:03:48 +04:00
2001-12-31 19:37:34 +03:00
# define SET_OCCURRENCE ctxt->vstate->occurs |= (1 << DEPTH)
# define RESET_OCCURRENCE ctxt->vstate->occurs &= ((1 << DEPTH) - 1)
2001-04-20 17:03:48 +04:00
static int
vstateVPush ( xmlValidCtxtPtr ctxt , xmlElementContentPtr cont ,
xmlNodePtr node , unsigned char depth , long occurs ,
unsigned char state ) {
2001-05-19 18:59:49 +04:00
int i = ctxt - > vstateNr - 1 ;
2002-04-15 14:15:25 +04:00
if ( ctxt - > vstateNr > MAX_RECURSE ) {
return ( - 1 ) ;
}
2003-04-24 20:06:47 +04:00
if ( ctxt - > vstateTab = = NULL ) {
ctxt - > vstateMax = 8 ;
ctxt - > vstateTab = ( xmlValidState * ) xmlMalloc (
ctxt - > vstateMax * sizeof ( ctxt - > vstateTab [ 0 ] ) ) ;
if ( ctxt - > vstateTab = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2003-04-24 20:06:47 +04:00
return ( - 1 ) ;
}
}
2001-04-20 17:03:48 +04:00
if ( ctxt - > vstateNr > = ctxt - > vstateMax ) {
2003-04-24 20:06:47 +04:00
xmlValidState * tmp ;
tmp = ( xmlValidState * ) xmlRealloc ( ctxt - > vstateTab ,
2 * ctxt - > vstateMax * sizeof ( ctxt - > vstateTab [ 0 ] ) ) ;
if ( tmp = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2002-04-15 14:15:25 +04:00
return ( - 1 ) ;
2001-04-20 17:03:48 +04:00
}
2003-04-24 20:06:47 +04:00
ctxt - > vstateMax * = 2 ;
ctxt - > vstateTab = tmp ;
2001-04-22 14:35:56 +04:00
ctxt - > vstate = & ctxt - > vstateTab [ 0 ] ;
2001-04-20 17:03:48 +04:00
}
2001-05-19 18:59:49 +04:00
/*
* Don ' t push on the stack a state already here
*/
if ( ( i > = 0 ) & & ( ctxt - > vstateTab [ i ] . cont = = cont ) & &
( ctxt - > vstateTab [ i ] . node = = node ) & &
( ctxt - > vstateTab [ i ] . depth = = depth ) & &
( ctxt - > vstateTab [ i ] . occurs = = occurs ) & &
( ctxt - > vstateTab [ i ] . state = = state ) )
return ( ctxt - > vstateNr ) ;
2001-04-20 17:03:48 +04:00
ctxt - > vstateTab [ ctxt - > vstateNr ] . cont = cont ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . node = node ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . depth = depth ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . occurs = occurs ;
ctxt - > vstateTab [ ctxt - > vstateNr ] . state = state ;
return ( ctxt - > vstateNr + + ) ;
}
static int
vstateVPop ( xmlValidCtxtPtr ctxt ) {
if ( ctxt - > vstateNr < = 1 ) return ( - 1 ) ;
ctxt - > vstateNr - - ;
ctxt - > vstate = & ctxt - > vstateTab [ 0 ] ;
ctxt - > vstate - > cont = ctxt - > vstateTab [ ctxt - > vstateNr ] . cont ;
ctxt - > vstate - > node = ctxt - > vstateTab [ ctxt - > vstateNr ] . node ;
ctxt - > vstate - > depth = ctxt - > vstateTab [ ctxt - > vstateNr ] . depth ;
ctxt - > vstate - > occurs = ctxt - > vstateTab [ ctxt - > vstateNr ] . occurs ;
ctxt - > vstate - > state = ctxt - > vstateTab [ ctxt - > vstateNr ] . state ;
return ( ctxt - > vstateNr ) ;
}
2002-09-24 18:13:13 +04:00
# endif /* LIBXML_REGEXP_ENABLED */
2002-11-30 14:22:59 +03:00
static int
nodeVPush ( xmlValidCtxtPtr ctxt , xmlNodePtr value )
{
if ( ctxt - > nodeMax < = 0 ) {
ctxt - > nodeMax = 4 ;
ctxt - > nodeTab =
( xmlNodePtr * ) xmlMalloc ( ctxt - > nodeMax *
sizeof ( ctxt - > nodeTab [ 0 ] ) ) ;
if ( ctxt - > nodeTab = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2002-11-30 14:22:59 +03:00
ctxt - > nodeMax = 0 ;
return ( 0 ) ;
}
}
if ( ctxt - > nodeNr > = ctxt - > nodeMax ) {
2003-04-24 20:06:47 +04:00
xmlNodePtr * tmp ;
tmp = ( xmlNodePtr * ) xmlRealloc ( ctxt - > nodeTab ,
ctxt - > nodeMax * 2 * sizeof ( ctxt - > nodeTab [ 0 ] ) ) ;
if ( tmp = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " realloc failed " ) ;
2002-11-30 14:22:59 +03:00
return ( 0 ) ;
}
2003-04-24 20:06:47 +04:00
ctxt - > nodeMax * = 2 ;
ctxt - > nodeTab = tmp ;
2002-11-30 14:22:59 +03:00
}
ctxt - > nodeTab [ ctxt - > nodeNr ] = value ;
ctxt - > node = value ;
return ( ctxt - > nodeNr + + ) ;
}
static xmlNodePtr
nodeVPop ( xmlValidCtxtPtr ctxt )
{
xmlNodePtr ret ;
if ( ctxt - > nodeNr < = 0 )
2005-07-29 03:49:35 +04:00
return ( NULL ) ;
2002-11-30 14:22:59 +03:00
ctxt - > nodeNr - - ;
if ( ctxt - > nodeNr > 0 )
ctxt - > node = ctxt - > nodeTab [ ctxt - > nodeNr - 1 ] ;
else
ctxt - > node = NULL ;
ret = ctxt - > nodeTab [ ctxt - > nodeNr ] ;
2005-07-29 03:49:35 +04:00
ctxt - > nodeTab [ ctxt - > nodeNr ] = NULL ;
2002-11-30 14:22:59 +03:00
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
# ifdef DEBUG_VALID_ALGO
2001-04-20 17:03:48 +04:00
static void
xmlValidPrintNode ( xmlNodePtr cur ) {
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext , " null " ) ;
return ;
}
switch ( cur - > type ) {
case XML_ELEMENT_NODE :
xmlGenericError ( xmlGenericErrorContext , " %s " , cur - > name ) ;
break ;
case XML_TEXT_NODE :
xmlGenericError ( xmlGenericErrorContext , " text " ) ;
break ;
case XML_CDATA_SECTION_NODE :
xmlGenericError ( xmlGenericErrorContext , " cdata " ) ;
break ;
case XML_ENTITY_REF_NODE :
xmlGenericError ( xmlGenericErrorContext , " &%s; " , cur - > name ) ;
break ;
case XML_PI_NODE :
xmlGenericError ( xmlGenericErrorContext , " pi(%s) " , cur - > name ) ;
break ;
case XML_COMMENT_NODE :
xmlGenericError ( xmlGenericErrorContext , " comment " ) ;
break ;
case XML_ATTRIBUTE_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?attr? " ) ;
break ;
case XML_ENTITY_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?ent? " ) ;
break ;
case XML_DOCUMENT_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?doc? " ) ;
break ;
case XML_DOCUMENT_TYPE_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?doctype? " ) ;
break ;
case XML_DOCUMENT_FRAG_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?frag? " ) ;
break ;
case XML_NOTATION_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?nota? " ) ;
break ;
case XML_HTML_DOCUMENT_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?html? " ) ;
break ;
2001-10-18 18:57:24 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?docb? " ) ;
break ;
# endif
2001-04-20 17:03:48 +04:00
case XML_DTD_NODE :
xmlGenericError ( xmlGenericErrorContext , " ?dtd? " ) ;
break ;
case XML_ELEMENT_DECL :
xmlGenericError ( xmlGenericErrorContext , " ?edecl? " ) ;
break ;
case XML_ATTRIBUTE_DECL :
xmlGenericError ( xmlGenericErrorContext , " ?adecl? " ) ;
break ;
case XML_ENTITY_DECL :
xmlGenericError ( xmlGenericErrorContext , " ?entdecl? " ) ;
break ;
case XML_NAMESPACE_DECL :
xmlGenericError ( xmlGenericErrorContext , " ?nsdecl? " ) ;
break ;
case XML_XINCLUDE_START :
xmlGenericError ( xmlGenericErrorContext , " incstart " ) ;
break ;
case XML_XINCLUDE_END :
xmlGenericError ( xmlGenericErrorContext , " incend " ) ;
break ;
}
}
static void
xmlValidPrintNodeList ( xmlNodePtr cur ) {
2001-02-23 20:55:21 +03:00
if ( cur = = NULL )
xmlGenericError ( xmlGenericErrorContext , " null " ) ;
while ( cur ! = NULL ) {
2001-04-20 17:03:48 +04:00
xmlValidPrintNode ( cur ) ;
2001-02-23 20:55:21 +03:00
cur = cur - > next ;
}
}
2001-04-20 17:03:48 +04:00
static void
xmlValidDebug ( xmlNodePtr cur , xmlElementContentPtr cont ) {
2003-03-07 00:37:30 +03:00
char expr [ 5000 ] ;
2001-02-23 20:55:21 +03:00
expr [ 0 ] = 0 ;
xmlGenericError ( xmlGenericErrorContext , " valid: " ) ;
xmlValidPrintNodeList ( cur ) ;
xmlGenericError ( xmlGenericErrorContext , " against " ) ;
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( expr , 5000 , cont , 1 ) ;
2001-02-23 20:55:21 +03:00
xmlGenericError ( xmlGenericErrorContext , " %s \n " , expr ) ;
}
2001-04-20 17:03:48 +04:00
static void
xmlValidDebugState ( xmlValidStatePtr state ) {
xmlGenericError ( xmlGenericErrorContext , " ( " ) ;
if ( state - > cont = = NULL )
xmlGenericError ( xmlGenericErrorContext , " null, " ) ;
else
switch ( state - > cont - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
xmlGenericError ( xmlGenericErrorContext , " pcdata, " ) ;
break ;
case XML_ELEMENT_CONTENT_ELEMENT :
xmlGenericError ( xmlGenericErrorContext , " %s, " ,
state - > cont - > name ) ;
break ;
case XML_ELEMENT_CONTENT_SEQ :
xmlGenericError ( xmlGenericErrorContext , " seq, " ) ;
break ;
case XML_ELEMENT_CONTENT_OR :
xmlGenericError ( xmlGenericErrorContext , " or, " ) ;
break ;
}
xmlValidPrintNode ( state - > node ) ;
xmlGenericError ( xmlGenericErrorContext , " ,%d,%X,%d) " ,
state - > depth , state - > occurs , state - > state ) ;
}
static void
xmlValidStateDebug ( xmlValidCtxtPtr ctxt ) {
int i , j ;
xmlGenericError ( xmlGenericErrorContext , " state: " ) ;
xmlValidDebugState ( ctxt - > vstate ) ;
xmlGenericError ( xmlGenericErrorContext , " stack: %d " ,
ctxt - > vstateNr - 1 ) ;
for ( i = 0 , j = ctxt - > vstateNr - 1 ; ( i < 3 ) & & ( j > 0 ) ; i + + , j - - )
xmlValidDebugState ( & ctxt - > vstateTab [ j ] ) ;
xmlGenericError ( xmlGenericErrorContext , " \n " ) ;
}
/*****
2001-02-23 20:55:21 +03:00
# define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c);
2001-04-20 17:03:48 +04:00
* * * * */
# define DEBUG_VALID_STATE(n,c) xmlValidStateDebug(ctxt);
2001-03-10 15:32:04 +03:00
# define DEBUG_VALID_MSG(m) \
xmlGenericError ( xmlGenericErrorContext , " %s \n " , m ) ;
2001-02-23 20:55:21 +03:00
# else
# define DEBUG_VALID_STATE(n,c)
2001-03-10 15:32:04 +03:00
# define DEBUG_VALID_MSG(m)
2001-02-23 20:55:21 +03:00
# endif
2001-12-31 19:16:02 +03:00
/* TODO: use hash table for accesses to elem and attribute definitions */
2001-02-23 20:55:21 +03:00
2002-09-05 14:58:49 +04:00
2001-02-23 20:55:21 +03:00
# define CHECK_DTD \
if ( doc = = NULL ) return ( 0 ) ; \
else if ( ( doc - > intSubset = = NULL ) & & \
( doc - > extSubset = = NULL ) ) return ( 0 )
xmlAttributePtr xmlScanAttributeDecl ( xmlDtdPtr dtd , const xmlChar * elem ) ;
2002-09-13 18:48:12 +04:00
# ifdef LIBXML_REGEXP_ENABLED
/************************************************************************
* *
* Content model validation based on the regexps *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlValidBuildAContentModel :
* @ content : the content model
* @ ctxt : the schema parser context
* @ name : the element name whose content is being built
*
* Generate the automata sequence needed for that type
*
2002-09-16 14:51:38 +04:00
* Returns 1 if successful or 0 in case of error .
2002-09-13 18:48:12 +04:00
*/
static int
xmlValidBuildAContentModel ( xmlElementContentPtr content ,
xmlValidCtxtPtr ctxt ,
const xmlChar * name ) {
if ( content = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , NULL , XML_ERR_INTERNAL_ERROR ,
" Found NULL content in content model of %s \n " ,
name , NULL , NULL ) ;
2002-09-16 14:51:38 +04:00
return ( 0 ) ;
2002-09-13 18:48:12 +04:00
}
switch ( content - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , NULL , XML_ERR_INTERNAL_ERROR ,
" Found PCDATA in content model of %s \n " ,
name , NULL , NULL ) ;
2002-09-16 14:51:38 +04:00
return ( 0 ) ;
2002-09-13 18:48:12 +04:00
break ;
case XML_ELEMENT_CONTENT_ELEMENT : {
xmlAutomataStatePtr oldstate = ctxt - > state ;
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( content - > name , content - > prefix , fn , 50 ) ;
if ( fullname = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " Building content model " ) ;
2003-04-07 14:22:39 +04:00
return ( 0 ) ;
2002-09-18 01:50:03 +04:00
}
2002-09-13 18:48:12 +04:00
switch ( content - > ocur ) {
case XML_ELEMENT_CONTENT_ONCE :
ctxt - > state = xmlAutomataNewTransition ( ctxt - > am ,
2003-04-07 14:22:39 +04:00
ctxt - > state , NULL , fullname , NULL ) ;
2002-09-13 18:48:12 +04:00
break ;
case XML_ELEMENT_CONTENT_OPT :
ctxt - > state = xmlAutomataNewTransition ( ctxt - > am ,
2003-04-07 14:22:39 +04:00
ctxt - > state , NULL , fullname , NULL ) ;
2002-09-13 18:48:12 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , ctxt - > state ) ;
break ;
case XML_ELEMENT_CONTENT_PLUS :
ctxt - > state = xmlAutomataNewTransition ( ctxt - > am ,
2003-04-07 14:22:39 +04:00
ctxt - > state , NULL , fullname , NULL ) ;
2002-09-13 18:48:12 +04:00
xmlAutomataNewTransition ( ctxt - > am , ctxt - > state ,
2003-04-07 14:22:39 +04:00
ctxt - > state , fullname , NULL ) ;
2002-09-13 18:48:12 +04:00
break ;
case XML_ELEMENT_CONTENT_MULT :
2004-04-17 17:31:06 +04:00
ctxt - > state = xmlAutomataNewEpsilon ( ctxt - > am ,
ctxt - > state , NULL ) ;
xmlAutomataNewTransition ( ctxt - > am ,
ctxt - > state , ctxt - > state , fullname , NULL ) ;
2002-09-13 18:48:12 +04:00
break ;
}
2003-04-07 14:22:39 +04:00
if ( ( fullname ! = fn ) & & ( fullname ! = content - > name ) )
xmlFree ( fullname ) ;
2002-09-13 18:48:12 +04:00
break ;
}
case XML_ELEMENT_CONTENT_SEQ : {
2002-09-18 20:29:02 +04:00
xmlAutomataStatePtr oldstate , oldend ;
2002-09-13 18:48:12 +04:00
xmlElementContentOccur ocur ;
/*
* Simply iterate over the content
*/
oldstate = ctxt - > state ;
ocur = content - > ocur ;
2003-02-24 22:54:33 +03:00
if ( ocur ! = XML_ELEMENT_CONTENT_ONCE ) {
ctxt - > state = xmlAutomataNewEpsilon ( ctxt - > am , oldstate , NULL ) ;
oldstate = ctxt - > state ;
}
2002-09-18 01:50:03 +04:00
do {
2002-09-13 18:48:12 +04:00
xmlValidBuildAContentModel ( content - > c1 , ctxt , name ) ;
content = content - > c2 ;
2002-09-18 01:50:03 +04:00
} while ( ( content - > type = = XML_ELEMENT_CONTENT_SEQ ) & &
( content - > ocur = = XML_ELEMENT_CONTENT_ONCE ) ) ;
xmlValidBuildAContentModel ( content , ctxt , name ) ;
2002-09-18 20:29:02 +04:00
oldend = ctxt - > state ;
ctxt - > state = xmlAutomataNewEpsilon ( ctxt - > am , oldend , NULL ) ;
2002-09-13 18:48:12 +04:00
switch ( ocur ) {
case XML_ELEMENT_CONTENT_ONCE :
break ;
case XML_ELEMENT_CONTENT_OPT :
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , ctxt - > state ) ;
break ;
case XML_ELEMENT_CONTENT_MULT :
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , ctxt - > state ) ;
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , oldend , oldstate ) ;
2002-09-13 18:48:12 +04:00
break ;
case XML_ELEMENT_CONTENT_PLUS :
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , oldend , oldstate ) ;
2002-09-13 18:48:12 +04:00
break ;
}
break ;
}
case XML_ELEMENT_CONTENT_OR : {
2002-09-18 20:29:02 +04:00
xmlAutomataStatePtr oldstate , oldend ;
2002-09-13 18:48:12 +04:00
xmlElementContentOccur ocur ;
ocur = content - > ocur ;
2002-09-18 20:29:02 +04:00
if ( ( ocur = = XML_ELEMENT_CONTENT_PLUS ) | |
( ocur = = XML_ELEMENT_CONTENT_MULT ) ) {
ctxt - > state = xmlAutomataNewEpsilon ( ctxt - > am ,
ctxt - > state , NULL ) ;
}
oldstate = ctxt - > state ;
oldend = xmlAutomataNewState ( ctxt - > am ) ;
2002-09-13 18:48:12 +04:00
/*
* iterate over the subtypes and remerge the end with an
* epsilon transition
*/
2002-09-18 01:50:03 +04:00
do {
2002-09-18 20:29:02 +04:00
ctxt - > state = oldstate ;
2002-09-13 18:48:12 +04:00
xmlValidBuildAContentModel ( content - > c1 , ctxt , name ) ;
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , oldend ) ;
2002-09-13 18:48:12 +04:00
content = content - > c2 ;
2002-09-18 01:50:03 +04:00
} while ( ( content - > type = = XML_ELEMENT_CONTENT_OR ) & &
( content - > ocur = = XML_ELEMENT_CONTENT_ONCE ) ) ;
2002-09-18 20:29:02 +04:00
ctxt - > state = oldstate ;
2002-09-18 01:50:03 +04:00
xmlValidBuildAContentModel ( content , ctxt , name ) ;
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , ctxt - > state , oldend ) ;
ctxt - > state = xmlAutomataNewEpsilon ( ctxt - > am , oldend , NULL ) ;
2002-09-13 18:48:12 +04:00
switch ( ocur ) {
case XML_ELEMENT_CONTENT_ONCE :
break ;
case XML_ELEMENT_CONTENT_OPT :
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , ctxt - > state ) ;
2002-09-13 18:48:12 +04:00
break ;
case XML_ELEMENT_CONTENT_MULT :
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , oldstate , ctxt - > state ) ;
xmlAutomataNewEpsilon ( ctxt - > am , oldend , oldstate ) ;
2002-09-13 18:48:12 +04:00
break ;
case XML_ELEMENT_CONTENT_PLUS :
2002-09-18 20:29:02 +04:00
xmlAutomataNewEpsilon ( ctxt - > am , oldend , oldstate ) ;
2002-09-13 18:48:12 +04:00
break ;
}
break ;
}
default :
2003-10-04 02:21:51 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" ContentModel broken for element %s \n " ,
( const char * ) name ) ;
2002-09-16 14:51:38 +04:00
return ( 0 ) ;
2002-09-13 18:48:12 +04:00
}
2002-09-16 14:51:38 +04:00
return ( 1 ) ;
2002-09-13 18:48:12 +04:00
}
/**
* xmlValidBuildContentModel :
* @ ctxt : a validation context
* @ elem : an element declaration node
*
* ( Re ) Build the automata associated to the content model of this
* element
*
2002-09-16 14:51:38 +04:00
* Returns 1 in case of success , 0 in case of error
2002-09-13 18:48:12 +04:00
*/
int
xmlValidBuildContentModel ( xmlValidCtxtPtr ctxt , xmlElementPtr elem ) {
if ( ( ctxt = = NULL ) | | ( elem = = NULL ) )
2002-09-16 14:51:38 +04:00
return ( 0 ) ;
2002-09-13 18:48:12 +04:00
if ( elem - > type ! = XML_ELEMENT_DECL )
return ( 0 ) ;
2002-09-16 14:51:38 +04:00
if ( elem - > etype ! = XML_ELEMENT_TYPE_ELEMENT )
return ( 1 ) ;
2002-09-13 18:48:12 +04:00
/* TODO: should we rebuild in this case ? */
2003-02-05 14:01:50 +03:00
if ( elem - > contModel ! = NULL ) {
if ( ! xmlRegexpIsDeterminist ( elem - > contModel ) ) {
ctxt - > valid = 0 ;
return ( 0 ) ;
}
2002-09-16 14:51:38 +04:00
return ( 1 ) ;
2003-02-05 14:01:50 +03:00
}
2002-09-13 18:48:12 +04:00
ctxt - > am = xmlNewAutomata ( ) ;
if ( ctxt - > am = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem ,
XML_ERR_INTERNAL_ERROR ,
" Cannot create automata for element %s \n " ,
elem - > name , NULL , NULL ) ;
2002-09-16 14:51:38 +04:00
return ( 0 ) ;
2002-09-13 18:48:12 +04:00
}
2003-07-31 18:47:38 +04:00
ctxt - > state = xmlAutomataGetInitState ( ctxt - > am ) ;
2002-09-13 18:48:12 +04:00
xmlValidBuildAContentModel ( elem - > content , ctxt , elem - > name ) ;
xmlAutomataSetFinalState ( ctxt - > am , ctxt - > state ) ;
2002-09-16 14:51:38 +04:00
elem - > contModel = xmlAutomataCompile ( ctxt - > am ) ;
2003-04-24 20:06:47 +04:00
if ( xmlRegexpIsDeterminist ( elem - > contModel ) ! = 1 ) {
2002-09-18 20:29:02 +04:00
char expr [ 5000 ] ;
expr [ 0 ] = 0 ;
xmlSnprintfElementContent ( expr , 5000 , elem - > content , 1 ) ;
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem ,
XML_DTD_CONTENT_NOT_DETERMINIST ,
" Content model of %s is not determinist: %s \n " ,
elem - > name , BAD_CAST expr , NULL ) ;
2002-09-18 20:29:02 +04:00
# ifdef DEBUG_REGEXP_ALGO
xmlRegexpPrint ( stderr , elem - > contModel ) ;
# endif
2002-09-13 18:48:12 +04:00
ctxt - > valid = 0 ;
2003-02-05 14:01:50 +03:00
ctxt - > state = NULL ;
xmlFreeAutomata ( ctxt - > am ) ;
ctxt - > am = NULL ;
return ( 0 ) ;
2002-09-13 18:48:12 +04:00
}
ctxt - > state = NULL ;
xmlFreeAutomata ( ctxt - > am ) ;
ctxt - > am = NULL ;
2002-09-16 14:51:38 +04:00
return ( 1 ) ;
2002-09-13 18:48:12 +04:00
}
# endif /* LIBXML_REGEXP_ENABLED */
2001-02-23 20:55:21 +03:00
/****************************************************************
* *
* Util functions for data allocation / deallocation *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-09 13:10:36 +04:00
/**
* xmlNewValidCtxt :
*
* Allocate a validation context structure .
*
* Returns NULL if not , otherwise the new validation context structure
*/
2003-10-03 02:28:19 +04:00
xmlValidCtxtPtr xmlNewValidCtxt ( void ) {
2003-06-09 13:10:36 +04:00
xmlValidCtxtPtr ret ;
2003-10-03 02:28:19 +04:00
if ( ( ret = xmlMalloc ( sizeof ( xmlValidCtxt ) ) ) = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2003-06-09 13:10:36 +04:00
return ( NULL ) ;
2003-10-03 02:28:19 +04:00
}
2003-06-09 13:10:36 +04:00
( void ) memset ( ret , 0 , sizeof ( xmlValidCtxt ) ) ;
return ( ret ) ;
}
/**
* xmlFreeValidCtxt :
* @ cur : the validation context to free
*
* Free a validation context structure .
*/
void
xmlFreeValidCtxt ( xmlValidCtxtPtr cur ) {
2004-11-03 22:16:55 +03:00
if ( cur - > vstateTab ! = NULL )
xmlFree ( cur - > vstateTab ) ;
if ( cur - > nodeTab ! = NULL )
xmlFree ( cur - > nodeTab ) ;
2003-06-09 13:10:36 +04:00
xmlFree ( cur ) ;
}
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-02-23 20:55:21 +03:00
/**
2005-01-25 03:22:52 +03:00
* xmlNewDocElementContent :
* @ doc : the document
2001-02-23 20:55:21 +03:00
* @ name : the subelement name or NULL
* @ type : the type of element content decl
*
2005-01-25 03:22:52 +03:00
* Allocate an element content structure for the document .
2001-02-23 20:55:21 +03:00
*
2001-12-31 19:16:02 +03:00
* Returns NULL if not , otherwise the new element content structure
2001-02-23 20:55:21 +03:00
*/
xmlElementContentPtr
2005-01-25 03:22:52 +03:00
xmlNewDocElementContent ( xmlDocPtr doc , const xmlChar * name ,
xmlElementContentType type ) {
2001-02-23 20:55:21 +03:00
xmlElementContentPtr ret ;
2005-01-25 03:22:52 +03:00
xmlDictPtr dict = NULL ;
if ( doc ! = NULL )
dict = doc - > dict ;
2001-02-23 20:55:21 +03:00
switch ( type ) {
case XML_ELEMENT_CONTENT_ELEMENT :
if ( name = = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" xmlNewElementContent : name == NULL ! \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
}
break ;
case XML_ELEMENT_CONTENT_PCDATA :
case XML_ELEMENT_CONTENT_SEQ :
case XML_ELEMENT_CONTENT_OR :
if ( name ! = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" xmlNewElementContent : name != NULL ! \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
}
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" Internal: ELEMENT content corrupted invalid type \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
ret = ( xmlElementContentPtr ) xmlMalloc ( sizeof ( xmlElementContent ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
2002-02-20 19:48:52 +03:00
memset ( ret , 0 , sizeof ( xmlElementContent ) ) ;
2001-02-23 20:55:21 +03:00
ret - > type = type ;
ret - > ocur = XML_ELEMENT_CONTENT_ONCE ;
2001-11-09 02:36:42 +03:00
if ( name ! = NULL ) {
2005-01-25 03:22:52 +03:00
int l ;
const xmlChar * tmp ;
tmp = xmlSplitQName3 ( name , & l ) ;
if ( tmp = = NULL ) {
if ( dict = = NULL )
ret - > name = xmlStrdup ( name ) ;
else
ret - > name = xmlDictLookup ( dict , name , - 1 ) ;
} else {
if ( dict = = NULL ) {
ret - > prefix = xmlStrndup ( name , l ) ;
ret - > name = xmlStrdup ( tmp ) ;
} else {
ret - > prefix = xmlDictLookup ( dict , name , l ) ;
ret - > name = xmlDictLookup ( dict , tmp , - 1 ) ;
}
}
2001-11-09 02:36:42 +03:00
}
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
/**
2005-01-25 03:22:52 +03:00
* xmlNewElementContent :
* @ name : the subelement name or NULL
* @ type : the type of element content decl
*
* Allocate an element content structure .
* Deprecated in favor of xmlNewDocElementContent
*
* Returns NULL if not , otherwise the new element content structure
*/
xmlElementContentPtr
xmlNewElementContent ( const xmlChar * name , xmlElementContentType type ) {
return ( xmlNewDocElementContent ( NULL , name , type ) ) ;
}
/**
* xmlCopyDocElementContent :
* @ doc : the document owning the element declaration
2002-12-10 18:19:08 +03:00
* @ cur : An element content pointer .
2001-02-23 20:55:21 +03:00
*
* Build a copy of an element content description .
*
* Returns the new xmlElementContentPtr or NULL in case of error .
*/
xmlElementContentPtr
2005-01-25 03:22:52 +03:00
xmlCopyDocElementContent ( xmlDocPtr doc , xmlElementContentPtr cur ) {
xmlElementContentPtr ret = NULL , prev = NULL , tmp ;
xmlDictPtr dict = NULL ;
2001-02-23 20:55:21 +03:00
if ( cur = = NULL ) return ( NULL ) ;
2005-01-25 03:22:52 +03:00
if ( doc ! = NULL )
dict = doc - > dict ;
ret = ( xmlElementContentPtr ) xmlMalloc ( sizeof ( xmlElementContent ) ) ;
2001-02-23 20:55:21 +03:00
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
2005-01-25 03:22:52 +03:00
memset ( ret , 0 , sizeof ( xmlElementContent ) ) ;
ret - > type = cur - > type ;
2001-02-23 20:55:21 +03:00
ret - > ocur = cur - > ocur ;
2005-01-25 03:22:52 +03:00
if ( cur - > name ! = NULL ) {
if ( dict )
ret - > name = xmlDictLookup ( dict , cur - > name , - 1 ) ;
else
ret - > name = xmlStrdup ( cur - > name ) ;
}
if ( cur - > prefix ! = NULL ) {
if ( dict )
ret - > prefix = xmlDictLookup ( dict , cur - > prefix , - 1 ) ;
else
ret - > prefix = xmlStrdup ( cur - > prefix ) ;
}
if ( cur - > c1 ! = NULL )
ret - > c1 = xmlCopyDocElementContent ( doc , cur - > c1 ) ;
2001-04-20 17:03:48 +04:00
if ( ret - > c1 ! = NULL )
ret - > c1 - > parent = ret ;
2005-01-25 03:22:52 +03:00
if ( cur - > c2 ! = NULL ) {
prev = ret ;
cur = cur - > c2 ;
while ( cur ! = NULL ) {
tmp = ( xmlElementContentPtr ) xmlMalloc ( sizeof ( xmlElementContent ) ) ;
if ( tmp = = NULL ) {
xmlVErrMemory ( NULL , " malloc failed " ) ;
return ( ret ) ;
}
memset ( tmp , 0 , sizeof ( xmlElementContent ) ) ;
tmp - > type = cur - > type ;
tmp - > ocur = cur - > ocur ;
prev - > c2 = tmp ;
if ( cur - > name ! = NULL ) {
if ( dict )
tmp - > name = xmlDictLookup ( dict , cur - > name , - 1 ) ;
else
tmp - > name = xmlStrdup ( cur - > name ) ;
}
if ( cur - > prefix ! = NULL ) {
if ( dict )
tmp - > prefix = xmlDictLookup ( dict , cur - > prefix , - 1 ) ;
else
tmp - > prefix = xmlStrdup ( cur - > prefix ) ;
}
if ( cur - > c1 ! = NULL )
tmp - > c1 = xmlCopyDocElementContent ( doc , cur - > c1 ) ;
if ( tmp - > c1 ! = NULL )
tmp - > c1 - > parent = ret ;
prev = tmp ;
cur = cur - > c2 ;
}
}
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2005-01-25 03:22:52 +03:00
/**
* xmlCopyElementContent :
* @ cur : An element content pointer .
*
* Build a copy of an element content description .
* Deprecated , use xmlCopyDocElementContent instead
*
* Returns the new xmlElementContentPtr or NULL in case of error .
*/
xmlElementContentPtr
xmlCopyElementContent ( xmlElementContentPtr cur ) {
return ( xmlCopyDocElementContent ( NULL , cur ) ) ;
}
/**
* xmlFreeDocElementContent :
* @ doc : the document owning the element declaration
* @ cur : the element content tree to free
*
* Free an element content structure . The whole subtree is removed .
*/
void
xmlFreeDocElementContent ( xmlDocPtr doc , xmlElementContentPtr cur ) {
xmlElementContentPtr next ;
xmlDictPtr dict = NULL ;
if ( doc ! = NULL )
dict = doc - > dict ;
while ( cur ! = NULL ) {
next = cur - > c2 ;
switch ( cur - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
case XML_ELEMENT_CONTENT_ELEMENT :
case XML_ELEMENT_CONTENT_SEQ :
case XML_ELEMENT_CONTENT_OR :
break ;
default :
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" Internal: ELEMENT content corrupted invalid type \n " ,
NULL ) ;
return ;
}
if ( cur - > c1 ! = NULL ) xmlFreeDocElementContent ( doc , cur - > c1 ) ;
if ( dict ) {
if ( ( cur - > name ! = NULL ) & & ( ! xmlDictOwns ( dict , cur - > name ) ) )
xmlFree ( ( xmlChar * ) cur - > name ) ;
if ( ( cur - > prefix ! = NULL ) & & ( ! xmlDictOwns ( dict , cur - > prefix ) ) )
xmlFree ( ( xmlChar * ) cur - > prefix ) ;
} else {
if ( cur - > name ! = NULL ) xmlFree ( ( xmlChar * ) cur - > name ) ;
if ( cur - > prefix ! = NULL ) xmlFree ( ( xmlChar * ) cur - > prefix ) ;
}
xmlFree ( cur ) ;
cur = next ;
}
}
2001-02-23 20:55:21 +03:00
/**
* xmlFreeElementContent :
* @ cur : the element content tree to free
*
2005-01-25 03:22:52 +03:00
* Free an element content structure . The whole subtree is removed .
* Deprecated , use xmlFreeDocElementContent instead
2001-02-23 20:55:21 +03:00
*/
void
xmlFreeElementContent ( xmlElementContentPtr cur ) {
2005-01-25 03:22:52 +03:00
xmlFreeDocElementContent ( NULL , cur ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlDumpElementContent :
* @ buf : An XML buffer
* @ content : An element table
* @ glob : 1 if one must print the englobing parenthesis , 0 otherwise
*
* This will dump the content of the element table as an XML DTD definition
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlDumpElementContent ( xmlBufferPtr buf , xmlElementContentPtr content , int glob ) {
if ( content = = NULL ) return ;
if ( glob ) xmlBufferWriteChar ( buf , " ( " ) ;
switch ( content - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
xmlBufferWriteChar ( buf , " #PCDATA " ) ;
break ;
case XML_ELEMENT_CONTENT_ELEMENT :
2001-11-09 02:36:42 +03:00
if ( content - > prefix ! = NULL ) {
xmlBufferWriteCHAR ( buf , content - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
2001-02-23 20:55:21 +03:00
xmlBufferWriteCHAR ( buf , content - > name ) ;
break ;
case XML_ELEMENT_CONTENT_SEQ :
if ( ( content - > c1 - > type = = XML_ELEMENT_CONTENT_OR ) | |
( content - > c1 - > type = = XML_ELEMENT_CONTENT_SEQ ) )
xmlDumpElementContent ( buf , content - > c1 , 1 ) ;
else
xmlDumpElementContent ( buf , content - > c1 , 0 ) ;
xmlBufferWriteChar ( buf , " , " ) ;
2004-06-24 06:24:44 +04:00
if ( ( content - > c2 - > type = = XML_ELEMENT_CONTENT_OR ) | |
( ( content - > c2 - > type = = XML_ELEMENT_CONTENT_SEQ ) & &
( content - > c2 - > ocur ! = XML_ELEMENT_CONTENT_ONCE ) ) )
2001-02-23 20:55:21 +03:00
xmlDumpElementContent ( buf , content - > c2 , 1 ) ;
else
xmlDumpElementContent ( buf , content - > c2 , 0 ) ;
break ;
case XML_ELEMENT_CONTENT_OR :
if ( ( content - > c1 - > type = = XML_ELEMENT_CONTENT_OR ) | |
( content - > c1 - > type = = XML_ELEMENT_CONTENT_SEQ ) )
xmlDumpElementContent ( buf , content - > c1 , 1 ) ;
else
xmlDumpElementContent ( buf , content - > c1 , 0 ) ;
xmlBufferWriteChar ( buf , " | " ) ;
2004-06-24 06:24:44 +04:00
if ( ( content - > c2 - > type = = XML_ELEMENT_CONTENT_SEQ ) | |
( ( content - > c2 - > type = = XML_ELEMENT_CONTENT_OR ) & &
( content - > c2 - > ocur ! = XML_ELEMENT_CONTENT_ONCE ) ) )
2001-02-23 20:55:21 +03:00
xmlDumpElementContent ( buf , content - > c2 , 1 ) ;
else
xmlDumpElementContent ( buf , content - > c2 , 0 ) ;
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" Internal: ELEMENT content corrupted invalid type \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
}
if ( glob )
xmlBufferWriteChar ( buf , " ) " ) ;
switch ( content - > ocur ) {
case XML_ELEMENT_CONTENT_ONCE :
break ;
case XML_ELEMENT_CONTENT_OPT :
xmlBufferWriteChar ( buf , " ? " ) ;
break ;
case XML_ELEMENT_CONTENT_MULT :
xmlBufferWriteChar ( buf , " * " ) ;
break ;
case XML_ELEMENT_CONTENT_PLUS :
xmlBufferWriteChar ( buf , " + " ) ;
break ;
}
}
/**
* xmlSprintfElementContent :
* @ buf : an output buffer
* @ content : An element table
2005-06-27 01:49:08 +04:00
* @ englob : 1 if one must print the englobing parenthesis , 0 otherwise
2001-02-23 20:55:21 +03:00
*
2001-08-15 16:06:36 +04:00
* Deprecated , unsafe , use xmlSnprintfElementContent
*/
void
xmlSprintfElementContent ( char * buf ATTRIBUTE_UNUSED ,
xmlElementContentPtr content ATTRIBUTE_UNUSED ,
2005-06-27 01:49:08 +04:00
int englob ATTRIBUTE_UNUSED ) {
2001-08-15 16:06:36 +04:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-08-15 16:06:36 +04:00
/**
* xmlSnprintfElementContent :
* @ buf : an output buffer
* @ size : the buffer size
* @ content : An element table
2005-06-27 01:49:08 +04:00
* @ englob : 1 if one must print the englobing parenthesis , 0 otherwise
2001-08-15 16:06:36 +04:00
*
2001-02-23 20:55:21 +03:00
* This will dump the content of the element content definition
* Intended just for the debug routine
*/
void
2005-06-27 01:49:08 +04:00
xmlSnprintfElementContent ( char * buf , int size , xmlElementContentPtr content , int englob ) {
2001-08-15 16:06:36 +04:00
int len ;
2001-02-23 20:55:21 +03:00
if ( content = = NULL ) return ;
2001-08-15 16:06:36 +04:00
len = strlen ( buf ) ;
if ( size - len < 50 ) {
if ( ( size - len > 4 ) & & ( buf [ len - 1 ] ! = ' . ' ) )
strcat ( buf , " ... " ) ;
return ;
}
2005-06-27 01:49:08 +04:00
if ( englob ) strcat ( buf , " ( " ) ;
2001-02-23 20:55:21 +03:00
switch ( content - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
strcat ( buf , " #PCDATA " ) ;
break ;
case XML_ELEMENT_CONTENT_ELEMENT :
2001-11-09 02:36:42 +03:00
if ( content - > prefix ! = NULL ) {
2002-03-19 17:36:46 +03:00
if ( size - len < xmlStrlen ( content - > prefix ) + 10 ) {
2001-11-09 02:36:42 +03:00
strcat ( buf , " ... " ) ;
return ;
}
strcat ( buf , ( char * ) content - > prefix ) ;
strcat ( buf , " : " ) ;
}
2002-03-19 17:36:46 +03:00
if ( size - len < xmlStrlen ( content - > name ) + 10 ) {
2001-08-15 16:06:36 +04:00
strcat ( buf , " ... " ) ;
return ;
}
2003-04-24 20:06:47 +04:00
if ( content - > name ! = NULL )
strcat ( buf , ( char * ) content - > name ) ;
2001-02-23 20:55:21 +03:00
break ;
case XML_ELEMENT_CONTENT_SEQ :
if ( ( content - > c1 - > type = = XML_ELEMENT_CONTENT_OR ) | |
( content - > c1 - > type = = XML_ELEMENT_CONTENT_SEQ ) )
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c1 , 1 ) ;
2001-02-23 20:55:21 +03:00
else
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c1 , 0 ) ;
len = strlen ( buf ) ;
if ( size - len < 50 ) {
if ( ( size - len > 4 ) & & ( buf [ len - 1 ] ! = ' . ' ) )
strcat ( buf , " ... " ) ;
return ;
}
2001-02-23 20:55:21 +03:00
strcat ( buf , " , " ) ;
2002-09-18 20:29:02 +04:00
if ( ( ( content - > c2 - > type = = XML_ELEMENT_CONTENT_OR ) | |
( content - > c2 - > ocur ! = XML_ELEMENT_CONTENT_ONCE ) ) & &
( content - > c2 - > type ! = XML_ELEMENT_CONTENT_ELEMENT ) )
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c2 , 1 ) ;
2001-02-23 20:55:21 +03:00
else
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c2 , 0 ) ;
2001-02-23 20:55:21 +03:00
break ;
case XML_ELEMENT_CONTENT_OR :
if ( ( content - > c1 - > type = = XML_ELEMENT_CONTENT_OR ) | |
( content - > c1 - > type = = XML_ELEMENT_CONTENT_SEQ ) )
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c1 , 1 ) ;
2001-02-23 20:55:21 +03:00
else
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c1 , 0 ) ;
len = strlen ( buf ) ;
if ( size - len < 50 ) {
if ( ( size - len > 4 ) & & ( buf [ len - 1 ] ! = ' . ' ) )
strcat ( buf , " ... " ) ;
return ;
}
2001-02-23 20:55:21 +03:00
strcat ( buf , " | " ) ;
2002-09-18 20:29:02 +04:00
if ( ( ( content - > c2 - > type = = XML_ELEMENT_CONTENT_SEQ ) | |
( content - > c2 - > ocur ! = XML_ELEMENT_CONTENT_ONCE ) ) & &
( content - > c2 - > type ! = XML_ELEMENT_CONTENT_ELEMENT ) )
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c2 , 1 ) ;
2001-02-23 20:55:21 +03:00
else
2001-08-15 16:06:36 +04:00
xmlSnprintfElementContent ( buf , size , content - > c2 , 0 ) ;
2001-02-23 20:55:21 +03:00
break ;
}
2005-06-27 01:49:08 +04:00
if ( englob )
2001-02-23 20:55:21 +03:00
strcat ( buf , " ) " ) ;
switch ( content - > ocur ) {
case XML_ELEMENT_CONTENT_ONCE :
break ;
case XML_ELEMENT_CONTENT_OPT :
strcat ( buf , " ? " ) ;
break ;
case XML_ELEMENT_CONTENT_MULT :
strcat ( buf , " * " ) ;
break ;
case XML_ELEMENT_CONTENT_PLUS :
strcat ( buf , " + " ) ;
break ;
}
}
/****************************************************************
* *
* Registration of DTD declarations *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlFreeElement :
* @ elem : An element
*
* Deallocate the memory used by an element definition
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlFreeElement ( xmlElementPtr elem ) {
if ( elem = = NULL ) return ;
xmlUnlinkNode ( ( xmlNodePtr ) elem ) ;
2005-01-25 03:22:52 +03:00
xmlFreeDocElementContent ( elem - > doc , elem - > content ) ;
2001-02-23 20:55:21 +03:00
if ( elem - > name ! = NULL )
xmlFree ( ( xmlChar * ) elem - > name ) ;
if ( elem - > prefix ! = NULL )
xmlFree ( ( xmlChar * ) elem - > prefix ) ;
2002-09-16 14:51:38 +04:00
# ifdef LIBXML_REGEXP_ENABLED
if ( elem - > contModel ! = NULL )
xmlRegFreeRegexp ( elem - > contModel ) ;
# endif
2001-02-23 20:55:21 +03:00
xmlFree ( elem ) ;
}
/**
* xmlAddElementDecl :
* @ ctxt : the validation context
* @ dtd : pointer to the DTD
* @ name : the entity name
* @ type : the element type
* @ content : the element content tree or NULL
*
* Register a new element declaration
*
2001-12-31 19:16:02 +03:00
* Returns NULL if not , otherwise the entity
2001-02-23 20:55:21 +03:00
*/
xmlElementPtr
2004-02-06 10:36:04 +03:00
xmlAddElementDecl ( xmlValidCtxtPtr ctxt ,
2003-09-29 17:20:24 +04:00
xmlDtdPtr dtd , const xmlChar * name ,
2001-02-23 20:55:21 +03:00
xmlElementTypeVal type ,
xmlElementContentPtr content ) {
xmlElementPtr ret ;
xmlElementTablePtr table ;
2001-04-18 17:09:01 +04:00
xmlAttributePtr oldAttributes = NULL ;
2001-02-23 20:55:21 +03:00
xmlChar * ns , * uqname ;
if ( dtd = = NULL ) {
return ( NULL ) ;
}
if ( name = = NULL ) {
return ( NULL ) ;
}
2005-01-24 01:56:39 +03:00
2001-02-23 20:55:21 +03:00
switch ( type ) {
case XML_ELEMENT_TYPE_EMPTY :
if ( content ! = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" xmlAddElementDecl: content != NULL for EMPTY \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
break ;
case XML_ELEMENT_TYPE_ANY :
if ( content ! = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" xmlAddElementDecl: content != NULL for ANY \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
break ;
case XML_ELEMENT_TYPE_MIXED :
if ( content = = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" xmlAddElementDecl: content == NULL for MIXED \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
break ;
case XML_ELEMENT_TYPE_ELEMENT :
if ( content = = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" xmlAddElementDecl: content == NULL for ELEMENT \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" Internal: ELEMENT decl corrupted invalid type \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
/*
* check if name is a QName
*/
uqname = xmlSplitQName2 ( name , & ns ) ;
if ( uqname ! = NULL )
name = uqname ;
/*
* Create the Element table if needed .
*/
table = ( xmlElementTablePtr ) dtd - > elements ;
if ( table = = NULL ) {
2005-01-24 01:56:39 +03:00
xmlDictPtr dict = NULL ;
if ( dtd - > doc ! = NULL )
dict = dtd - > doc - > dict ;
table = xmlHashCreateDict ( 0 , dict ) ;
2001-02-23 20:55:21 +03:00
dtd - > elements = ( void * ) table ;
}
if ( table = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt ,
2003-10-03 02:28:19 +04:00
" xmlAddElementDecl: Table creation failed! \n " ) ;
2003-04-24 20:06:47 +04:00
if ( uqname ! = NULL )
xmlFree ( uqname ) ;
if ( ns ! = NULL )
xmlFree ( ns ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
/*
2001-04-18 17:09:01 +04:00
* lookup old attributes inserted on an undefined element in the
* internal subset .
2001-02-23 20:55:21 +03:00
*/
2001-04-18 17:09:01 +04:00
if ( ( dtd - > doc ! = NULL ) & & ( dtd - > doc - > intSubset ! = NULL ) ) {
ret = xmlHashLookup2 ( dtd - > doc - > intSubset - > elements , name , ns ) ;
if ( ( ret ! = NULL ) & & ( ret - > etype = = XML_ELEMENT_TYPE_UNDEFINED ) ) {
oldAttributes = ret - > attributes ;
ret - > attributes = NULL ;
xmlHashRemoveEntry2 ( dtd - > doc - > intSubset - > elements , name , ns , NULL ) ;
xmlFreeElement ( ret ) ;
}
}
2001-02-23 20:55:21 +03:00
/*
2001-04-18 17:09:01 +04:00
* The element may already be present if one of its attribute
* was registered first
2001-02-23 20:55:21 +03:00
*/
2001-04-18 17:09:01 +04:00
ret = xmlHashLookup2 ( table , name , ns ) ;
if ( ret ! = NULL ) {
if ( ret - > etype ! = XML_ELEMENT_TYPE_UNDEFINED ) {
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-04-18 17:09:01 +04:00
/*
2001-12-31 19:16:02 +03:00
* The element is already defined in this DTD .
2001-04-18 17:09:01 +04:00
*/
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) dtd , XML_DTD_ELEM_REDEFINED ,
" Redefinition of element %s \n " ,
name , NULL , NULL ) ;
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-04-18 17:09:01 +04:00
if ( uqname ! = NULL )
xmlFree ( uqname ) ;
2003-04-24 20:06:47 +04:00
if ( ns ! = NULL )
xmlFree ( ns ) ;
2001-04-18 17:09:01 +04:00
return ( NULL ) ;
}
2005-04-15 05:34:41 +04:00
if ( ns ! = NULL ) {
xmlFree ( ns ) ;
ns = NULL ;
}
2001-04-18 17:09:01 +04:00
} else {
ret = ( xmlElementPtr ) xmlMalloc ( sizeof ( xmlElement ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2003-04-24 20:06:47 +04:00
if ( uqname ! = NULL )
xmlFree ( uqname ) ;
if ( ns ! = NULL )
xmlFree ( ns ) ;
2001-04-18 17:09:01 +04:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlElement ) ) ;
ret - > type = XML_ELEMENT_DECL ;
2001-02-23 20:55:21 +03:00
/*
2001-04-18 17:09:01 +04:00
* fill the structure .
2001-02-23 20:55:21 +03:00
*/
2001-04-18 17:09:01 +04:00
ret - > name = xmlStrdup ( name ) ;
2003-04-24 20:06:47 +04:00
if ( ret - > name = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2003-04-24 20:06:47 +04:00
if ( uqname ! = NULL )
xmlFree ( uqname ) ;
if ( ns ! = NULL )
xmlFree ( ns ) ;
xmlFree ( ret ) ;
return ( NULL ) ;
}
2001-04-18 17:09:01 +04:00
ret - > prefix = ns ;
/*
* Validity Check :
* Insertion must not fail
*/
if ( xmlHashAddEntry2 ( table , name , ns , ret ) ) {
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-04-18 17:09:01 +04:00
/*
2001-12-31 19:16:02 +03:00
* The element is already defined in this DTD .
2001-04-18 17:09:01 +04:00
*/
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) dtd , XML_DTD_ELEM_REDEFINED ,
" Redefinition of element %s \n " ,
name , NULL , NULL ) ;
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-04-18 17:09:01 +04:00
xmlFreeElement ( ret ) ;
if ( uqname ! = NULL )
xmlFree ( uqname ) ;
return ( NULL ) ;
}
2003-09-14 22:07:39 +04:00
/*
* For new element , may have attributes from earlier
* definition in internal subset
*/
ret - > attributes = oldAttributes ;
2001-02-23 20:55:21 +03:00
}
2001-04-18 17:09:01 +04:00
/*
* Finish to fill the structure .
*/
ret - > etype = type ;
2005-01-25 03:22:52 +03:00
/*
* Avoid a stupid copy when called by the parser
* and flag it by setting a special parent value
* so the parser doesn ' t unallocate it .
*/
2005-01-26 03:04:52 +03:00
if ( ( ctxt ! = NULL ) & &
( ( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_0 ) | |
( ctxt - > finishDtd = = XML_CTXT_FINISH_DTD_1 ) ) ) {
2005-01-25 03:22:52 +03:00
ret - > content = content ;
if ( content ! = NULL )
content - > parent = ( xmlElementContentPtr ) 1 ;
} else {
ret - > content = xmlCopyDocElementContent ( dtd - > doc , content ) ;
}
2001-04-18 17:09:01 +04:00
2001-02-23 20:55:21 +03:00
/*
2001-12-31 19:16:02 +03:00
* Link it to the DTD
2001-02-23 20:55:21 +03:00
*/
ret - > parent = dtd ;
ret - > doc = dtd - > doc ;
if ( dtd - > last = = NULL ) {
dtd - > children = dtd - > last = ( xmlNodePtr ) ret ;
} else {
dtd - > last - > next = ( xmlNodePtr ) ret ;
ret - > prev = dtd - > last ;
dtd - > last = ( xmlNodePtr ) ret ;
}
if ( uqname ! = NULL )
xmlFree ( uqname ) ;
return ( ret ) ;
}
/**
* xmlFreeElementTable :
* @ table : An element table
*
* Deallocate the memory used by an element hash table .
*/
void
xmlFreeElementTable ( xmlElementTablePtr table ) {
xmlHashFree ( table , ( xmlHashDeallocator ) xmlFreeElement ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlCopyElement :
* @ elem : An element
*
* Build a copy of an element .
*
* Returns the new xmlElementPtr or NULL in case of error .
*/
2001-03-24 20:00:36 +03:00
static xmlElementPtr
2001-02-23 20:55:21 +03:00
xmlCopyElement ( xmlElementPtr elem ) {
xmlElementPtr cur ;
cur = ( xmlElementPtr ) xmlMalloc ( sizeof ( xmlElement ) ) ;
if ( cur = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlElement ) ) ;
cur - > type = XML_ELEMENT_DECL ;
cur - > etype = elem - > etype ;
if ( elem - > name ! = NULL )
cur - > name = xmlStrdup ( elem - > name ) ;
else
cur - > name = NULL ;
if ( elem - > prefix ! = NULL )
cur - > prefix = xmlStrdup ( elem - > prefix ) ;
else
cur - > prefix = NULL ;
cur - > content = xmlCopyElementContent ( elem - > content ) ;
/* TODO : rebuild the attribute list on the copy */
cur - > attributes = NULL ;
return ( cur ) ;
}
/**
* xmlCopyElementTable :
* @ table : An element table
*
* Build a copy of an element table .
*
* Returns the new xmlElementTablePtr or NULL in case of error .
*/
xmlElementTablePtr
xmlCopyElementTable ( xmlElementTablePtr table ) {
return ( ( xmlElementTablePtr ) xmlHashCopy ( table ,
( xmlHashCopier ) xmlCopyElement ) ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlDumpElementDecl :
* @ buf : the XML buffer output
* @ elem : An element table
*
* This will dump the content of the element declaration as an XML
* DTD definition
*/
void
xmlDumpElementDecl ( xmlBufferPtr buf , xmlElementPtr elem ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( elem = = NULL ) )
return ;
2001-02-23 20:55:21 +03:00
switch ( elem - > etype ) {
case XML_ELEMENT_TYPE_EMPTY :
xmlBufferWriteChar ( buf , " <!ELEMENT " ) ;
2001-11-09 02:36:42 +03:00
if ( elem - > prefix ! = NULL ) {
xmlBufferWriteCHAR ( buf , elem - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
2001-02-23 20:55:21 +03:00
xmlBufferWriteCHAR ( buf , elem - > name ) ;
xmlBufferWriteChar ( buf , " EMPTY> \n " ) ;
break ;
case XML_ELEMENT_TYPE_ANY :
xmlBufferWriteChar ( buf , " <!ELEMENT " ) ;
2001-11-09 02:36:42 +03:00
if ( elem - > prefix ! = NULL ) {
xmlBufferWriteCHAR ( buf , elem - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
2001-02-23 20:55:21 +03:00
xmlBufferWriteCHAR ( buf , elem - > name ) ;
xmlBufferWriteChar ( buf , " ANY> \n " ) ;
break ;
case XML_ELEMENT_TYPE_MIXED :
xmlBufferWriteChar ( buf , " <!ELEMENT " ) ;
2001-11-09 02:36:42 +03:00
if ( elem - > prefix ! = NULL ) {
xmlBufferWriteCHAR ( buf , elem - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
2001-02-23 20:55:21 +03:00
xmlBufferWriteCHAR ( buf , elem - > name ) ;
xmlBufferWriteChar ( buf , " " ) ;
xmlDumpElementContent ( buf , elem - > content , 1 ) ;
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
case XML_ELEMENT_TYPE_ELEMENT :
xmlBufferWriteChar ( buf , " <!ELEMENT " ) ;
2001-11-09 02:36:42 +03:00
if ( elem - > prefix ! = NULL ) {
xmlBufferWriteCHAR ( buf , elem - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
2001-02-23 20:55:21 +03:00
xmlBufferWriteCHAR ( buf , elem - > name ) ;
xmlBufferWriteChar ( buf , " " ) ;
xmlDumpElementContent ( buf , elem - > content , 1 ) ;
xmlBufferWriteChar ( buf , " > \n " ) ;
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" Internal: ELEMENT struct corrupted invalid type \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
}
}
2003-10-20 18:56:06 +04:00
/**
* xmlDumpElementDeclScan :
* @ elem : An element table
* @ buf : the XML buffer output
*
* This routine is used by the hash scan function . It just reverses
* the arguments .
*/
static void
xmlDumpElementDeclScan ( xmlElementPtr elem , xmlBufferPtr buf ) {
xmlDumpElementDecl ( buf , elem ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlDumpElementTable :
* @ buf : the XML buffer output
* @ table : An element table
*
* This will dump the content of the element table as an XML DTD definition
*/
void
xmlDumpElementTable ( xmlBufferPtr buf , xmlElementTablePtr table ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( table = = NULL ) )
return ;
2003-10-20 18:56:06 +04:00
xmlHashScan ( table , ( xmlHashScanner ) xmlDumpElementDeclScan , buf ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlCreateEnumeration :
* @ name : the enumeration name or NULL
*
* create and initialize an enumeration attribute node .
*
* Returns the xmlEnumerationPtr just created or NULL in case
* of error .
*/
xmlEnumerationPtr
2003-08-18 16:15:38 +04:00
xmlCreateEnumeration ( const xmlChar * name ) {
2001-02-23 20:55:21 +03:00
xmlEnumerationPtr ret ;
ret = ( xmlEnumerationPtr ) xmlMalloc ( sizeof ( xmlEnumeration ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlEnumeration ) ) ;
if ( name ! = NULL )
ret - > name = xmlStrdup ( name ) ;
return ( ret ) ;
}
/**
* xmlFreeEnumeration :
* @ cur : the tree to free .
*
* free an enumeration attribute node ( recursive ) .
*/
void
xmlFreeEnumeration ( xmlEnumerationPtr cur ) {
if ( cur = = NULL ) return ;
if ( cur - > next ! = NULL ) xmlFreeEnumeration ( cur - > next ) ;
if ( cur - > name ! = NULL ) xmlFree ( ( xmlChar * ) cur - > name ) ;
xmlFree ( cur ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlCopyEnumeration :
* @ cur : the tree to copy .
*
* Copy an enumeration attribute node ( recursive ) .
*
* Returns the xmlEnumerationPtr just created or NULL in case
* of error .
*/
xmlEnumerationPtr
xmlCopyEnumeration ( xmlEnumerationPtr cur ) {
xmlEnumerationPtr ret ;
if ( cur = = NULL ) return ( NULL ) ;
ret = xmlCreateEnumeration ( ( xmlChar * ) cur - > name ) ;
if ( cur - > next ! = NULL ) ret - > next = xmlCopyEnumeration ( cur - > next ) ;
else ret - > next = NULL ;
return ( ret ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlDumpEnumeration :
* @ buf : the XML buffer output
* @ enum : An enumeration
*
* This will dump the content of the enumeration
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlDumpEnumeration ( xmlBufferPtr buf , xmlEnumerationPtr cur ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( cur = = NULL ) )
return ;
2001-02-23 20:55:21 +03:00
xmlBufferWriteCHAR ( buf , cur - > name ) ;
if ( cur - > next = = NULL )
xmlBufferWriteChar ( buf , " ) " ) ;
else {
xmlBufferWriteChar ( buf , " | " ) ;
xmlDumpEnumeration ( buf , cur - > next ) ;
}
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlScanAttributeDeclCallback :
* @ attr : the attribute decl
* @ list : the list to update
*
* Callback called by xmlScanAttributeDecl when a new attribute
* has to be entered in the list .
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlScanAttributeDeclCallback ( xmlAttributePtr attr , xmlAttributePtr * list ,
2001-03-26 20:28:29 +04:00
const xmlChar * name ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
attr - > nexth = * list ;
* list = attr ;
}
/**
* xmlScanAttributeDecl :
* @ dtd : pointer to the DTD
* @ elem : the element name
*
* When inserting a new element scan the DtD for existing attributes
2001-12-31 19:16:02 +03:00
* for that element and initialize the Attribute chain
2001-02-23 20:55:21 +03:00
*
* Returns the pointer to the first attribute decl in the chain ,
* possibly NULL .
*/
xmlAttributePtr
xmlScanAttributeDecl ( xmlDtdPtr dtd , const xmlChar * elem ) {
xmlAttributePtr ret = NULL ;
xmlAttributeTablePtr table ;
if ( dtd = = NULL ) {
return ( NULL ) ;
}
if ( elem = = NULL ) {
return ( NULL ) ;
}
table = ( xmlAttributeTablePtr ) dtd - > attributes ;
if ( table = = NULL )
return ( NULL ) ;
/* WRONG !!! */
xmlHashScan3 ( table , NULL , NULL , elem ,
( xmlHashScanner ) xmlScanAttributeDeclCallback , & ret ) ;
return ( ret ) ;
}
/**
* xmlScanIDAttributeDecl :
* @ ctxt : the validation context
* @ elem : the element name
2005-06-27 17:42:57 +04:00
* @ err : whether to raise errors here
2001-02-23 20:55:21 +03:00
*
* Verify that the element don ' t have too many ID attributes
* declared .
*
* Returns the number of ID attributes found .
*/
2001-03-24 20:00:36 +03:00
static int
2005-06-27 17:42:57 +04:00
xmlScanIDAttributeDecl ( xmlValidCtxtPtr ctxt , xmlElementPtr elem , int err ) {
2001-02-23 20:55:21 +03:00
xmlAttributePtr cur ;
int ret = 0 ;
if ( elem = = NULL ) return ( 0 ) ;
cur = elem - > attributes ;
while ( cur ! = NULL ) {
if ( cur - > atype = = XML_ATTRIBUTE_ID ) {
ret + + ;
2005-06-27 17:42:57 +04:00
if ( ( ret > 1 ) & & ( err ) )
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_MULTIPLE_ID ,
2001-04-18 17:09:01 +04:00
" Element %s has too many ID attributes defined : %s \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , cur - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
}
cur = cur - > nexth ;
}
return ( ret ) ;
}
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlFreeAttribute :
* @ elem : An attribute
*
* Deallocate the memory used by an attribute definition
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlFreeAttribute ( xmlAttributePtr attr ) {
2005-01-25 03:22:52 +03:00
xmlDictPtr dict ;
2001-02-23 20:55:21 +03:00
if ( attr = = NULL ) return ;
2005-01-25 03:22:52 +03:00
if ( attr - > doc ! = NULL )
dict = attr - > doc - > dict ;
else
dict = NULL ;
2001-02-23 20:55:21 +03:00
xmlUnlinkNode ( ( xmlNodePtr ) attr ) ;
if ( attr - > tree ! = NULL )
xmlFreeEnumeration ( attr - > tree ) ;
2005-01-25 03:22:52 +03:00
if ( dict ) {
if ( ( attr - > elem ! = NULL ) & & ( ! xmlDictOwns ( dict , attr - > elem ) ) )
xmlFree ( ( xmlChar * ) attr - > elem ) ;
if ( ( attr - > name ! = NULL ) & & ( ! xmlDictOwns ( dict , attr - > name ) ) )
xmlFree ( ( xmlChar * ) attr - > name ) ;
if ( ( attr - > prefix ! = NULL ) & & ( ! xmlDictOwns ( dict , attr - > prefix ) ) )
xmlFree ( ( xmlChar * ) attr - > prefix ) ;
if ( ( attr - > defaultValue ! = NULL ) & &
( ! xmlDictOwns ( dict , attr - > defaultValue ) ) )
xmlFree ( ( xmlChar * ) attr - > defaultValue ) ;
} else {
if ( attr - > elem ! = NULL )
xmlFree ( ( xmlChar * ) attr - > elem ) ;
if ( attr - > name ! = NULL )
xmlFree ( ( xmlChar * ) attr - > name ) ;
if ( attr - > defaultValue ! = NULL )
xmlFree ( ( xmlChar * ) attr - > defaultValue ) ;
if ( attr - > prefix ! = NULL )
xmlFree ( ( xmlChar * ) attr - > prefix ) ;
}
2001-02-23 20:55:21 +03:00
xmlFree ( attr ) ;
}
/**
* xmlAddAttributeDecl :
* @ ctxt : the validation context
* @ dtd : pointer to the DTD
* @ elem : the element name
* @ name : the attribute name
* @ ns : the attribute namespace prefix
* @ type : the attribute type
* @ def : the attribute default type
* @ defaultValue : the attribute default value
* @ tree : if it ' s an enumeration , the associated list
*
* Register a new attribute declaration
* Note that @ tree becomes the ownership of the DTD
*
2001-12-31 19:16:02 +03:00
* Returns NULL if not new , otherwise the attribute decl
2001-02-23 20:55:21 +03:00
*/
xmlAttributePtr
2004-02-06 10:36:04 +03:00
xmlAddAttributeDecl ( xmlValidCtxtPtr ctxt ,
2003-09-29 17:20:24 +04:00
xmlDtdPtr dtd , const xmlChar * elem ,
2001-02-23 20:55:21 +03:00
const xmlChar * name , const xmlChar * ns ,
xmlAttributeType type , xmlAttributeDefault def ,
const xmlChar * defaultValue , xmlEnumerationPtr tree ) {
xmlAttributePtr ret ;
xmlAttributeTablePtr table ;
xmlElementPtr elemDef ;
2005-01-25 03:22:52 +03:00
xmlDictPtr dict = NULL ;
2001-02-23 20:55:21 +03:00
if ( dtd = = NULL ) {
xmlFreeEnumeration ( tree ) ;
return ( NULL ) ;
}
if ( name = = NULL ) {
xmlFreeEnumeration ( tree ) ;
return ( NULL ) ;
}
if ( elem = = NULL ) {
xmlFreeEnumeration ( tree ) ;
return ( NULL ) ;
}
2005-01-25 03:22:52 +03:00
if ( dtd - > doc ! = NULL )
dict = dtd - > doc - > dict ;
2002-03-25 13:48:46 +03:00
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-02-23 20:55:21 +03:00
/*
* Check the type and possibly the default value .
*/
switch ( type ) {
case XML_ATTRIBUTE_CDATA :
break ;
case XML_ATTRIBUTE_ID :
break ;
case XML_ATTRIBUTE_IDREF :
break ;
case XML_ATTRIBUTE_IDREFS :
break ;
case XML_ATTRIBUTE_ENTITY :
break ;
case XML_ATTRIBUTE_ENTITIES :
break ;
case XML_ATTRIBUTE_NMTOKEN :
break ;
case XML_ATTRIBUTE_NMTOKENS :
break ;
case XML_ATTRIBUTE_ENUMERATION :
break ;
case XML_ATTRIBUTE_NOTATION :
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
" Internal: ATTRIBUTE struct corrupted invalid type \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
xmlFreeEnumeration ( tree ) ;
return ( NULL ) ;
}
if ( ( defaultValue ! = NULL ) & &
( ! xmlValidateAttributeValue ( type , defaultValue ) ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) dtd , XML_DTD_ATTRIBUTE_DEFAULT ,
" Attribute %s of %s: invalid default value \n " ,
elem , name , defaultValue ) ;
2001-02-23 20:55:21 +03:00
defaultValue = NULL ;
2004-11-08 13:52:06 +03:00
if ( ctxt ! = NULL )
ctxt - > valid = 0 ;
2001-02-23 20:55:21 +03:00
}
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-02-23 20:55:21 +03:00
2002-03-25 13:48:46 +03:00
/*
* Check first that an attribute defined in the external subset wasn ' t
* already defined in the internal subset
*/
if ( ( dtd - > doc ! = NULL ) & & ( dtd - > doc - > extSubset = = dtd ) & &
( dtd - > doc - > intSubset ! = NULL ) & &
( dtd - > doc - > intSubset - > attributes ! = NULL ) ) {
ret = xmlHashLookup3 ( dtd - > doc - > intSubset - > attributes , name , ns , elem ) ;
if ( ret ! = NULL )
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
/*
* Create the Attribute table if needed .
*/
table = ( xmlAttributeTablePtr ) dtd - > attributes ;
if ( table = = NULL ) {
2005-01-24 01:56:39 +03:00
table = xmlHashCreateDict ( 0 , dict ) ;
2001-02-23 20:55:21 +03:00
dtd - > attributes = ( void * ) table ;
}
if ( table = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt ,
2003-10-03 02:28:19 +04:00
" xmlAddAttributeDecl: Table creation failed! \n " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
ret = ( xmlAttributePtr ) xmlMalloc ( sizeof ( xmlAttribute ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlAttribute ) ) ;
ret - > type = XML_ATTRIBUTE_DECL ;
/*
* fill the structure .
*/
ret - > atype = type ;
2005-07-07 02:48:41 +04:00
/*
* doc must be set before possible error causes call
* to xmlFreeAttribute ( because it ' s used to check on
* dict use )
*/
ret - > doc = dtd - > doc ;
2005-01-25 03:22:52 +03:00
if ( dict ) {
ret - > name = xmlDictLookup ( dict , name , - 1 ) ;
ret - > prefix = xmlDictLookup ( dict , ns , - 1 ) ;
ret - > elem = xmlDictLookup ( dict , elem , - 1 ) ;
} else {
ret - > name = xmlStrdup ( name ) ;
ret - > prefix = xmlStrdup ( ns ) ;
ret - > elem = xmlStrdup ( elem ) ;
}
2001-02-23 20:55:21 +03:00
ret - > def = def ;
ret - > tree = tree ;
2005-01-25 03:22:52 +03:00
if ( defaultValue ! = NULL ) {
if ( dict )
ret - > defaultValue = xmlDictLookup ( dict , defaultValue , - 1 ) ;
else
ret - > defaultValue = xmlStrdup ( defaultValue ) ;
}
2001-02-23 20:55:21 +03:00
/*
* Validity Check :
* Search the DTD for previous declarations of the ATTLIST
*/
2005-01-25 03:22:52 +03:00
if ( xmlHashAddEntry3 ( table , ret - > name , ret - > prefix , ret - > elem , ret ) < 0 ) {
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-02-23 20:55:21 +03:00
/*
2001-12-31 19:16:02 +03:00
* The attribute is already defined in this DTD .
2001-02-23 20:55:21 +03:00
*/
2003-10-04 02:21:51 +04:00
xmlErrValidWarning ( ctxt , ( xmlNodePtr ) dtd , XML_DTD_ATTRIBUTE_REDEFINED ,
2002-08-03 02:19:49 +04:00
" Attribute %s of element %s: already defined \n " ,
2003-10-04 02:21:51 +04:00
name , elem , NULL ) ;
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-02-23 20:55:21 +03:00
xmlFreeAttribute ( ret ) ;
return ( NULL ) ;
}
/*
* Validity Check :
* Multiple ID per element
*/
2001-04-18 17:09:01 +04:00
elemDef = xmlGetDtdElementDesc2 ( dtd , elem , 1 ) ;
2001-02-23 20:55:21 +03:00
if ( elemDef ! = NULL ) {
2001-08-07 05:10:10 +04:00
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-02-23 20:55:21 +03:00
if ( ( type = = XML_ATTRIBUTE_ID ) & &
2005-06-27 17:42:57 +04:00
( xmlScanIDAttributeDecl ( NULL , elemDef , 1 ) ! = 0 ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) dtd , XML_DTD_MULTIPLE_ID ,
2001-02-23 20:55:21 +03:00
" Element %s has too may ID attributes defined : %s \n " ,
2003-10-04 02:21:51 +04:00
elem , name , NULL ) ;
2004-11-08 13:52:06 +03:00
if ( ctxt ! = NULL )
ctxt - > valid = 0 ;
2002-02-18 01:47:37 +03:00
}
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2002-02-18 01:47:37 +03:00
2001-08-07 05:10:10 +04:00
/*
* Insert namespace default def first they need to be
2001-12-31 19:16:02 +03:00
* processed first .
2001-08-07 05:10:10 +04:00
*/
if ( ( xmlStrEqual ( ret - > name , BAD_CAST " xmlns " ) ) | |
( ( ret - > prefix ! = NULL & &
( xmlStrEqual ( ret - > prefix , BAD_CAST " xmlns " ) ) ) ) ) {
ret - > nexth = elemDef - > attributes ;
elemDef - > attributes = ret ;
} else {
xmlAttributePtr tmp = elemDef - > attributes ;
while ( ( tmp ! = NULL ) & &
( ( xmlStrEqual ( tmp - > name , BAD_CAST " xmlns " ) ) | |
( ( ret - > prefix ! = NULL & &
( xmlStrEqual ( ret - > prefix , BAD_CAST " xmlns " ) ) ) ) ) ) {
if ( tmp - > nexth = = NULL )
break ;
tmp = tmp - > nexth ;
}
if ( tmp ! = NULL ) {
ret - > nexth = tmp - > nexth ;
tmp - > nexth = ret ;
} else {
ret - > nexth = elemDef - > attributes ;
elemDef - > attributes = ret ;
}
}
2001-02-23 20:55:21 +03:00
}
/*
2001-12-31 19:16:02 +03:00
* Link it to the DTD
2001-02-23 20:55:21 +03:00
*/
ret - > parent = dtd ;
if ( dtd - > last = = NULL ) {
dtd - > children = dtd - > last = ( xmlNodePtr ) ret ;
} else {
dtd - > last - > next = ( xmlNodePtr ) ret ;
ret - > prev = dtd - > last ;
dtd - > last = ( xmlNodePtr ) ret ;
}
return ( ret ) ;
}
/**
* xmlFreeAttributeTable :
* @ table : An attribute table
*
* Deallocate the memory used by an entities hash table .
*/
void
xmlFreeAttributeTable ( xmlAttributeTablePtr table ) {
xmlHashFree ( table , ( xmlHashDeallocator ) xmlFreeAttribute ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlCopyAttribute :
* @ attr : An attribute
*
* Build a copy of an attribute .
*
* Returns the new xmlAttributePtr or NULL in case of error .
*/
2001-03-24 20:00:36 +03:00
static xmlAttributePtr
2001-02-23 20:55:21 +03:00
xmlCopyAttribute ( xmlAttributePtr attr ) {
xmlAttributePtr cur ;
cur = ( xmlAttributePtr ) xmlMalloc ( sizeof ( xmlAttribute ) ) ;
if ( cur = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlAttribute ) ) ;
2002-01-24 18:02:46 +03:00
cur - > type = XML_ATTRIBUTE_DECL ;
2001-02-23 20:55:21 +03:00
cur - > atype = attr - > atype ;
cur - > def = attr - > def ;
cur - > tree = xmlCopyEnumeration ( attr - > tree ) ;
if ( attr - > elem ! = NULL )
cur - > elem = xmlStrdup ( attr - > elem ) ;
if ( attr - > name ! = NULL )
cur - > name = xmlStrdup ( attr - > name ) ;
2002-01-24 18:02:46 +03:00
if ( attr - > prefix ! = NULL )
cur - > prefix = xmlStrdup ( attr - > prefix ) ;
2001-02-23 20:55:21 +03:00
if ( attr - > defaultValue ! = NULL )
cur - > defaultValue = xmlStrdup ( attr - > defaultValue ) ;
return ( cur ) ;
}
/**
* xmlCopyAttributeTable :
* @ table : An attribute table
*
* Build a copy of an attribute table .
*
* Returns the new xmlAttributeTablePtr or NULL in case of error .
*/
xmlAttributeTablePtr
xmlCopyAttributeTable ( xmlAttributeTablePtr table ) {
return ( ( xmlAttributeTablePtr ) xmlHashCopy ( table ,
( xmlHashCopier ) xmlCopyAttribute ) ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlDumpAttributeDecl :
* @ buf : the XML buffer output
* @ attr : An attribute declaration
*
* This will dump the content of the attribute declaration as an XML
* DTD definition
*/
void
xmlDumpAttributeDecl ( xmlBufferPtr buf , xmlAttributePtr attr ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( attr = = NULL ) )
return ;
2001-02-23 20:55:21 +03:00
xmlBufferWriteChar ( buf , " <!ATTLIST " ) ;
xmlBufferWriteCHAR ( buf , attr - > elem ) ;
xmlBufferWriteChar ( buf , " " ) ;
if ( attr - > prefix ! = NULL ) {
xmlBufferWriteCHAR ( buf , attr - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
xmlBufferWriteCHAR ( buf , attr - > name ) ;
switch ( attr - > atype ) {
case XML_ATTRIBUTE_CDATA :
xmlBufferWriteChar ( buf , " CDATA " ) ;
break ;
case XML_ATTRIBUTE_ID :
xmlBufferWriteChar ( buf , " ID " ) ;
break ;
case XML_ATTRIBUTE_IDREF :
xmlBufferWriteChar ( buf , " IDREF " ) ;
break ;
case XML_ATTRIBUTE_IDREFS :
xmlBufferWriteChar ( buf , " IDREFS " ) ;
break ;
case XML_ATTRIBUTE_ENTITY :
xmlBufferWriteChar ( buf , " ENTITY " ) ;
break ;
case XML_ATTRIBUTE_ENTITIES :
xmlBufferWriteChar ( buf , " ENTITIES " ) ;
break ;
case XML_ATTRIBUTE_NMTOKEN :
xmlBufferWriteChar ( buf , " NMTOKEN " ) ;
break ;
case XML_ATTRIBUTE_NMTOKENS :
xmlBufferWriteChar ( buf , " NMTOKENS " ) ;
break ;
case XML_ATTRIBUTE_ENUMERATION :
xmlBufferWriteChar ( buf , " ( " ) ;
xmlDumpEnumeration ( buf , attr - > tree ) ;
break ;
case XML_ATTRIBUTE_NOTATION :
xmlBufferWriteChar ( buf , " NOTATION ( " ) ;
xmlDumpEnumeration ( buf , attr - > tree ) ;
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" Internal: ATTRIBUTE struct corrupted invalid type \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
}
switch ( attr - > def ) {
case XML_ATTRIBUTE_NONE :
break ;
case XML_ATTRIBUTE_REQUIRED :
xmlBufferWriteChar ( buf , " #REQUIRED " ) ;
break ;
case XML_ATTRIBUTE_IMPLIED :
xmlBufferWriteChar ( buf , " #IMPLIED " ) ;
break ;
case XML_ATTRIBUTE_FIXED :
xmlBufferWriteChar ( buf , " #FIXED " ) ;
break ;
default :
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" Internal: ATTRIBUTE struct corrupted invalid def \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
}
if ( attr - > defaultValue ! = NULL ) {
xmlBufferWriteChar ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf , attr - > defaultValue ) ;
}
xmlBufferWriteChar ( buf , " > \n " ) ;
}
2003-10-20 18:56:06 +04:00
/**
* xmlDumpAttributeDeclScan :
* @ attr : An attribute declaration
* @ buf : the XML buffer output
*
* This is used with the hash scan function - just reverses arguments
*/
static void
xmlDumpAttributeDeclScan ( xmlAttributePtr attr , xmlBufferPtr buf ) {
xmlDumpAttributeDecl ( buf , attr ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlDumpAttributeTable :
* @ buf : the XML buffer output
* @ table : An attribute table
*
* This will dump the content of the attribute table as an XML DTD definition
*/
void
xmlDumpAttributeTable ( xmlBufferPtr buf , xmlAttributeTablePtr table ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( table = = NULL ) )
return ;
2003-10-20 18:56:06 +04:00
xmlHashScan ( table , ( xmlHashScanner ) xmlDumpAttributeDeclScan , buf ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* NOTATIONs *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlFreeNotation :
* @ not : A notation
*
* Deallocate the memory used by an notation definition
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlFreeNotation ( xmlNotationPtr nota ) {
if ( nota = = NULL ) return ;
if ( nota - > name ! = NULL )
xmlFree ( ( xmlChar * ) nota - > name ) ;
if ( nota - > PublicID ! = NULL )
xmlFree ( ( xmlChar * ) nota - > PublicID ) ;
if ( nota - > SystemID ! = NULL )
xmlFree ( ( xmlChar * ) nota - > SystemID ) ;
xmlFree ( nota ) ;
}
/**
* xmlAddNotationDecl :
* @ dtd : pointer to the DTD
* @ ctxt : the validation context
* @ name : the entity name
* @ PublicID : the public identifier or NULL
* @ SystemID : the system identifier or NULL
*
* Register a new notation declaration
*
2001-12-31 19:16:02 +03:00
* Returns NULL if not , otherwise the entity
2001-02-23 20:55:21 +03:00
*/
xmlNotationPtr
2004-02-06 10:36:04 +03:00
xmlAddNotationDecl ( xmlValidCtxtPtr ctxt , xmlDtdPtr dtd ,
2001-03-24 20:00:36 +03:00
const xmlChar * name ,
2001-02-23 20:55:21 +03:00
const xmlChar * PublicID , const xmlChar * SystemID ) {
xmlNotationPtr ret ;
xmlNotationTablePtr table ;
if ( dtd = = NULL ) {
return ( NULL ) ;
}
if ( name = = NULL ) {
return ( NULL ) ;
}
if ( ( PublicID = = NULL ) & & ( SystemID = = NULL ) ) {
2002-02-18 02:07:47 +03:00
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
}
/*
* Create the Notation table if needed .
*/
table = ( xmlNotationTablePtr ) dtd - > notations ;
2005-01-24 01:56:39 +03:00
if ( table = = NULL ) {
xmlDictPtr dict = NULL ;
if ( dtd - > doc ! = NULL )
dict = dtd - > doc - > dict ;
dtd - > notations = table = xmlHashCreateDict ( 0 , dict ) ;
}
2001-02-23 20:55:21 +03:00
if ( table = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt ,
2001-02-23 20:55:21 +03:00
" xmlAddNotationDecl: Table creation failed! \n " ) ;
return ( NULL ) ;
}
ret = ( xmlNotationPtr ) xmlMalloc ( sizeof ( xmlNotation ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlNotation ) ) ;
/*
* fill the structure .
*/
ret - > name = xmlStrdup ( name ) ;
if ( SystemID ! = NULL )
ret - > SystemID = xmlStrdup ( SystemID ) ;
if ( PublicID ! = NULL )
ret - > PublicID = xmlStrdup ( PublicID ) ;
/*
* Validity Check :
* Check the DTD for previous declarations of the ATTLIST
*/
if ( xmlHashAddEntry ( table , name , ret ) ) {
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_DTD_NOTATION_REDEFINED ,
" xmlAddNotationDecl: %s already defined \n " ,
( const char * ) name ) ;
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-02-23 20:55:21 +03:00
xmlFreeNotation ( ret ) ;
return ( NULL ) ;
}
return ( ret ) ;
}
/**
* xmlFreeNotationTable :
* @ table : An notation table
*
* Deallocate the memory used by an entities hash table .
*/
void
xmlFreeNotationTable ( xmlNotationTablePtr table ) {
xmlHashFree ( table , ( xmlHashDeallocator ) xmlFreeNotation ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlCopyNotation :
* @ nota : A notation
*
* Build a copy of a notation .
*
* Returns the new xmlNotationPtr or NULL in case of error .
*/
2001-03-24 20:00:36 +03:00
static xmlNotationPtr
2001-02-23 20:55:21 +03:00
xmlCopyNotation ( xmlNotationPtr nota ) {
xmlNotationPtr cur ;
cur = ( xmlNotationPtr ) xmlMalloc ( sizeof ( xmlNotation ) ) ;
if ( cur = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
if ( nota - > name ! = NULL )
cur - > name = xmlStrdup ( nota - > name ) ;
else
cur - > name = NULL ;
if ( nota - > PublicID ! = NULL )
cur - > PublicID = xmlStrdup ( nota - > PublicID ) ;
else
cur - > PublicID = NULL ;
if ( nota - > SystemID ! = NULL )
cur - > SystemID = xmlStrdup ( nota - > SystemID ) ;
else
cur - > SystemID = NULL ;
return ( cur ) ;
}
/**
* xmlCopyNotationTable :
* @ table : A notation table
*
* Build a copy of a notation table .
*
* Returns the new xmlNotationTablePtr or NULL in case of error .
*/
xmlNotationTablePtr
xmlCopyNotationTable ( xmlNotationTablePtr table ) {
return ( ( xmlNotationTablePtr ) xmlHashCopy ( table ,
( xmlHashCopier ) xmlCopyNotation ) ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlDumpNotationDecl :
* @ buf : the XML buffer output
* @ nota : A notation declaration
*
* This will dump the content the notation declaration as an XML DTD definition
*/
void
xmlDumpNotationDecl ( xmlBufferPtr buf , xmlNotationPtr nota ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( nota = = NULL ) )
return ;
2001-02-23 20:55:21 +03:00
xmlBufferWriteChar ( buf , " <!NOTATION " ) ;
xmlBufferWriteCHAR ( buf , nota - > name ) ;
if ( nota - > PublicID ! = NULL ) {
xmlBufferWriteChar ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf , nota - > PublicID ) ;
if ( nota - > SystemID ! = NULL ) {
xmlBufferWriteChar ( buf , " " ) ;
2004-09-09 00:55:38 +04:00
xmlBufferWriteQuotedString ( buf , nota - > SystemID ) ;
2001-02-23 20:55:21 +03:00
}
} else {
xmlBufferWriteChar ( buf , " SYSTEM " ) ;
2004-09-09 00:55:38 +04:00
xmlBufferWriteQuotedString ( buf , nota - > SystemID ) ;
2001-02-23 20:55:21 +03:00
}
xmlBufferWriteChar ( buf , " > \n " ) ;
}
2003-10-20 18:56:06 +04:00
/**
* xmlDumpNotationDeclScan :
* @ nota : A notation declaration
* @ buf : the XML buffer output
*
* This is called with the hash scan function , and just reverses args
*/
static void
xmlDumpNotationDeclScan ( xmlNotationPtr nota , xmlBufferPtr buf ) {
xmlDumpNotationDecl ( buf , nota ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlDumpNotationTable :
* @ buf : the XML buffer output
* @ table : A notation table
*
* This will dump the content of the notation table as an XML DTD definition
*/
void
xmlDumpNotationTable ( xmlBufferPtr buf , xmlNotationTablePtr table ) {
2004-11-05 20:22:25 +03:00
if ( ( buf = = NULL ) | | ( table = = NULL ) )
return ;
2003-10-20 18:56:06 +04:00
xmlHashScan ( table , ( xmlHashScanner ) xmlDumpNotationDeclScan , buf ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 17:20:24 +04:00
# endif /* LIBXML_OUTPUT_ENABLED */
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* IDs *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-11-15 21:24:36 +03:00
/**
* DICT_FREE :
* @ str : a string
*
* Free a string if it is not owned by the " dict " dictionnary in the
* current scope
*/
# define DICT_FREE(str) \
if ( ( str ) & & ( ( ! dict ) | | \
( xmlDictOwns ( dict , ( const xmlChar * ) ( str ) ) = = 0 ) ) ) \
xmlFree ( ( char * ) ( str ) ) ;
2001-02-23 20:55:21 +03:00
/**
* xmlFreeID :
* @ not : A id
*
* Deallocate the memory used by an id definition
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlFreeID ( xmlIDPtr id ) {
2003-11-15 21:24:36 +03:00
xmlDictPtr dict = NULL ;
2001-02-23 20:55:21 +03:00
if ( id = = NULL ) return ;
2003-11-15 21:24:36 +03:00
if ( id - > doc ! = NULL )
dict = id - > doc - > dict ;
2001-02-23 20:55:21 +03:00
if ( id - > value ! = NULL )
2003-11-15 21:24:36 +03:00
DICT_FREE ( id - > value )
2002-12-20 03:16:24 +03:00
if ( id - > name ! = NULL )
2003-11-15 21:24:36 +03:00
DICT_FREE ( id - > name )
2001-02-23 20:55:21 +03:00
xmlFree ( id ) ;
}
2003-11-15 21:24:36 +03:00
2001-02-23 20:55:21 +03:00
/**
* xmlAddID :
* @ ctxt : the validation context
* @ doc : pointer to the document
* @ value : the value name
* @ attr : the attribute holding the ID
*
* Register a new id declaration
*
2001-12-31 19:16:02 +03:00
* Returns NULL if not , otherwise the new xmlIDPtr
2001-02-23 20:55:21 +03:00
*/
xmlIDPtr
xmlAddID ( xmlValidCtxtPtr ctxt , xmlDocPtr doc , const xmlChar * value ,
xmlAttrPtr attr ) {
xmlIDPtr ret ;
xmlIDTablePtr table ;
if ( doc = = NULL ) {
return ( NULL ) ;
}
if ( value = = NULL ) {
return ( NULL ) ;
}
if ( attr = = NULL ) {
return ( NULL ) ;
}
/*
* Create the ID table if needed .
*/
table = ( xmlIDTablePtr ) doc - > ids ;
2005-01-24 01:56:39 +03:00
if ( table = = NULL ) {
doc - > ids = table = xmlHashCreateDict ( 0 , doc - > dict ) ;
}
2001-02-23 20:55:21 +03:00
if ( table = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt ,
2001-02-23 20:55:21 +03:00
" xmlAddID: Table creation failed! \n " ) ;
return ( NULL ) ;
}
ret = ( xmlIDPtr ) xmlMalloc ( sizeof ( xmlID ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
/*
* fill the structure .
*/
ret - > value = xmlStrdup ( value ) ;
2003-11-15 21:24:36 +03:00
ret - > doc = doc ;
2002-12-20 03:16:24 +03:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > vstateNr ! = 0 ) ) {
/*
* Operating in streaming mode , attr is gonna disapear
*/
2003-11-15 21:24:36 +03:00
if ( doc - > dict ! = NULL )
ret - > name = xmlDictLookup ( doc - > dict , attr - > name , - 1 ) ;
else
ret - > name = xmlStrdup ( attr - > name ) ;
2002-12-20 03:16:24 +03:00
ret - > attr = NULL ;
} else {
ret - > attr = attr ;
ret - > name = NULL ;
}
ret - > lineno = xmlGetLineNo ( attr - > parent ) ;
2001-02-23 20:55:21 +03:00
if ( xmlHashAddEntry ( table , value , ret ) < 0 ) {
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-02-23 20:55:21 +03:00
/*
2001-12-31 19:16:02 +03:00
* The id is already defined in this DTD .
2001-02-23 20:55:21 +03:00
*/
2004-02-25 15:34:55 +03:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > error ! = NULL ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , attr - > parent , XML_DTD_ID_REDEFINED ,
" ID %s already defined \n " ,
value , NULL , NULL ) ;
2002-09-05 18:21:15 +04:00
}
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2001-02-23 20:55:21 +03:00
xmlFreeID ( ret ) ;
return ( NULL ) ;
}
2003-03-20 00:02:29 +03:00
if ( attr ! = NULL )
attr - > atype = XML_ATTRIBUTE_ID ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
/**
* xmlFreeIDTable :
* @ table : An id table
*
* Deallocate the memory used by an ID hash table .
*/
void
xmlFreeIDTable ( xmlIDTablePtr table ) {
xmlHashFree ( table , ( xmlHashDeallocator ) xmlFreeID ) ;
}
/**
* xmlIsID :
* @ doc : the document
* @ elem : the element carrying the attribute
* @ attr : the attribute
*
2001-12-31 19:16:02 +03:00
* Determine whether an attribute is of type ID . In case we have DTD ( s )
2002-10-08 12:26:11 +04:00
* then this is done if DTD loading has been requested . In the case
* of HTML documents parsed with the HTML parser , then ID detection is
* done systematically .
2001-02-23 20:55:21 +03:00
*
* Returns 0 or 1 depending on the lookup result
*/
int
xmlIsID ( xmlDocPtr doc , xmlNodePtr elem , xmlAttrPtr attr ) {
2005-09-03 17:28:24 +04:00
if ( ( attr = = NULL ) | | ( attr - > name = = NULL ) ) return ( 0 ) ;
if ( ( attr - > ns ! = NULL ) & & ( attr - > ns - > prefix ! = NULL ) & &
( ! strcmp ( ( char * ) attr - > name , " id " ) ) & &
( ! strcmp ( ( char * ) attr - > ns - > prefix , " xml " ) ) )
return ( 1 ) ;
2001-02-23 20:55:21 +03:00
if ( doc = = NULL ) return ( 0 ) ;
if ( ( doc - > intSubset = = NULL ) & & ( doc - > extSubset = = NULL ) ) {
return ( 0 ) ;
} else if ( doc - > type = = XML_HTML_DOCUMENT_NODE ) {
2006-03-03 19:44:37 +03:00
if ( ( xmlStrEqual ( BAD_CAST " id " , attr - > name ) ) | |
( ( xmlStrEqual ( BAD_CAST " name " , attr - > name ) ) & &
2007-06-12 20:20:09 +04:00
( ( elem = = NULL ) | | ( xmlStrEqual ( elem - > name , BAD_CAST " a " ) ) ) ) )
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
return ( 0 ) ;
2005-08-12 14:18:14 +04:00
} else if ( elem = = NULL ) {
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
} else {
2005-08-22 16:07:04 +04:00
xmlAttributePtr attrDecl = NULL ;
2001-02-23 20:55:21 +03:00
2005-08-12 14:18:14 +04:00
xmlChar felem [ 50 ] , fattr [ 50 ] ;
xmlChar * fullelemname , * fullattrname ;
fullelemname = ( elem - > ns ! = NULL & & elem - > ns - > prefix ! = NULL ) ?
xmlBuildQName ( elem - > name , elem - > ns - > prefix , felem , 50 ) :
( xmlChar * ) elem - > name ;
fullattrname = ( attr - > ns ! = NULL & & attr - > ns - > prefix ! = NULL ) ?
xmlBuildQName ( attr - > name , attr - > ns - > prefix , fattr , 50 ) :
( xmlChar * ) attr - > name ;
if ( fullelemname ! = NULL & & fullattrname ! = NULL ) {
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , fullelemname ,
fullattrname ) ;
2002-07-06 21:53:56 +04:00
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
2005-08-12 14:18:14 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , fullelemname ,
fullattrname ) ;
2002-07-06 21:53:56 +04:00
}
2001-02-23 20:55:21 +03:00
2005-08-12 14:18:14 +04:00
if ( ( fullattrname ! = fattr ) & & ( fullattrname ! = attr - > name ) )
xmlFree ( fullattrname ) ;
if ( ( fullelemname ! = felem ) & & ( fullelemname ! = elem - > name ) )
xmlFree ( fullelemname ) ;
2001-02-23 20:55:21 +03:00
if ( ( attrDecl ! = NULL ) & & ( attrDecl - > atype = = XML_ATTRIBUTE_ID ) )
return ( 1 ) ;
}
return ( 0 ) ;
}
/**
2002-12-10 18:19:08 +03:00
* xmlRemoveID :
2001-02-23 20:55:21 +03:00
* @ doc : the document
* @ attr : the attribute
*
* Remove the given attribute from the ID table maintained internally .
*
* Returns - 1 if the lookup failed and 0 otherwise
*/
int
xmlRemoveID ( xmlDocPtr doc , xmlAttrPtr attr ) {
xmlIDTablePtr table ;
2003-11-15 21:24:36 +03:00
xmlIDPtr id ;
2001-02-23 20:55:21 +03:00
xmlChar * ID ;
if ( doc = = NULL ) return ( - 1 ) ;
if ( attr = = NULL ) return ( - 1 ) ;
table = ( xmlIDTablePtr ) doc - > ids ;
if ( table = = NULL )
return ( - 1 ) ;
if ( attr = = NULL )
return ( - 1 ) ;
ID = xmlNodeListGetString ( doc , attr - > children , 1 ) ;
if ( ID = = NULL )
return ( - 1 ) ;
2003-11-15 21:24:36 +03:00
id = xmlHashLookup ( table , ID ) ;
if ( id = = NULL | | id - > attr ! = attr ) {
2001-02-23 20:55:21 +03:00
xmlFree ( ID ) ;
return ( - 1 ) ;
}
2004-12-10 13:26:42 +03:00
xmlHashRemoveEntry ( table , ID , ( xmlHashDeallocator ) xmlFreeID ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( ID ) ;
2005-06-20 21:17:54 +04:00
attr - > atype = 0 ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/**
* xmlGetID :
* @ doc : pointer to the document
* @ ID : the ID value
*
* Search the attribute declaring the given ID
*
* Returns NULL if not found , otherwise the xmlAttrPtr defining the ID
*/
xmlAttrPtr
xmlGetID ( xmlDocPtr doc , const xmlChar * ID ) {
xmlIDTablePtr table ;
xmlIDPtr id ;
if ( doc = = NULL ) {
return ( NULL ) ;
}
if ( ID = = NULL ) {
return ( NULL ) ;
}
table = ( xmlIDTablePtr ) doc - > ids ;
if ( table = = NULL )
return ( NULL ) ;
id = xmlHashLookup ( table , ID ) ;
if ( id = = NULL )
return ( NULL ) ;
2002-12-20 03:16:24 +03:00
if ( id - > attr = = NULL ) {
/*
* We are operating on a stream , return a well known reference
* since the attribute node doesn ' t exist anymore
*/
return ( ( xmlAttrPtr ) doc ) ;
}
2001-02-23 20:55:21 +03:00
return ( id - > attr ) ;
}
/************************************************************************
* *
* Refs *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-02-26 13:49:57 +03:00
typedef struct xmlRemoveMemo_t
2001-02-23 20:55:21 +03:00
{
xmlListPtr l ;
xmlAttrPtr ap ;
2001-02-26 13:49:57 +03:00
} xmlRemoveMemo ;
typedef xmlRemoveMemo * xmlRemoveMemoPtr ;
typedef struct xmlValidateMemo_t
{
xmlValidCtxtPtr ctxt ;
const xmlChar * name ;
} xmlValidateMemo ;
typedef xmlValidateMemo * xmlValidateMemoPtr ;
2001-02-23 20:55:21 +03:00
/**
* xmlFreeRef :
* @ lk : A list link
*
* Deallocate the memory used by a ref definition
*/
static void
xmlFreeRef ( xmlLinkPtr lk ) {
2001-05-04 19:21:12 +04:00
xmlRefPtr ref = ( xmlRefPtr ) xmlLinkGetData ( lk ) ;
if ( ref = = NULL ) return ;
if ( ref - > value ! = NULL )
xmlFree ( ( xmlChar * ) ref - > value ) ;
2002-12-20 03:16:24 +03:00
if ( ref - > name ! = NULL )
xmlFree ( ( xmlChar * ) ref - > name ) ;
2001-05-04 19:21:12 +04:00
xmlFree ( ref ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlFreeRefList :
* @ list_ref : A list of references .
*
* Deallocate the memory used by a list of references
*/
static void
xmlFreeRefList ( xmlListPtr list_ref ) {
2001-05-04 19:21:12 +04:00
if ( list_ref = = NULL ) return ;
xmlListDelete ( list_ref ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlWalkRemoveRef :
* @ data : Contents of current link
* @ user : Value supplied by the user
*
2001-12-31 19:16:02 +03:00
* Returns 0 to abort the walk or 1 to continue
2001-02-23 20:55:21 +03:00
*/
static int
xmlWalkRemoveRef ( const void * data , const void * user )
{
2001-05-04 19:21:12 +04:00
xmlAttrPtr attr0 = ( ( xmlRefPtr ) data ) - > attr ;
xmlAttrPtr attr1 = ( ( xmlRemoveMemoPtr ) user ) - > ap ;
xmlListPtr ref_list = ( ( xmlRemoveMemoPtr ) user ) - > l ;
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
if ( attr0 = = attr1 ) { /* Matched: remove and terminate walk */
xmlListRemoveFirst ( ref_list , ( void * ) data ) ;
return 0 ;
}
return 1 ;
2001-02-23 20:55:21 +03:00
}
2004-02-25 13:44:30 +03:00
/**
* xmlDummyCompare
* @ data0 : Value supplied by the user
* @ data1 : Value supplied by the user
*
* Do nothing , return 0. Used to create unordered lists .
*/
static int
2004-02-25 14:52:31 +03:00
xmlDummyCompare ( const void * data0 ATTRIBUTE_UNUSED ,
const void * data1 ATTRIBUTE_UNUSED )
2004-02-25 13:44:30 +03:00
{
return ( 0 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlAddRef :
* @ ctxt : the validation context
* @ doc : pointer to the document
* @ value : the value name
* @ attr : the attribute holding the Ref
*
* Register a new ref declaration
*
2001-12-31 19:16:02 +03:00
* Returns NULL if not , otherwise the new xmlRefPtr
2001-02-23 20:55:21 +03:00
*/
xmlRefPtr
2004-02-06 10:36:04 +03:00
xmlAddRef ( xmlValidCtxtPtr ctxt , xmlDocPtr doc , const xmlChar * value ,
2001-02-23 20:55:21 +03:00
xmlAttrPtr attr ) {
2001-05-04 19:21:12 +04:00
xmlRefPtr ret ;
xmlRefTablePtr table ;
xmlListPtr ref_list ;
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
if ( doc = = NULL ) {
return ( NULL ) ;
}
if ( value = = NULL ) {
return ( NULL ) ;
}
if ( attr = = NULL ) {
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
/*
2001-02-23 20:55:21 +03:00
* Create the Ref table if needed .
*/
2001-05-04 19:21:12 +04:00
table = ( xmlRefTablePtr ) doc - > refs ;
2005-01-24 01:56:39 +03:00
if ( table = = NULL ) {
doc - > refs = table = xmlHashCreateDict ( 0 , doc - > dict ) ;
}
2001-05-04 19:21:12 +04:00
if ( table = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt ,
2001-05-04 19:21:12 +04:00
" xmlAddRef: Table creation failed! \n " ) ;
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
ret = ( xmlRefPtr ) xmlMalloc ( sizeof ( xmlRef ) ) ;
if ( ret = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2001-05-04 19:21:12 +04:00
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
/*
2001-02-23 20:55:21 +03:00
* fill the structure .
*/
2001-05-04 19:21:12 +04:00
ret - > value = xmlStrdup ( value ) ;
2002-12-20 03:16:24 +03:00
if ( ( ctxt ! = NULL ) & & ( ctxt - > vstateNr ! = 0 ) ) {
/*
* Operating in streaming mode , attr is gonna disapear
*/
ret - > name = xmlStrdup ( attr - > name ) ;
ret - > attr = NULL ;
} else {
ret - > name = NULL ;
ret - > attr = attr ;
}
ret - > lineno = xmlGetLineNo ( attr - > parent ) ;
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
/* To add a reference :-
* References are maintained as a list of references ,
* Lookup the entry , if no entry create new nodelist
* Add the owning node to the NodeList
* Return the ref
*/
if ( NULL = = ( ref_list = xmlHashLookup ( table , value ) ) ) {
2004-02-25 13:44:30 +03:00
if ( NULL = = ( ref_list = xmlListCreate ( xmlFreeRef , xmlDummyCompare ) ) ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" xmlAddRef: Reference list creation failed! \n " ,
NULL ) ;
2007-05-10 03:53:30 +04:00
goto failed ;
2001-05-04 19:21:12 +04:00
}
if ( xmlHashAddEntry ( table , value , ref_list ) < 0 ) {
xmlListDelete ( ref_list ) ;
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" xmlAddRef: Reference list insertion failed! \n " ,
NULL ) ;
2007-05-10 03:53:30 +04:00
goto failed ;
2001-05-04 19:21:12 +04:00
}
}
2007-05-10 03:53:30 +04:00
if ( xmlListAppend ( ref_list , ret ) ! = 0 ) {
xmlErrValid ( NULL , XML_ERR_INTERNAL_ERROR ,
" xmlAddRef: Reference list insertion failed! \n " ,
NULL ) ;
goto failed ;
}
2001-05-04 19:21:12 +04:00
return ( ret ) ;
2007-05-10 03:53:30 +04:00
failed :
if ( ret ! = NULL ) {
if ( ret - > value ! = NULL )
xmlFree ( ( char * ) ret - > value ) ;
if ( ret - > name ! = NULL )
xmlFree ( ( char * ) ret - > name ) ;
xmlFree ( ret ) ;
}
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlFreeRefTable :
* @ table : An ref table
*
* Deallocate the memory used by an Ref hash table .
*/
void
xmlFreeRefTable ( xmlRefTablePtr table ) {
2001-05-04 19:21:12 +04:00
xmlHashFree ( table , ( xmlHashDeallocator ) xmlFreeRefList ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlIsRef :
* @ doc : the document
* @ elem : the element carrying the attribute
* @ attr : the attribute
*
2001-12-31 19:16:02 +03:00
* Determine whether an attribute is of type Ref . In case we have DTD ( s )
2001-02-23 20:55:21 +03:00
* then this is simple , otherwise we use an heuristic : name Ref ( upper
* or lowercase ) .
*
* Returns 0 or 1 depending on the lookup result
*/
int
xmlIsRef ( xmlDocPtr doc , xmlNodePtr elem , xmlAttrPtr attr ) {
2004-11-05 13:03:46 +03:00
if ( attr = = NULL )
return ( 0 ) ;
if ( doc = = NULL ) {
doc = attr - > doc ;
if ( doc = = NULL ) return ( 0 ) ;
}
2001-05-04 19:21:12 +04:00
if ( ( doc - > intSubset = = NULL ) & & ( doc - > extSubset = = NULL ) ) {
return ( 0 ) ;
} else if ( doc - > type = = XML_HTML_DOCUMENT_NODE ) {
/* TODO @@@ */
return ( 0 ) ;
} else {
xmlAttributePtr attrDecl ;
2004-11-05 13:03:46 +03:00
if ( elem = = NULL ) return ( 0 ) ;
2001-05-04 19:21:12 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , elem - > name , attr - > name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset ,
elem - > name , attr - > name ) ;
if ( ( attrDecl ! = NULL ) & &
( attrDecl - > atype = = XML_ATTRIBUTE_IDREF | |
attrDecl - > atype = = XML_ATTRIBUTE_IDREFS ) )
return ( 1 ) ;
}
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
}
/**
2002-12-10 18:19:08 +03:00
* xmlRemoveRef :
2001-02-23 20:55:21 +03:00
* @ doc : the document
* @ attr : the attribute
*
* Remove the given attribute from the Ref table maintained internally .
*
* Returns - 1 if the lookup failed and 0 otherwise
*/
int
xmlRemoveRef ( xmlDocPtr doc , xmlAttrPtr attr ) {
2001-05-04 19:21:12 +04:00
xmlListPtr ref_list ;
xmlRefTablePtr table ;
xmlChar * ID ;
xmlRemoveMemo target ;
if ( doc = = NULL ) return ( - 1 ) ;
if ( attr = = NULL ) return ( - 1 ) ;
table = ( xmlRefTablePtr ) doc - > refs ;
if ( table = = NULL )
return ( - 1 ) ;
if ( attr = = NULL )
return ( - 1 ) ;
ID = xmlNodeListGetString ( doc , attr - > children , 1 ) ;
if ( ID = = NULL )
return ( - 1 ) ;
ref_list = xmlHashLookup ( table , ID ) ;
if ( ref_list = = NULL ) {
xmlFree ( ID ) ;
return ( - 1 ) ;
}
/* At this point, ref_list refers to a list of references which
* have the same key as the supplied attr . Our list of references
* is ordered by reference address and we don ' t have that information
* here to use when removing . We ' ll have to walk the list and
* check for a matching attribute , when we find one stop the walk
* and remove the entry .
* The list is ordered by reference , so that means we don ' t have the
* key . Passing the list and the reference to the walker means we
* will have enough data to be able to remove the entry .
*/
target . l = ref_list ;
target . ap = attr ;
/* Remove the supplied attr from our list */
xmlListWalk ( ref_list , xmlWalkRemoveRef , & target ) ;
/*If the list is empty then remove the list entry in the hash */
if ( xmlListEmpty ( ref_list ) )
xmlHashUpdateEntry ( table , ID , NULL , ( xmlHashDeallocator )
xmlFreeRefList ) ;
xmlFree ( ID ) ;
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlGetRefs :
* @ doc : pointer to the document
* @ ID : the ID value
*
* Find the set of references for the supplied ID .
*
* Returns NULL if not found , otherwise node set for the ID .
*/
xmlListPtr
xmlGetRefs ( xmlDocPtr doc , const xmlChar * ID ) {
2001-05-04 19:21:12 +04:00
xmlRefTablePtr table ;
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
if ( doc = = NULL ) {
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
if ( ID = = NULL ) {
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
table = ( xmlRefTablePtr ) doc - > refs ;
if ( table = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
2001-05-04 19:21:12 +04:00
return ( xmlHashLookup ( table , ID ) ) ;
2001-02-23 20:55:21 +03:00
}
/************************************************************************
* *
* Routines for validity checking *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlGetDtdElementDesc :
* @ dtd : a pointer to the DtD to search
* @ name : the element name
*
2001-12-31 19:16:02 +03:00
* Search the DTD for the description of this element
2001-02-23 20:55:21 +03:00
*
* returns the xmlElementPtr if found or NULL
*/
xmlElementPtr
xmlGetDtdElementDesc ( xmlDtdPtr dtd , const xmlChar * name ) {
xmlElementTablePtr table ;
xmlElementPtr cur ;
xmlChar * uqname = NULL , * prefix = NULL ;
2003-04-24 20:06:47 +04:00
if ( ( dtd = = NULL ) | | ( name = = NULL ) ) return ( NULL ) ;
2001-04-18 17:09:01 +04:00
if ( dtd - > elements = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
table = ( xmlElementTablePtr ) dtd - > elements ;
uqname = xmlSplitQName2 ( name , & prefix ) ;
2001-04-18 17:09:01 +04:00
if ( uqname ! = NULL )
name = uqname ;
cur = xmlHashLookup2 ( table , name , prefix ) ;
if ( prefix ! = NULL ) xmlFree ( prefix ) ;
if ( uqname ! = NULL ) xmlFree ( uqname ) ;
return ( cur ) ;
}
/**
* xmlGetDtdElementDesc2 :
* @ dtd : a pointer to the DtD to search
* @ name : the element name
* @ create : create an empty description if not found
*
2001-12-31 19:16:02 +03:00
* Search the DTD for the description of this element
2001-04-18 17:09:01 +04:00
*
* returns the xmlElementPtr if found or NULL
*/
2001-12-13 17:55:21 +03:00
static xmlElementPtr
2001-04-18 17:09:01 +04:00
xmlGetDtdElementDesc2 ( xmlDtdPtr dtd , const xmlChar * name , int create ) {
xmlElementTablePtr table ;
xmlElementPtr cur ;
xmlChar * uqname = NULL , * prefix = NULL ;
if ( dtd = = NULL ) return ( NULL ) ;
if ( dtd - > elements = = NULL ) {
2005-01-24 01:56:39 +03:00
xmlDictPtr dict = NULL ;
if ( dtd - > doc ! = NULL )
dict = dtd - > doc - > dict ;
2001-04-18 17:09:01 +04:00
if ( ! create )
return ( NULL ) ;
/*
* Create the Element table if needed .
*/
table = ( xmlElementTablePtr ) dtd - > elements ;
if ( table = = NULL ) {
2005-01-24 01:56:39 +03:00
table = xmlHashCreateDict ( 0 , dict ) ;
2001-04-18 17:09:01 +04:00
dtd - > elements = ( void * ) table ;
}
if ( table = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " element table allocation failed " ) ;
2001-04-18 17:09:01 +04:00
return ( NULL ) ;
}
}
table = ( xmlElementTablePtr ) dtd - > elements ;
uqname = xmlSplitQName2 ( name , & prefix ) ;
if ( uqname ! = NULL )
name = uqname ;
cur = xmlHashLookup2 ( table , name , prefix ) ;
if ( ( cur = = NULL ) & & ( create ) ) {
cur = ( xmlElementPtr ) xmlMalloc ( sizeof ( xmlElement ) ) ;
if ( cur = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( NULL , " malloc failed " ) ;
2001-04-18 17:09:01 +04:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlElement ) ) ;
cur - > type = XML_ELEMENT_DECL ;
/*
* fill the structure .
*/
cur - > name = xmlStrdup ( name ) ;
cur - > prefix = xmlStrdup ( prefix ) ;
cur - > etype = XML_ELEMENT_TYPE_UNDEFINED ;
xmlHashAddEntry2 ( table , name , prefix , cur ) ;
}
if ( prefix ! = NULL ) xmlFree ( prefix ) ;
if ( uqname ! = NULL ) xmlFree ( uqname ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
/**
* xmlGetDtdQElementDesc :
* @ dtd : a pointer to the DtD to search
* @ name : the element name
* @ prefix : the element namespace prefix
*
2001-12-31 19:16:02 +03:00
* Search the DTD for the description of this element
2001-02-23 20:55:21 +03:00
*
* returns the xmlElementPtr if found or NULL
*/
2001-08-07 05:10:10 +04:00
xmlElementPtr
2001-02-23 20:55:21 +03:00
xmlGetDtdQElementDesc ( xmlDtdPtr dtd , const xmlChar * name ,
const xmlChar * prefix ) {
xmlElementTablePtr table ;
if ( dtd = = NULL ) return ( NULL ) ;
if ( dtd - > elements = = NULL ) return ( NULL ) ;
table = ( xmlElementTablePtr ) dtd - > elements ;
return ( xmlHashLookup2 ( table , name , prefix ) ) ;
}
/**
* xmlGetDtdAttrDesc :
* @ dtd : a pointer to the DtD to search
* @ elem : the element name
* @ name : the attribute name
*
2001-12-31 19:16:02 +03:00
* Search the DTD for the description of this attribute on
2001-02-23 20:55:21 +03:00
* this element .
*
* returns the xmlAttributePtr if found or NULL
*/
xmlAttributePtr
xmlGetDtdAttrDesc ( xmlDtdPtr dtd , const xmlChar * elem , const xmlChar * name ) {
xmlAttributeTablePtr table ;
xmlAttributePtr cur ;
xmlChar * uqname = NULL , * prefix = NULL ;
if ( dtd = = NULL ) return ( NULL ) ;
if ( dtd - > attributes = = NULL ) return ( NULL ) ;
table = ( xmlAttributeTablePtr ) dtd - > attributes ;
if ( table = = NULL )
return ( NULL ) ;
uqname = xmlSplitQName2 ( name , & prefix ) ;
if ( uqname ! = NULL ) {
cur = xmlHashLookup3 ( table , uqname , prefix , elem ) ;
if ( prefix ! = NULL ) xmlFree ( prefix ) ;
if ( uqname ! = NULL ) xmlFree ( uqname ) ;
} else
cur = xmlHashLookup3 ( table , name , NULL , elem ) ;
return ( cur ) ;
}
/**
* xmlGetDtdQAttrDesc :
* @ dtd : a pointer to the DtD to search
* @ elem : the element name
* @ name : the attribute name
* @ prefix : the attribute namespace prefix
*
2001-12-31 19:16:02 +03:00
* Search the DTD for the description of this qualified attribute on
2001-02-23 20:55:21 +03:00
* this element .
*
* returns the xmlAttributePtr if found or NULL
*/
2001-08-07 05:10:10 +04:00
xmlAttributePtr
2001-02-23 20:55:21 +03:00
xmlGetDtdQAttrDesc ( xmlDtdPtr dtd , const xmlChar * elem , const xmlChar * name ,
const xmlChar * prefix ) {
xmlAttributeTablePtr table ;
if ( dtd = = NULL ) return ( NULL ) ;
if ( dtd - > attributes = = NULL ) return ( NULL ) ;
table = ( xmlAttributeTablePtr ) dtd - > attributes ;
return ( xmlHashLookup3 ( table , name , prefix , elem ) ) ;
}
/**
* xmlGetDtdNotationDesc :
* @ dtd : a pointer to the DtD to search
* @ name : the notation name
*
2001-12-31 19:16:02 +03:00
* Search the DTD for the description of this notation
2001-02-23 20:55:21 +03:00
*
* returns the xmlNotationPtr if found or NULL
*/
xmlNotationPtr
xmlGetDtdNotationDesc ( xmlDtdPtr dtd , const xmlChar * name ) {
xmlNotationTablePtr table ;
if ( dtd = = NULL ) return ( NULL ) ;
if ( dtd - > notations = = NULL ) return ( NULL ) ;
table = ( xmlNotationTablePtr ) dtd - > notations ;
return ( xmlHashLookup ( table , name ) ) ;
}
2004-02-25 14:52:31 +03:00
# if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlValidateNotationUse :
* @ ctxt : the validation context
* @ doc : the document
* @ notationName : the notation name to check
*
2001-12-31 19:16:02 +03:00
* Validate that the given name match a notation declaration .
2001-02-23 20:55:21 +03:00
* - [ VC : Notation Declared ]
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateNotationUse ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
const xmlChar * notationName ) {
xmlNotationPtr notaDecl ;
if ( ( doc = = NULL ) | | ( doc - > intSubset = = NULL ) ) return ( - 1 ) ;
notaDecl = xmlGetDtdNotationDesc ( doc - > intSubset , notationName ) ;
if ( ( notaDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
notaDecl = xmlGetDtdNotationDesc ( doc - > extSubset , notationName ) ;
2003-03-31 01:10:09 +04:00
if ( ( notaDecl = = NULL ) & & ( ctxt ! = NULL ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) doc , XML_DTD_UNKNOWN_NOTATION ,
" NOTATION %s is not declared \n " ,
notationName , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
return ( 1 ) ;
}
2004-02-25 14:52:31 +03:00
# endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */
2001-02-23 20:55:21 +03:00
/**
2002-12-10 18:19:08 +03:00
* xmlIsMixedElement :
2001-02-23 20:55:21 +03:00
* @ doc : the document
* @ name : the element name
*
* Search in the DtDs whether an element accept Mixed content ( or ANY )
* basically if it is supposed to accept text childs
*
* returns 0 if no , 1 if yes , and - 1 if no element description is available
*/
int
xmlIsMixedElement ( xmlDocPtr doc , const xmlChar * name ) {
xmlElementPtr elemDecl ;
if ( ( doc = = NULL ) | | ( doc - > intSubset = = NULL ) ) return ( - 1 ) ;
elemDecl = xmlGetDtdElementDesc ( doc - > intSubset , name ) ;
if ( ( elemDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
elemDecl = xmlGetDtdElementDesc ( doc - > extSubset , name ) ;
if ( elemDecl = = NULL ) return ( - 1 ) ;
switch ( elemDecl - > etype ) {
2001-04-18 17:09:01 +04:00
case XML_ELEMENT_TYPE_UNDEFINED :
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
case XML_ELEMENT_TYPE_ELEMENT :
return ( 0 ) ;
case XML_ELEMENT_TYPE_EMPTY :
/*
* return 1 for EMPTY since we want VC error to pop up
* on < empty > < / empty > for example
*/
case XML_ELEMENT_TYPE_ANY :
case XML_ELEMENT_TYPE_MIXED :
return ( 1 ) ;
}
return ( 1 ) ;
}
2003-09-28 22:58:27 +04:00
# ifdef LIBXML_VALID_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlValidateNameValue :
* @ value : an Name value
*
* Validate that the given value match Name production
*
* returns 1 if valid or 0 otherwise
*/
2002-04-14 16:56:08 +04:00
int
2001-02-23 20:55:21 +03:00
xmlValidateNameValue ( const xmlChar * value ) {
const xmlChar * cur ;
2002-01-13 18:43:22 +03:00
int val , len ;
2001-02-23 20:55:21 +03:00
if ( value = = NULL ) return ( 0 ) ;
cur = value ;
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
if ( ! IS_LETTER ( val ) & & ( val ! = ' _ ' ) & &
( val ! = ' : ' ) ) {
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
while ( ( IS_LETTER ( val ) ) | | ( IS_DIGIT ( val ) ) | |
( val = = ' . ' ) | | ( val = = ' - ' ) | |
( val = = ' _ ' ) | | ( val = = ' : ' ) | |
( IS_COMBINING ( val ) ) | |
( IS_EXTENDER ( val ) ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2001-02-23 20:55:21 +03:00
2002-01-13 18:43:22 +03:00
if ( val ! = 0 ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
}
/**
* xmlValidateNamesValue :
* @ value : an Names value
*
* Validate that the given value match Names production
*
* returns 1 if valid or 0 otherwise
*/
2002-04-14 16:56:08 +04:00
int
2001-02-23 20:55:21 +03:00
xmlValidateNamesValue ( const xmlChar * value ) {
const xmlChar * cur ;
2002-01-13 18:43:22 +03:00
int val , len ;
2001-02-23 20:55:21 +03:00
if ( value = = NULL ) return ( 0 ) ;
cur = value ;
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
2001-02-23 20:55:21 +03:00
2002-01-13 18:43:22 +03:00
if ( ! IS_LETTER ( val ) & & ( val ! = ' _ ' ) & &
( val ! = ' : ' ) ) {
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
while ( ( IS_LETTER ( val ) ) | | ( IS_DIGIT ( val ) ) | |
( val = = ' . ' ) | | ( val = = ' - ' ) | |
( val = = ' _ ' ) | | ( val = = ' : ' ) | |
( IS_COMBINING ( val ) ) | |
( IS_EXTENDER ( val ) ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2001-02-23 20:55:21 +03:00
2004-09-26 18:42:56 +04:00
/* Should not test IS_BLANK(val) here -- see erratum E20*/
while ( val = = 0x20 ) {
while ( val = = 0x20 ) {
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2001-02-23 20:55:21 +03:00
2002-01-13 18:43:22 +03:00
if ( ! IS_LETTER ( val ) & & ( val ! = ' _ ' ) & &
( val ! = ' : ' ) ) {
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
while ( ( IS_LETTER ( val ) ) | | ( IS_DIGIT ( val ) ) | |
( val = = ' . ' ) | | ( val = = ' - ' ) | |
( val = = ' _ ' ) | | ( val = = ' : ' ) | |
( IS_COMBINING ( val ) ) | |
( IS_EXTENDER ( val ) ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2001-02-23 20:55:21 +03:00
}
2002-01-13 18:43:22 +03:00
if ( val ! = 0 ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
}
/**
* xmlValidateNmtokenValue :
2001-12-31 19:16:02 +03:00
* @ value : an Nmtoken value
2001-02-23 20:55:21 +03:00
*
* Validate that the given value match Nmtoken production
*
* [ VC : Name Token ]
*
* returns 1 if valid or 0 otherwise
*/
2002-04-14 16:56:08 +04:00
int
2001-02-23 20:55:21 +03:00
xmlValidateNmtokenValue ( const xmlChar * value ) {
const xmlChar * cur ;
2002-01-13 18:43:22 +03:00
int val , len ;
2001-02-23 20:55:21 +03:00
if ( value = = NULL ) return ( 0 ) ;
cur = value ;
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
2001-02-23 20:55:21 +03:00
2002-01-13 18:43:22 +03:00
if ( ! IS_LETTER ( val ) & & ! IS_DIGIT ( val ) & &
( val ! = ' . ' ) & & ( val ! = ' - ' ) & &
( val ! = ' _ ' ) & & ( val ! = ' : ' ) & &
( ! IS_COMBINING ( val ) ) & &
( ! IS_EXTENDER ( val ) ) )
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
2002-01-13 18:43:22 +03:00
while ( ( IS_LETTER ( val ) ) | | ( IS_DIGIT ( val ) ) | |
( val = = ' . ' ) | | ( val = = ' - ' ) | |
( val = = ' _ ' ) | | ( val = = ' : ' ) | |
( IS_COMBINING ( val ) ) | |
( IS_EXTENDER ( val ) ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2001-02-23 20:55:21 +03:00
2002-01-13 18:43:22 +03:00
if ( val ! = 0 ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
}
/**
* xmlValidateNmtokensValue :
2001-12-31 19:16:02 +03:00
* @ value : an Nmtokens value
2001-02-23 20:55:21 +03:00
*
* Validate that the given value match Nmtokens production
*
* [ VC : Name Token ]
*
* returns 1 if valid or 0 otherwise
*/
2002-04-14 16:56:08 +04:00
int
2001-02-23 20:55:21 +03:00
xmlValidateNmtokensValue ( const xmlChar * value ) {
const xmlChar * cur ;
2002-01-13 18:43:22 +03:00
int val , len ;
2001-02-23 20:55:21 +03:00
if ( value = = NULL ) return ( 0 ) ;
cur = value ;
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
2001-02-23 20:55:21 +03:00
2002-01-13 18:43:22 +03:00
while ( IS_BLANK ( val ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
if ( ! IS_LETTER ( val ) & & ! IS_DIGIT ( val ) & &
( val ! = ' . ' ) & & ( val ! = ' - ' ) & &
( val ! = ' _ ' ) & & ( val ! = ' : ' ) & &
( ! IS_COMBINING ( val ) ) & &
( ! IS_EXTENDER ( val ) ) )
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
2002-01-13 18:43:22 +03:00
while ( ( IS_LETTER ( val ) ) | | ( IS_DIGIT ( val ) ) | |
( val = = ' . ' ) | | ( val = = ' - ' ) | |
( val = = ' _ ' ) | | ( val = = ' : ' ) | |
( IS_COMBINING ( val ) ) | |
( IS_EXTENDER ( val ) ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2004-09-26 18:42:56 +04:00
/* Should not test IS_BLANK(val) here -- see erratum E20*/
while ( val = = 0x20 ) {
while ( val = = 0x20 ) {
2002-01-13 18:43:22 +03:00
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
if ( val = = 0 ) return ( 1 ) ;
if ( ! IS_LETTER ( val ) & & ! IS_DIGIT ( val ) & &
( val ! = ' . ' ) & & ( val ! = ' - ' ) & &
( val ! = ' _ ' ) & & ( val ! = ' : ' ) & &
( ! IS_COMBINING ( val ) ) & &
( ! IS_EXTENDER ( val ) ) )
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
2002-01-13 18:43:22 +03:00
while ( ( IS_LETTER ( val ) ) | | ( IS_DIGIT ( val ) ) | |
( val = = ' . ' ) | | ( val = = ' - ' ) | |
( val = = ' _ ' ) | | ( val = = ' : ' ) | |
( IS_COMBINING ( val ) ) | |
( IS_EXTENDER ( val ) ) ) {
val = xmlStringCurrentChar ( NULL , cur , & len ) ;
cur + = len ;
}
2001-02-23 20:55:21 +03:00
}
2002-01-13 18:43:22 +03:00
if ( val ! = 0 ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
return ( 1 ) ;
}
/**
* xmlValidateNotationDecl :
* @ ctxt : the validation context
* @ doc : a document instance
* @ nota : a notation definition
*
* Try to validate a single notation definition
* basically it does the following checks as described by the
* XML - 1.0 recommendation :
2001-12-31 19:16:02 +03:00
* - it seems that no validity constraint exists on notation declarations
2001-02-23 20:55:21 +03:00
* But this function get called anyway . . .
*
* returns 1 if valid or 0 otherwise
*/
int
2001-03-26 20:28:29 +04:00
xmlValidateNotationDecl ( xmlValidCtxtPtr ctxt ATTRIBUTE_UNUSED , xmlDocPtr doc ATTRIBUTE_UNUSED ,
xmlNotationPtr nota ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
int ret = 1 ;
return ( ret ) ;
}
/**
* xmlValidateAttributeValue :
* @ type : an attribute type
* @ value : an attribute value
*
* Validate that the given attribute value match the proper production
*
* [ VC : ID ]
* Values of type ID must match the Name production . . . .
*
* [ VC : IDREF ]
* Values of type IDREF must match the Name production , and values
* of type IDREFS must match Names . . .
*
* [ VC : Entity Name ]
* Values of type ENTITY must match the Name production , values
* of type ENTITIES must match Names . . .
*
* [ VC : Name Token ]
* Values of type NMTOKEN must match the Nmtoken production ; values
* of type NMTOKENS must match Nmtokens .
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateAttributeValue ( xmlAttributeType type , const xmlChar * value ) {
switch ( type ) {
case XML_ATTRIBUTE_ENTITIES :
case XML_ATTRIBUTE_IDREFS :
return ( xmlValidateNamesValue ( value ) ) ;
case XML_ATTRIBUTE_ENTITY :
case XML_ATTRIBUTE_IDREF :
case XML_ATTRIBUTE_ID :
case XML_ATTRIBUTE_NOTATION :
return ( xmlValidateNameValue ( value ) ) ;
case XML_ATTRIBUTE_NMTOKENS :
case XML_ATTRIBUTE_ENUMERATION :
return ( xmlValidateNmtokensValue ( value ) ) ;
case XML_ATTRIBUTE_NMTOKEN :
return ( xmlValidateNmtokenValue ( value ) ) ;
case XML_ATTRIBUTE_CDATA :
break ;
}
return ( 1 ) ;
}
/**
* xmlValidateAttributeValue2 :
* @ ctxt : the validation context
* @ doc : the document
* @ name : the attribute name ( used for error reporting only )
* @ type : the attribute type
* @ value : the attribute value
*
* Validate that the given attribute value match a given type .
* This typically cannot be done before having finished parsing
* the subsets .
*
* [ VC : IDREF ]
* Values of type IDREF must match one of the declared IDs
* Values of type IDREFS must match a sequence of the declared IDs
* each Name must match the value of an ID attribute on some element
* in the XML document ; i . e . IDREF values must match the value of
* some ID attribute
*
* [ VC : Entity Name ]
* Values of type ENTITY must match one declared entity
* Values of type ENTITIES must match a sequence of declared entities
*
* [ VC : Notation Attributes ]
* all notation names in the declaration must be declared .
*
* returns 1 if valid or 0 otherwise
*/
2001-03-24 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlValidateAttributeValue2 ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
const xmlChar * name , xmlAttributeType type , const xmlChar * value ) {
int ret = 1 ;
switch ( type ) {
case XML_ATTRIBUTE_IDREFS :
case XML_ATTRIBUTE_IDREF :
case XML_ATTRIBUTE_ID :
case XML_ATTRIBUTE_NMTOKENS :
case XML_ATTRIBUTE_ENUMERATION :
case XML_ATTRIBUTE_NMTOKEN :
case XML_ATTRIBUTE_CDATA :
break ;
case XML_ATTRIBUTE_ENTITY : {
xmlEntityPtr ent ;
ent = xmlGetDocEntity ( doc , value ) ;
2003-09-15 16:56:36 +04:00
/* yeah it's a bit messy... */
2002-02-19 16:46:09 +03:00
if ( ( ent = = NULL ) & & ( doc - > standalone = = 1 ) ) {
doc - > standalone = 0 ;
ent = xmlGetDocEntity ( doc , value ) ;
}
2001-02-23 20:55:21 +03:00
if ( ent = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) doc ,
XML_DTD_UNKNOWN_ENTITY ,
2001-02-23 20:55:21 +03:00
" ENTITY attribute %s reference an unknown entity \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
name , value , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
} else if ( ent - > etype ! = XML_EXTERNAL_GENERAL_UNPARSED_ENTITY ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) doc ,
XML_DTD_ENTITY_TYPE ,
2001-02-23 20:55:21 +03:00
" ENTITY attribute %s reference an entity \" %s \" of wrong type \n " ,
2003-10-04 02:21:51 +04:00
name , value , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
break ;
}
case XML_ATTRIBUTE_ENTITIES : {
xmlChar * dup , * nam = NULL , * cur , save ;
xmlEntityPtr ent ;
dup = xmlStrdup ( value ) ;
if ( dup = = NULL )
return ( 0 ) ;
cur = dup ;
while ( * cur ! = 0 ) {
nam = cur ;
2003-10-18 20:20:14 +04:00
while ( ( * cur ! = 0 ) & & ( ! IS_BLANK_CH ( * cur ) ) ) cur + + ;
2001-02-23 20:55:21 +03:00
save = * cur ;
* cur = 0 ;
ent = xmlGetDocEntity ( doc , nam ) ;
if ( ent = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) doc ,
XML_DTD_UNKNOWN_ENTITY ,
2001-02-23 20:55:21 +03:00
" ENTITIES attribute %s reference an unknown entity \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
name , nam , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
} else if ( ent - > etype ! = XML_EXTERNAL_GENERAL_UNPARSED_ENTITY ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) doc ,
XML_DTD_ENTITY_TYPE ,
2001-02-23 20:55:21 +03:00
" ENTITIES attribute %s reference an entity \" %s \" of wrong type \n " ,
2003-10-04 02:21:51 +04:00
name , nam , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
if ( save = = 0 )
break ;
* cur = save ;
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2001-02-23 20:55:21 +03:00
}
xmlFree ( dup ) ;
break ;
}
case XML_ATTRIBUTE_NOTATION : {
xmlNotationPtr nota ;
nota = xmlGetDtdNotationDesc ( doc - > intSubset , value ) ;
if ( ( nota = = NULL ) & & ( doc - > extSubset ! = NULL ) )
nota = xmlGetDtdNotationDesc ( doc - > extSubset , value ) ;
if ( nota = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) doc ,
XML_DTD_UNKNOWN_NOTATION ,
2001-02-23 20:55:21 +03:00
" NOTATION attribute %s reference an unknown notation \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
name , value , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
break ;
}
}
return ( ret ) ;
}
2002-02-20 00:08:48 +03:00
/**
* xmlValidCtxtNormalizeAttributeValue :
* @ ctxt : the validation context
* @ doc : the document
* @ elem : the parent
* @ name : the attribute name
* @ value : the attribute value
* @ ctxt : the validation context or NULL
*
* Does the validation related extra step of the normalization of attribute
* values :
*
* If the declared value is not CDATA , then the XML processor must further
* process the normalized attribute value by discarding any leading and
* trailing space ( # x20 ) characters , and by replacing sequences of space
* ( # x20 ) characters by single space ( # x20 ) character .
*
* Also check VC : Standalone Document Declaration in P32 , and update
* ctxt - > valid accordingly
*
* returns a new normalized string if normalization is needed , NULL otherwise
* the caller must free the returned value .
*/
xmlChar *
xmlValidCtxtNormalizeAttributeValue ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlNodePtr elem , const xmlChar * name , const xmlChar * value ) {
xmlChar * ret , * dst ;
const xmlChar * src ;
xmlAttributePtr attrDecl = NULL ;
int extsubset = 0 ;
if ( doc = = NULL ) return ( NULL ) ;
if ( elem = = NULL ) return ( NULL ) ;
if ( name = = NULL ) return ( NULL ) ;
if ( value = = NULL ) return ( NULL ) ;
if ( ( elem - > ns ! = NULL ) & & ( elem - > ns - > prefix ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( elem - > name , elem - > ns - > prefix , fn , 50 ) ;
if ( fullname = = NULL )
2005-07-29 03:49:35 +04:00
return ( NULL ) ;
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , fullname , name ) ;
2002-02-20 00:08:48 +03:00
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , fullname , name ) ;
2002-02-20 00:08:48 +03:00
if ( attrDecl ! = NULL )
extsubset = 1 ;
}
2003-04-07 14:22:39 +04:00
if ( ( fullname ! = fn ) & & ( fullname ! = elem - > name ) )
xmlFree ( fullname ) ;
2002-02-20 00:08:48 +03:00
}
if ( ( attrDecl = = NULL ) & & ( doc - > intSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , elem - > name , name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) ) {
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , elem - > name , name ) ;
if ( attrDecl ! = NULL )
extsubset = 1 ;
}
if ( attrDecl = = NULL )
return ( NULL ) ;
if ( attrDecl - > atype = = XML_ATTRIBUTE_CDATA )
return ( NULL ) ;
ret = xmlStrdup ( value ) ;
if ( ret = = NULL )
return ( NULL ) ;
src = value ;
dst = ret ;
while ( * src = = 0x20 ) src + + ;
while ( * src ! = 0 ) {
if ( * src = = 0x20 ) {
while ( * src = = 0x20 ) src + + ;
if ( * src ! = 0 )
* dst + + = 0x20 ;
} else {
* dst + + = * src + + ;
}
}
* dst = 0 ;
if ( ( doc - > standalone ) & & ( extsubset = = 1 ) & & ( ! xmlStrEqual ( value , ret ) ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_NOT_STANDALONE ,
2002-02-20 00:08:48 +03:00
" standalone: %s on %s value had to be normalized based on external subset declaration \n " ,
2003-10-04 02:21:51 +04:00
name , elem - > name , NULL ) ;
2002-02-20 00:08:48 +03:00
ctxt - > valid = 0 ;
}
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlValidNormalizeAttributeValue :
* @ doc : the document
* @ elem : the parent
* @ name : the attribute name
* @ value : the attribute value
*
* Does the validation related extra step of the normalization of attribute
* values :
*
* If the declared value is not CDATA , then the XML processor must further
* process the normalized attribute value by discarding any leading and
* trailing space ( # x20 ) characters , and by replacing sequences of space
* ( # x20 ) characters by single space ( # x20 ) character .
*
2003-09-29 22:02:38 +04:00
* Returns a new normalized string if normalization is needed , NULL otherwise
2001-02-23 20:55:21 +03:00
* the caller must free the returned value .
*/
xmlChar *
xmlValidNormalizeAttributeValue ( xmlDocPtr doc , xmlNodePtr elem ,
const xmlChar * name , const xmlChar * value ) {
xmlChar * ret , * dst ;
const xmlChar * src ;
xmlAttributePtr attrDecl = NULL ;
if ( doc = = NULL ) return ( NULL ) ;
if ( elem = = NULL ) return ( NULL ) ;
if ( name = = NULL ) return ( NULL ) ;
if ( value = = NULL ) return ( NULL ) ;
if ( ( elem - > ns ! = NULL ) & & ( elem - > ns - > prefix ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( elem - > name , elem - > ns - > prefix , fn , 50 ) ;
if ( fullname = = NULL )
2005-07-29 03:49:35 +04:00
return ( NULL ) ;
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , fullname , name ) ;
2001-02-23 20:55:21 +03:00
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , fullname , name ) ;
if ( ( fullname ! = fn ) & & ( fullname ! = elem - > name ) )
xmlFree ( fullname ) ;
2001-02-23 20:55:21 +03:00
}
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , elem - > name , name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , elem - > name , name ) ;
if ( attrDecl = = NULL )
return ( NULL ) ;
if ( attrDecl - > atype = = XML_ATTRIBUTE_CDATA )
return ( NULL ) ;
ret = xmlStrdup ( value ) ;
if ( ret = = NULL )
return ( NULL ) ;
src = value ;
dst = ret ;
while ( * src = = 0x20 ) src + + ;
while ( * src ! = 0 ) {
if ( * src = = 0x20 ) {
while ( * src = = 0x20 ) src + + ;
if ( * src ! = 0 )
* dst + + = 0x20 ;
} else {
* dst + + = * src + + ;
}
}
* dst = 0 ;
return ( ret ) ;
}
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlValidateAttributeIdCallback ( xmlAttributePtr attr , int * count ,
2001-03-26 20:28:29 +04:00
const xmlChar * name ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
if ( attr - > atype = = XML_ATTRIBUTE_ID ) ( * count ) + + ;
}
/**
* xmlValidateAttributeDecl :
* @ ctxt : the validation context
* @ doc : a document instance
* @ attr : an attribute definition
*
* Try to validate a single attribute definition
* basically it does the following checks as described by the
* XML - 1.0 recommendation :
* - [ VC : Attribute Default Legal ]
* - [ VC : Enumeration ]
* - [ VC : ID Attribute Default ]
*
* The ID / IDREF uniqueness and matching are done separately
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateAttributeDecl ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlAttributePtr attr ) {
int ret = 1 ;
int val ;
CHECK_DTD ;
if ( attr = = NULL ) return ( 1 ) ;
/* Attribute Default Legal */
/* Enumeration */
if ( attr - > defaultValue ! = NULL ) {
val = xmlValidateAttributeValue ( attr - > atype , attr - > defaultValue ) ;
if ( val = = 0 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) attr , XML_DTD_ATTRIBUTE_DEFAULT ,
2002-08-03 02:19:49 +04:00
" Syntax of default value for attribute %s of %s is not valid \n " ,
2003-10-04 02:21:51 +04:00
attr - > name , attr - > elem , NULL ) ;
2001-02-23 20:55:21 +03:00
}
ret & = val ;
}
/* ID Attribute Default */
if ( ( attr - > atype = = XML_ATTRIBUTE_ID ) & &
( attr - > def ! = XML_ATTRIBUTE_IMPLIED ) & &
( attr - > def ! = XML_ATTRIBUTE_REQUIRED ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) attr , XML_DTD_ID_FIXED ,
2002-08-03 02:19:49 +04:00
" ID attribute %s of %s is not valid must be #IMPLIED or #REQUIRED \n " ,
2003-10-04 02:21:51 +04:00
attr - > name , attr - > elem , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
/* One ID per Element Type */
if ( attr - > atype = = XML_ATTRIBUTE_ID ) {
int nbId ;
2001-12-31 19:16:02 +03:00
/* the trick is that we parse DtD as their own internal subset */
2001-02-23 20:55:21 +03:00
xmlElementPtr elem = xmlGetDtdElementDesc ( doc - > intSubset ,
attr - > elem ) ;
if ( elem ! = NULL ) {
2005-06-27 17:42:57 +04:00
nbId = xmlScanIDAttributeDecl ( NULL , elem , 0 ) ;
2001-02-23 20:55:21 +03:00
} else {
xmlAttributeTablePtr table ;
/*
* The attribute may be declared in the internal subset and the
* element in the external subset .
*/
nbId = 0 ;
2006-03-10 03:36:23 +03:00
if ( doc - > intSubset ! = NULL ) {
table = ( xmlAttributeTablePtr ) doc - > intSubset - > attributes ;
xmlHashScan3 ( table , NULL , NULL , attr - > elem , ( xmlHashScanner )
xmlValidateAttributeIdCallback , & nbId ) ;
}
2001-02-23 20:55:21 +03:00
}
if ( nbId > 1 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNodeNr ( ctxt , ( xmlNodePtr ) attr , XML_DTD_ID_SUBSET ,
2001-02-23 20:55:21 +03:00
" Element %s has %d ID attribute defined in the internal subset : %s \n " ,
attr - > elem , nbId , attr - > name ) ;
} else if ( doc - > extSubset ! = NULL ) {
int extId = 0 ;
elem = xmlGetDtdElementDesc ( doc - > extSubset , attr - > elem ) ;
if ( elem ! = NULL ) {
2005-06-27 17:42:57 +04:00
extId = xmlScanIDAttributeDecl ( NULL , elem , 0 ) ;
2001-02-23 20:55:21 +03:00
}
if ( extId > 1 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNodeNr ( ctxt , ( xmlNodePtr ) attr , XML_DTD_ID_SUBSET ,
2001-02-23 20:55:21 +03:00
" Element %s has %d ID attribute defined in the external subset : %s \n " ,
attr - > elem , extId , attr - > name ) ;
} else if ( extId + nbId > 1 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) attr , XML_DTD_ID_SUBSET ,
2001-02-23 20:55:21 +03:00
" Element %s has ID attributes defined in the internal and external subset : %s \n " ,
2003-10-04 02:21:51 +04:00
attr - > elem , attr - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
}
}
}
/* Validity Constraint: Enumeration */
if ( ( attr - > defaultValue ! = NULL ) & & ( attr - > tree ! = NULL ) ) {
xmlEnumerationPtr tree = attr - > tree ;
while ( tree ! = NULL ) {
if ( xmlStrEqual ( tree - > name , attr - > defaultValue ) ) break ;
tree = tree - > next ;
}
if ( tree = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) attr , XML_DTD_ATTRIBUTE_VALUE ,
2002-08-03 02:19:49 +04:00
" Default value \" %s \" for attribute %s of %s is not among the enumerated set \n " ,
2001-02-23 20:55:21 +03:00
attr - > defaultValue , attr - > name , attr - > elem ) ;
ret = 0 ;
}
}
return ( ret ) ;
}
/**
* xmlValidateElementDecl :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element definition
*
* Try to validate a single element definition
* basically it does the following checks as described by the
* XML - 1.0 recommendation :
* - [ VC : One ID per Element Type ]
* - [ VC : No Duplicate Types ]
* - [ VC : Unique Element Type Declaration ]
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateElementDecl ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlElementPtr elem ) {
int ret = 1 ;
xmlElementPtr tst ;
CHECK_DTD ;
if ( elem = = NULL ) return ( 1 ) ;
2002-09-18 20:29:02 +04:00
#if 0
2002-09-16 14:51:38 +04:00
# ifdef LIBXML_REGEXP_ENABLED
/* Build the regexp associated to the content model */
ret = xmlValidBuildContentModel ( ctxt , elem ) ;
2002-09-18 20:29:02 +04:00
# endif
2002-09-16 14:51:38 +04:00
# endif
2001-02-23 20:55:21 +03:00
/* No Duplicate Types */
if ( elem - > etype = = XML_ELEMENT_TYPE_MIXED ) {
xmlElementContentPtr cur , next ;
const xmlChar * name ;
cur = elem - > content ;
while ( cur ! = NULL ) {
if ( cur - > type ! = XML_ELEMENT_CONTENT_OR ) break ;
if ( cur - > c1 = = NULL ) break ;
if ( cur - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
name = cur - > c1 - > name ;
next = cur - > c2 ;
while ( next ! = NULL ) {
if ( next - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
2003-08-04 02:58:54 +04:00
if ( ( xmlStrEqual ( next - > name , name ) ) & &
( xmlStrEqual ( next - > prefix , cur - > prefix ) ) ) {
if ( cur - > prefix = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_CONTENT_ERROR ,
2001-02-23 20:55:21 +03:00
" Definition of %s has duplicate references of %s \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , name , NULL ) ;
2003-08-04 02:58:54 +04:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_CONTENT_ERROR ,
2003-08-04 02:58:54 +04:00
" Definition of %s has duplicate references of %s:%s \n " ,
elem - > name , cur - > prefix , name ) ;
}
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
break ;
}
if ( next - > c1 = = NULL ) break ;
if ( next - > c1 - > type ! = XML_ELEMENT_CONTENT_ELEMENT ) break ;
2003-08-04 02:58:54 +04:00
if ( ( xmlStrEqual ( next - > c1 - > name , name ) ) & &
( xmlStrEqual ( next - > c1 - > prefix , cur - > prefix ) ) ) {
if ( cur - > prefix = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_CONTENT_ERROR ,
2003-08-04 02:58:54 +04:00
" Definition of %s has duplicate references to %s \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , name , NULL ) ;
2003-08-04 02:58:54 +04:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_CONTENT_ERROR ,
2003-08-04 02:58:54 +04:00
" Definition of %s has duplicate references to %s:%s \n " ,
elem - > name , cur - > prefix , name ) ;
}
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
next = next - > c2 ;
}
}
cur = cur - > c2 ;
}
}
/* VC: Unique Element Type Declaration */
tst = xmlGetDtdElementDesc ( doc - > intSubset , elem - > name ) ;
2001-04-18 17:09:01 +04:00
if ( ( tst ! = NULL ) & & ( tst ! = elem ) & &
2001-11-09 02:36:42 +03:00
( ( tst - > prefix = = elem - > prefix ) | |
( xmlStrEqual ( tst - > prefix , elem - > prefix ) ) ) & &
2001-04-18 17:09:01 +04:00
( tst - > etype ! = XML_ELEMENT_TYPE_UNDEFINED ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_ELEM_REDEFINED ,
" Redefinition of element %s \n " ,
elem - > name , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
tst = xmlGetDtdElementDesc ( doc - > extSubset , elem - > name ) ;
2001-04-18 17:09:01 +04:00
if ( ( tst ! = NULL ) & & ( tst ! = elem ) & &
2001-11-09 02:36:42 +03:00
( ( tst - > prefix = = elem - > prefix ) | |
( xmlStrEqual ( tst - > prefix , elem - > prefix ) ) ) & &
2001-04-18 17:09:01 +04:00
( tst - > etype ! = XML_ELEMENT_TYPE_UNDEFINED ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , ( xmlNodePtr ) elem , XML_DTD_ELEM_REDEFINED ,
" Redefinition of element %s \n " ,
elem - > name , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
2001-04-18 17:09:01 +04:00
/* One ID per Element Type
* already done when registering the attribute
2001-02-23 20:55:21 +03:00
if ( xmlScanIDAttributeDecl ( ctxt , elem ) > 1 ) {
ret = 0 ;
2001-04-18 17:09:01 +04:00
} */
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
/**
* xmlValidateOneAttribute :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
* @ attr : an attribute instance
* @ value : the attribute value ( without entities processing )
*
* Try to validate a single attribute for an element
* basically it does the following checks as described by the
* XML - 1.0 recommendation :
* - [ VC : Attribute Value Type ]
* - [ VC : Fixed Attribute Default ]
* - [ VC : Entity Name ]
* - [ VC : Name Token ]
* - [ VC : ID ]
* - [ VC : IDREF ]
* - [ VC : Entity Name ]
* - [ VC : Notation Attributes ]
*
* The ID / IDREF uniqueness and matching are done separately
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateOneAttribute ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
2003-09-10 14:51:05 +04:00
xmlNodePtr elem , xmlAttrPtr attr , const xmlChar * value )
{
2001-02-23 20:55:21 +03:00
xmlAttributePtr attrDecl = NULL ;
int val ;
int ret = 1 ;
CHECK_DTD ;
if ( ( elem = = NULL ) | | ( elem - > name = = NULL ) ) return ( 0 ) ;
if ( ( attr = = NULL ) | | ( attr - > name = = NULL ) ) return ( 0 ) ;
if ( ( elem - > ns ! = NULL ) & & ( elem - > ns - > prefix ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( elem - > name , elem - > ns - > prefix , fn , 50 ) ;
if ( fullname = = NULL )
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
if ( attr - > ns ! = NULL ) {
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdQAttrDesc ( doc - > intSubset , fullname ,
2001-02-23 20:55:21 +03:00
attr - > name , attr - > ns - > prefix ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdQAttrDesc ( doc - > extSubset , fullname ,
2001-02-23 20:55:21 +03:00
attr - > name , attr - > ns - > prefix ) ;
} else {
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , fullname , attr - > name ) ;
2001-02-23 20:55:21 +03:00
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset ,
2003-04-07 14:22:39 +04:00
fullname , attr - > name ) ;
2001-02-23 20:55:21 +03:00
}
2003-04-07 14:22:39 +04:00
if ( ( fullname ! = fn ) & & ( fullname ! = elem - > name ) )
xmlFree ( fullname ) ;
2001-02-23 20:55:21 +03:00
}
if ( attrDecl = = NULL ) {
if ( attr - > ns ! = NULL ) {
attrDecl = xmlGetDtdQAttrDesc ( doc - > intSubset , elem - > name ,
attr - > name , attr - > ns - > prefix ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdQAttrDesc ( doc - > extSubset , elem - > name ,
attr - > name , attr - > ns - > prefix ) ;
} else {
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset ,
elem - > name , attr - > name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset ,
elem - > name , attr - > name ) ;
}
}
/* Validity Constraint: Attribute Value Type */
if ( attrDecl = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_ATTRIBUTE ,
2002-08-03 02:19:49 +04:00
" No declaration for attribute %s of element %s \n " ,
2003-10-04 02:21:51 +04:00
attr - > name , elem - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
attr - > atype = attrDecl - > atype ;
val = xmlValidateAttributeValue ( attrDecl - > atype , value ) ;
if ( val = = 0 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_VALUE ,
2002-08-03 02:19:49 +04:00
" Syntax of value for attribute %s of %s is not valid \n " ,
2003-10-04 02:21:51 +04:00
attr - > name , elem - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
/* Validity constraint: Fixed Attribute Default */
if ( attrDecl - > def = = XML_ATTRIBUTE_FIXED ) {
if ( ! xmlStrEqual ( value , attrDecl - > defaultValue ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_DEFAULT ,
2002-08-03 02:19:49 +04:00
" Value for attribute %s of %s is different from default \" %s \" \n " ,
2001-02-23 20:55:21 +03:00
attr - > name , elem - > name , attrDecl - > defaultValue ) ;
ret = 0 ;
}
}
/* Validity Constraint: ID uniqueness */
if ( attrDecl - > atype = = XML_ATTRIBUTE_ID ) {
if ( xmlAddID ( ctxt , doc , value , attr ) = = NULL )
ret = 0 ;
}
if ( ( attrDecl - > atype = = XML_ATTRIBUTE_IDREF ) | |
( attrDecl - > atype = = XML_ATTRIBUTE_IDREFS ) ) {
if ( xmlAddRef ( ctxt , doc , value , attr ) = = NULL )
ret = 0 ;
}
/* Validity Constraint: Notation Attributes */
if ( attrDecl - > atype = = XML_ATTRIBUTE_NOTATION ) {
xmlEnumerationPtr tree = attrDecl - > tree ;
xmlNotationPtr nota ;
/* First check that the given NOTATION was declared */
nota = xmlGetDtdNotationDesc ( doc - > intSubset , value ) ;
if ( nota = = NULL )
nota = xmlGetDtdNotationDesc ( doc - > extSubset , value ) ;
if ( nota = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_NOTATION ,
2002-08-03 02:19:49 +04:00
" Value \" %s \" for attribute %s of %s is not a declared Notation \n " ,
2001-02-23 20:55:21 +03:00
value , attr - > name , elem - > name ) ;
ret = 0 ;
}
/* Second, verify that it's among the list */
while ( tree ! = NULL ) {
if ( xmlStrEqual ( tree - > name , value ) ) break ;
tree = tree - > next ;
}
if ( tree = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_NOTATION_VALUE ,
2002-08-03 02:19:49 +04:00
" Value \" %s \" for attribute %s of %s is not among the enumerated notations \n " ,
2001-02-23 20:55:21 +03:00
value , attr - > name , elem - > name ) ;
ret = 0 ;
}
}
/* Validity Constraint: Enumeration */
if ( attrDecl - > atype = = XML_ATTRIBUTE_ENUMERATION ) {
xmlEnumerationPtr tree = attrDecl - > tree ;
while ( tree ! = NULL ) {
if ( xmlStrEqual ( tree - > name , value ) ) break ;
tree = tree - > next ;
}
if ( tree = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_VALUE ,
2002-08-03 02:19:49 +04:00
" Value \" %s \" for attribute %s of %s is not among the enumerated set \n " ,
2001-02-23 20:55:21 +03:00
value , attr - > name , elem - > name ) ;
ret = 0 ;
}
}
/* Fixed Attribute Default */
if ( ( attrDecl - > def = = XML_ATTRIBUTE_FIXED ) & &
( ! xmlStrEqual ( attrDecl - > defaultValue , value ) ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_VALUE ,
2002-08-03 02:19:49 +04:00
" Value for attribute %s of %s must be \" %s \" \n " ,
2001-02-23 20:55:21 +03:00
attr - > name , elem - > name , attrDecl - > defaultValue ) ;
ret = 0 ;
}
/* Extra check for the attribute value */
ret & = xmlValidateAttributeValue2 ( ctxt , doc , attr - > name ,
attrDecl - > atype , value ) ;
return ( ret ) ;
}
2002-09-26 20:10:21 +04:00
/**
* xmlValidateOneNamespace :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
2002-12-11 17:23:49 +03:00
* @ prefix : the namespace prefix
2002-09-26 20:10:21 +04:00
* @ ns : an namespace declaration instance
* @ value : the attribute value ( without entities processing )
*
* Try to validate a single namespace declaration for an element
* basically it does the following checks as described by the
* XML - 1.0 recommendation :
* - [ VC : Attribute Value Type ]
* - [ VC : Fixed Attribute Default ]
* - [ VC : Entity Name ]
* - [ VC : Name Token ]
* - [ VC : ID ]
* - [ VC : IDREF ]
* - [ VC : Entity Name ]
* - [ VC : Notation Attributes ]
*
* The ID / IDREF uniqueness and matching are done separately
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateOneNamespace ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlNodePtr elem , const xmlChar * prefix , xmlNsPtr ns , const xmlChar * value ) {
/* xmlElementPtr elemDecl; */
xmlAttributePtr attrDecl = NULL ;
int val ;
int ret = 1 ;
CHECK_DTD ;
if ( ( elem = = NULL ) | | ( elem - > name = = NULL ) ) return ( 0 ) ;
if ( ( ns = = NULL ) | | ( ns - > href = = NULL ) ) return ( 0 ) ;
if ( prefix ! = NULL ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( elem - > name , prefix , fn , 50 ) ;
if ( fullname = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " Validating namespace " ) ;
2003-04-07 14:22:39 +04:00
return ( 0 ) ;
}
2002-09-26 20:10:21 +04:00
if ( ns - > prefix ! = NULL ) {
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdQAttrDesc ( doc - > intSubset , fullname ,
2002-09-26 20:10:21 +04:00
ns - > prefix , BAD_CAST " xmlns " ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdQAttrDesc ( doc - > extSubset , fullname ,
2002-09-26 20:10:21 +04:00
ns - > prefix , BAD_CAST " xmlns " ) ;
} else {
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , fullname ,
2002-09-26 20:10:21 +04:00
BAD_CAST " xmlns " ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
2003-04-07 14:22:39 +04:00
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , fullname ,
2002-09-26 20:10:21 +04:00
BAD_CAST " xmlns " ) ;
}
2003-04-07 14:22:39 +04:00
if ( ( fullname ! = fn ) & & ( fullname ! = elem - > name ) )
xmlFree ( fullname ) ;
2002-09-26 20:10:21 +04:00
}
if ( attrDecl = = NULL ) {
if ( ns - > prefix ! = NULL ) {
attrDecl = xmlGetDtdQAttrDesc ( doc - > intSubset , elem - > name ,
ns - > prefix , BAD_CAST " xmlns " ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdQAttrDesc ( doc - > extSubset , elem - > name ,
ns - > prefix , BAD_CAST " xmlns " ) ;
} else {
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset ,
elem - > name , BAD_CAST " xmlns " ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset ,
elem - > name , BAD_CAST " xmlns " ) ;
}
}
/* Validity Constraint: Attribute Value Type */
if ( attrDecl = = NULL ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_ATTRIBUTE ,
2002-09-26 20:10:21 +04:00
" No declaration for attribute xmlns:%s of element %s \n " ,
2003-10-04 02:21:51 +04:00
ns - > prefix , elem - > name , NULL ) ;
2002-09-26 20:10:21 +04:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_ATTRIBUTE ,
2002-09-26 20:10:21 +04:00
" No declaration for attribute xmlns of element %s \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , NULL , NULL ) ;
2002-09-26 20:10:21 +04:00
}
return ( 0 ) ;
}
val = xmlValidateAttributeValue ( attrDecl - > atype , value ) ;
if ( val = = 0 ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_INVALID_DEFAULT ,
2002-09-26 20:10:21 +04:00
" Syntax of value for attribute xmlns:%s of %s is not valid \n " ,
2003-10-04 02:21:51 +04:00
ns - > prefix , elem - > name , NULL ) ;
2002-09-26 20:10:21 +04:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_INVALID_DEFAULT ,
2002-09-26 20:10:21 +04:00
" Syntax of value for attribute xmlns of %s is not valid \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , NULL , NULL ) ;
2002-09-26 20:10:21 +04:00
}
ret = 0 ;
}
/* Validity constraint: Fixed Attribute Default */
if ( attrDecl - > def = = XML_ATTRIBUTE_FIXED ) {
if ( ! xmlStrEqual ( value , attrDecl - > defaultValue ) ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_DEFAULT ,
2002-09-26 20:10:21 +04:00
" Value for attribute xmlns:%s of %s is different from default \" %s \" \n " ,
ns - > prefix , elem - > name , attrDecl - > defaultValue ) ;
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_DEFAULT ,
2002-09-26 20:10:21 +04:00
" Value for attribute xmlns of %s is different from default \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , attrDecl - > defaultValue , NULL ) ;
2002-09-26 20:10:21 +04:00
}
ret = 0 ;
}
}
/* Validity Constraint: ID uniqueness */
if ( attrDecl - > atype = = XML_ATTRIBUTE_ID ) {
if ( xmlAddID ( ctxt , doc , value , ( xmlAttrPtr ) ns ) = = NULL )
ret = 0 ;
}
if ( ( attrDecl - > atype = = XML_ATTRIBUTE_IDREF ) | |
( attrDecl - > atype = = XML_ATTRIBUTE_IDREFS ) ) {
if ( xmlAddRef ( ctxt , doc , value , ( xmlAttrPtr ) ns ) = = NULL )
ret = 0 ;
}
/* Validity Constraint: Notation Attributes */
if ( attrDecl - > atype = = XML_ATTRIBUTE_NOTATION ) {
xmlEnumerationPtr tree = attrDecl - > tree ;
xmlNotationPtr nota ;
/* First check that the given NOTATION was declared */
nota = xmlGetDtdNotationDesc ( doc - > intSubset , value ) ;
if ( nota = = NULL )
nota = xmlGetDtdNotationDesc ( doc - > extSubset , value ) ;
if ( nota = = NULL ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_NOTATION ,
2002-09-26 20:10:21 +04:00
" Value \" %s \" for attribute xmlns:%s of %s is not a declared Notation \n " ,
value , ns - > prefix , elem - > name ) ;
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_NOTATION ,
2002-09-26 20:10:21 +04:00
" Value \" %s \" for attribute xmlns of %s is not a declared Notation \n " ,
2003-10-04 02:21:51 +04:00
value , elem - > name , NULL ) ;
2002-09-26 20:10:21 +04:00
}
ret = 0 ;
}
/* Second, verify that it's among the list */
while ( tree ! = NULL ) {
if ( xmlStrEqual ( tree - > name , value ) ) break ;
tree = tree - > next ;
}
if ( tree = = NULL ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_NOTATION_VALUE ,
2002-09-26 20:10:21 +04:00
" Value \" %s \" for attribute xmlns:%s of %s is not among the enumerated notations \n " ,
value , ns - > prefix , elem - > name ) ;
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_NOTATION_VALUE ,
2002-09-26 20:10:21 +04:00
" Value \" %s \" for attribute xmlns of %s is not among the enumerated notations \n " ,
2003-10-04 02:21:51 +04:00
value , elem - > name , NULL ) ;
2002-09-26 20:10:21 +04:00
}
ret = 0 ;
}
}
/* Validity Constraint: Enumeration */
if ( attrDecl - > atype = = XML_ATTRIBUTE_ENUMERATION ) {
xmlEnumerationPtr tree = attrDecl - > tree ;
while ( tree ! = NULL ) {
if ( xmlStrEqual ( tree - > name , value ) ) break ;
tree = tree - > next ;
}
if ( tree = = NULL ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_VALUE ,
2002-09-26 20:10:21 +04:00
" Value \" %s \" for attribute xmlns:%s of %s is not among the enumerated set \n " ,
value , ns - > prefix , elem - > name ) ;
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ATTRIBUTE_VALUE ,
2002-09-26 20:10:21 +04:00
" Value \" %s \" for attribute xmlns of %s is not among the enumerated set \n " ,
2003-10-04 02:21:51 +04:00
value , elem - > name , NULL ) ;
2002-09-26 20:10:21 +04:00
}
ret = 0 ;
}
}
/* Fixed Attribute Default */
if ( ( attrDecl - > def = = XML_ATTRIBUTE_FIXED ) & &
( ! xmlStrEqual ( attrDecl - > defaultValue , value ) ) ) {
if ( ns - > prefix ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ELEM_NAMESPACE ,
2002-09-26 20:10:21 +04:00
" Value for attribute xmlns:%s of %s must be \" %s \" \n " ,
ns - > prefix , elem - > name , attrDecl - > defaultValue ) ;
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ELEM_NAMESPACE ,
2002-09-26 20:10:21 +04:00
" Value for attribute xmlns of %s must be \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , attrDecl - > defaultValue , NULL ) ;
2002-09-26 20:10:21 +04:00
}
ret = 0 ;
}
/* Extra check for the attribute value */
if ( ns - > prefix ! = NULL ) {
ret & = xmlValidateAttributeValue2 ( ctxt , doc , ns - > prefix ,
attrDecl - > atype , value ) ;
} else {
ret & = xmlValidateAttributeValue2 ( ctxt , doc , BAD_CAST " xmlns " ,
attrDecl - > atype , value ) ;
}
return ( ret ) ;
}
2002-09-24 18:13:13 +04:00
# ifndef LIBXML_REGEXP_ENABLED
2001-04-20 17:03:48 +04:00
/**
* xmlValidateSkipIgnorable :
* @ ctxt : the validation context
* @ child : the child list
*
* Skip ignorable elements w . r . t . the validation process
*
* returns the first element to consider for validation of the content model
*/
static xmlNodePtr
2001-04-21 14:28:59 +04:00
xmlValidateSkipIgnorable ( xmlNodePtr child ) {
2001-04-20 17:03:48 +04:00
while ( child ! = NULL ) {
switch ( child - > type ) {
/* These things are ignored (skipped) during validation. */
case XML_PI_NODE :
case XML_COMMENT_NODE :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
child = child - > next ;
break ;
case XML_TEXT_NODE :
if ( xmlIsBlankNode ( child ) )
child = child - > next ;
else
return ( child ) ;
break ;
/* keep current node */
default :
return ( child ) ;
}
}
return ( child ) ;
}
/**
* xmlValidateElementType :
* @ ctxt : the validation context
*
* Try to validate the content model of an element internal function
*
2001-05-08 00:50:47 +04:00
* returns 1 if valid or 0 , - 1 in case of error , - 2 if an entity
* reference is found and - 3 if the validation succeeded but
* the content model is not determinist .
2001-04-20 17:03:48 +04:00
*/
static int
xmlValidateElementType ( xmlValidCtxtPtr ctxt ) {
2001-11-20 12:37:09 +03:00
int ret = - 1 ;
2001-05-08 00:50:47 +04:00
int determinist = 1 ;
2001-04-20 17:03:48 +04:00
2001-04-21 14:28:59 +04:00
NODE = xmlValidateSkipIgnorable ( NODE ) ;
2001-04-20 17:03:48 +04:00
if ( ( NODE = = NULL ) & & ( CONT = = NULL ) )
return ( 1 ) ;
if ( ( NODE = = NULL ) & &
( ( CONT - > ocur = = XML_ELEMENT_CONTENT_MULT ) | |
( CONT - > ocur = = XML_ELEMENT_CONTENT_OPT ) ) ) {
return ( 1 ) ;
}
if ( CONT = = NULL ) return ( - 1 ) ;
2001-04-24 19:52:00 +04:00
if ( ( NODE ! = NULL ) & & ( NODE - > type = = XML_ENTITY_REF_NODE ) )
2001-04-21 14:28:59 +04:00
return ( - 2 ) ;
2001-04-20 17:03:48 +04:00
/*
* We arrive here when more states need to be examined
*/
cont :
/*
* We just recovered from a rollback generated by a possible
* epsilon transition , go directly to the analysis phase
*/
if ( STATE = = ROLLBACK_PARENT ) {
2001-12-31 19:16:02 +03:00
DEBUG_VALID_MSG ( " restored parent branch " ) ;
2001-04-20 17:03:48 +04:00
DEBUG_VALID_STATE ( NODE , CONT )
ret = 1 ;
goto analyze ;
}
DEBUG_VALID_STATE ( NODE , CONT )
/*
* we may have to save a backup state here . This is the equivalent
* of handling epsilon transition in NFAs .
*/
2001-05-15 12:53:16 +04:00
if ( ( CONT ! = NULL ) & &
2001-10-18 18:57:24 +04:00
( ( CONT - > parent = = NULL ) | |
( CONT - > parent - > type ! = XML_ELEMENT_CONTENT_OR ) ) & &
2001-04-20 17:03:48 +04:00
( ( CONT - > ocur = = XML_ELEMENT_CONTENT_MULT ) | |
2001-04-20 19:47:35 +04:00
( CONT - > ocur = = XML_ELEMENT_CONTENT_OPT ) | |
2001-12-31 19:37:34 +03:00
( ( CONT - > ocur = = XML_ELEMENT_CONTENT_PLUS ) & & ( OCCURRENCE ) ) ) ) {
2001-04-20 17:03:48 +04:00
DEBUG_VALID_MSG ( " saving parent branch " ) ;
2002-04-15 14:15:25 +04:00
if ( vstateVPush ( ctxt , CONT , NODE , DEPTH , OCCURS , ROLLBACK_PARENT ) < 0 )
return ( 0 ) ;
2001-04-20 17:03:48 +04:00
}
/*
* Check first if the content matches
*/
switch ( CONT - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
if ( NODE = = NULL ) {
DEBUG_VALID_MSG ( " pcdata failed no node " ) ;
ret = 0 ;
break ;
}
if ( NODE - > type = = XML_TEXT_NODE ) {
DEBUG_VALID_MSG ( " pcdata found, skip to next " ) ;
/*
* go to next element in the content model
* skipping ignorable elems
*/
do {
NODE = NODE - > next ;
2001-04-21 14:28:59 +04:00
NODE = xmlValidateSkipIgnorable ( NODE ) ;
if ( ( NODE ! = NULL ) & &
( NODE - > type = = XML_ENTITY_REF_NODE ) )
return ( - 2 ) ;
2001-04-20 17:03:48 +04:00
} while ( ( NODE ! = NULL ) & &
( ( NODE - > type ! = XML_ELEMENT_NODE ) & &
2002-02-19 17:18:08 +03:00
( NODE - > type ! = XML_TEXT_NODE ) & &
( NODE - > type ! = XML_CDATA_SECTION_NODE ) ) ) ;
2001-04-20 17:03:48 +04:00
ret = 1 ;
break ;
} else {
DEBUG_VALID_MSG ( " pcdata failed " ) ;
ret = 0 ;
break ;
}
break ;
case XML_ELEMENT_CONTENT_ELEMENT :
if ( NODE = = NULL ) {
DEBUG_VALID_MSG ( " element failed no node " ) ;
ret = 0 ;
break ;
}
2001-06-11 16:47:59 +04:00
ret = ( ( NODE - > type = = XML_ELEMENT_NODE ) & &
( xmlStrEqual ( NODE - > name , CONT - > name ) ) ) ;
2001-11-09 02:36:42 +03:00
if ( ret = = 1 ) {
if ( ( NODE - > ns = = NULL ) | | ( NODE - > ns - > prefix = = NULL ) ) {
ret = ( CONT - > prefix = = NULL ) ;
} else if ( CONT - > prefix = = NULL ) {
ret = 0 ;
} else {
ret = xmlStrEqual ( NODE - > ns - > prefix , CONT - > prefix ) ;
}
}
2001-04-20 17:03:48 +04:00
if ( ret = = 1 ) {
DEBUG_VALID_MSG ( " element found, skip to next " ) ;
/*
* go to next element in the content model
* skipping ignorable elems
*/
do {
NODE = NODE - > next ;
2001-04-21 14:28:59 +04:00
NODE = xmlValidateSkipIgnorable ( NODE ) ;
if ( ( NODE ! = NULL ) & &
( NODE - > type = = XML_ENTITY_REF_NODE ) )
return ( - 2 ) ;
2001-04-20 17:03:48 +04:00
} while ( ( NODE ! = NULL ) & &
( ( NODE - > type ! = XML_ELEMENT_NODE ) & &
2002-02-19 17:18:08 +03:00
( NODE - > type ! = XML_TEXT_NODE ) & &
( NODE - > type ! = XML_CDATA_SECTION_NODE ) ) ) ;
2001-04-20 17:03:48 +04:00
} else {
DEBUG_VALID_MSG ( " element failed " ) ;
ret = 0 ;
break ;
}
break ;
case XML_ELEMENT_CONTENT_OR :
2001-04-20 17:48:21 +04:00
/*
* Small optimization .
*/
if ( CONT - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
if ( ( NODE = = NULL ) | |
( ! xmlStrEqual ( NODE - > name , CONT - > c1 - > name ) ) ) {
DEPTH + + ;
CONT = CONT - > c2 ;
goto cont ;
}
2001-11-09 02:36:42 +03:00
if ( ( NODE - > ns = = NULL ) | | ( NODE - > ns - > prefix = = NULL ) ) {
ret = ( CONT - > c1 - > prefix = = NULL ) ;
} else if ( CONT - > c1 - > prefix = = NULL ) {
ret = 0 ;
} else {
ret = xmlStrEqual ( NODE - > ns - > prefix , CONT - > c1 - > prefix ) ;
}
if ( ret = = 0 ) {
DEPTH + + ;
CONT = CONT - > c2 ;
goto cont ;
}
2001-04-20 17:48:21 +04:00
}
2001-04-20 17:03:48 +04:00
/*
* save the second branch ' or ' branch
*/
DEBUG_VALID_MSG ( " saving 'or' branch " ) ;
2002-04-15 14:15:25 +04:00
if ( vstateVPush ( ctxt , CONT - > c2 , NODE , ( unsigned char ) ( DEPTH + 1 ) ,
OCCURS , ROLLBACK_OR ) < 0 )
return ( - 1 ) ;
2001-04-20 17:03:48 +04:00
DEPTH + + ;
CONT = CONT - > c1 ;
goto cont ;
case XML_ELEMENT_CONTENT_SEQ :
2001-06-09 20:41:01 +04:00
/*
* Small optimization .
*/
if ( ( CONT - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) & &
( ( CONT - > c1 - > ocur = = XML_ELEMENT_CONTENT_OPT ) | |
( CONT - > c1 - > ocur = = XML_ELEMENT_CONTENT_MULT ) ) ) {
if ( ( NODE = = NULL ) | |
( ! xmlStrEqual ( NODE - > name , CONT - > c1 - > name ) ) ) {
DEPTH + + ;
CONT = CONT - > c2 ;
goto cont ;
}
2001-11-09 02:36:42 +03:00
if ( ( NODE - > ns = = NULL ) | | ( NODE - > ns - > prefix = = NULL ) ) {
ret = ( CONT - > c1 - > prefix = = NULL ) ;
} else if ( CONT - > c1 - > prefix = = NULL ) {
ret = 0 ;
} else {
ret = xmlStrEqual ( NODE - > ns - > prefix , CONT - > c1 - > prefix ) ;
}
if ( ret = = 0 ) {
DEPTH + + ;
CONT = CONT - > c2 ;
goto cont ;
}
2001-06-09 20:41:01 +04:00
}
2001-04-20 17:03:48 +04:00
DEPTH + + ;
CONT = CONT - > c1 ;
goto cont ;
}
/*
* At this point handle going up in the tree
*/
if ( ret = = - 1 ) {
DEBUG_VALID_MSG ( " error found returning " ) ;
return ( ret ) ;
}
analyze :
while ( CONT ! = NULL ) {
/*
2001-12-31 19:16:02 +03:00
* First do the analysis depending on the occurrence model at
2001-04-20 17:03:48 +04:00
* this level .
*/
if ( ret = = 0 ) {
switch ( CONT - > ocur ) {
2001-05-08 00:50:47 +04:00
xmlNodePtr cur ;
2001-04-20 17:03:48 +04:00
case XML_ELEMENT_CONTENT_ONCE :
2001-05-08 00:50:47 +04:00
cur = ctxt - > vstate - > node ;
2001-04-20 17:03:48 +04:00
DEBUG_VALID_MSG ( " Once branch failed, rollback " ) ;
if ( vstateVPop ( ctxt ) < 0 ) {
DEBUG_VALID_MSG ( " exhaustion, failed " ) ;
return ( 0 ) ;
}
2001-05-08 00:50:47 +04:00
if ( cur ! = ctxt - > vstate - > node )
determinist = - 3 ;
2001-04-20 17:03:48 +04:00
goto cont ;
case XML_ELEMENT_CONTENT_PLUS :
2001-12-31 19:37:34 +03:00
if ( OCCURRENCE = = 0 ) {
2001-05-08 00:50:47 +04:00
cur = ctxt - > vstate - > node ;
2001-04-20 17:03:48 +04:00
DEBUG_VALID_MSG ( " Plus branch failed, rollback " ) ;
if ( vstateVPop ( ctxt ) < 0 ) {
DEBUG_VALID_MSG ( " exhaustion, failed " ) ;
return ( 0 ) ;
}
2001-05-08 00:50:47 +04:00
if ( cur ! = ctxt - > vstate - > node )
determinist = - 3 ;
2001-04-20 17:03:48 +04:00
goto cont ;
}
DEBUG_VALID_MSG ( " Plus branch found " ) ;
ret = 1 ;
break ;
case XML_ELEMENT_CONTENT_MULT :
# ifdef DEBUG_VALID_ALGO
2001-12-31 19:37:34 +03:00
if ( OCCURRENCE = = 0 ) {
2001-04-20 17:03:48 +04:00
DEBUG_VALID_MSG ( " Mult branch failed " ) ;
} else {
DEBUG_VALID_MSG ( " Mult branch found " ) ;
}
# endif
ret = 1 ;
break ;
case XML_ELEMENT_CONTENT_OPT :
DEBUG_VALID_MSG ( " Option branch failed " ) ;
ret = 1 ;
break ;
}
} else {
switch ( CONT - > ocur ) {
case XML_ELEMENT_CONTENT_OPT :
DEBUG_VALID_MSG ( " Option branch succeeded " ) ;
ret = 1 ;
break ;
case XML_ELEMENT_CONTENT_ONCE :
DEBUG_VALID_MSG ( " Once branch succeeded " ) ;
ret = 1 ;
break ;
case XML_ELEMENT_CONTENT_PLUS :
if ( STATE = = ROLLBACK_PARENT ) {
DEBUG_VALID_MSG ( " Plus branch rollback " ) ;
ret = 1 ;
break ;
}
if ( NODE = = NULL ) {
DEBUG_VALID_MSG ( " Plus branch exhausted " ) ;
ret = 1 ;
break ;
}
DEBUG_VALID_MSG ( " Plus branch succeeded, continuing " ) ;
2001-12-31 19:37:34 +03:00
SET_OCCURRENCE ;
2001-04-20 17:03:48 +04:00
goto cont ;
case XML_ELEMENT_CONTENT_MULT :
if ( STATE = = ROLLBACK_PARENT ) {
DEBUG_VALID_MSG ( " Mult branch rollback " ) ;
ret = 1 ;
break ;
}
if ( NODE = = NULL ) {
DEBUG_VALID_MSG ( " Mult branch exhausted " ) ;
ret = 1 ;
break ;
}
DEBUG_VALID_MSG ( " Mult branch succeeded, continuing " ) ;
2001-12-31 19:37:34 +03:00
/* SET_OCCURRENCE; */
2001-04-20 17:03:48 +04:00
goto cont ;
}
}
STATE = 0 ;
/*
* Then act accordingly at the parent level
*/
2001-12-31 19:37:34 +03:00
RESET_OCCURRENCE ;
2001-04-20 17:03:48 +04:00
if ( CONT - > parent = = NULL )
break ;
switch ( CONT - > parent - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
DEBUG_VALID_MSG ( " Error: parent pcdata " ) ;
return ( - 1 ) ;
case XML_ELEMENT_CONTENT_ELEMENT :
DEBUG_VALID_MSG ( " Error: parent element " ) ;
return ( - 1 ) ;
case XML_ELEMENT_CONTENT_OR :
if ( ret = = 1 ) {
DEBUG_VALID_MSG ( " Or succeeded " ) ;
CONT = CONT - > parent ;
DEPTH - - ;
} else {
DEBUG_VALID_MSG ( " Or failed " ) ;
CONT = CONT - > parent ;
DEPTH - - ;
}
break ;
case XML_ELEMENT_CONTENT_SEQ :
if ( ret = = 0 ) {
DEBUG_VALID_MSG ( " Sequence failed " ) ;
CONT = CONT - > parent ;
DEPTH - - ;
} else if ( CONT = = CONT - > parent - > c1 ) {
DEBUG_VALID_MSG ( " Sequence testing 2nd branch " ) ;
CONT = CONT - > parent - > c2 ;
goto cont ;
} else {
DEBUG_VALID_MSG ( " Sequence succeeded " ) ;
CONT = CONT - > parent ;
DEPTH - - ;
}
}
}
if ( NODE ! = NULL ) {
2001-05-08 00:50:47 +04:00
xmlNodePtr cur ;
cur = ctxt - > vstate - > node ;
2001-04-20 17:03:48 +04:00
DEBUG_VALID_MSG ( " Failed, remaining input, rollback " ) ;
if ( vstateVPop ( ctxt ) < 0 ) {
DEBUG_VALID_MSG ( " exhaustion, failed " ) ;
return ( 0 ) ;
}
2001-05-08 00:50:47 +04:00
if ( cur ! = ctxt - > vstate - > node )
determinist = - 3 ;
2001-04-20 17:03:48 +04:00
goto cont ;
}
if ( ret = = 0 ) {
2001-05-08 00:50:47 +04:00
xmlNodePtr cur ;
cur = ctxt - > vstate - > node ;
2001-04-20 17:03:48 +04:00
DEBUG_VALID_MSG ( " Failure, rollback " ) ;
if ( vstateVPop ( ctxt ) < 0 ) {
DEBUG_VALID_MSG ( " exhaustion, failed " ) ;
return ( 0 ) ;
}
2001-05-08 00:50:47 +04:00
if ( cur ! = ctxt - > vstate - > node )
determinist = - 3 ;
2001-04-20 17:03:48 +04:00
goto cont ;
}
2001-05-08 00:50:47 +04:00
return ( determinist ) ;
2001-04-20 17:03:48 +04:00
}
2002-09-19 23:56:43 +04:00
# endif
2001-04-20 17:03:48 +04:00
2001-04-21 18:16:10 +04:00
/**
2001-08-15 16:06:36 +04:00
* xmlSnprintfElements :
2001-04-21 18:16:10 +04:00
* @ buf : an output buffer
2001-08-15 16:06:36 +04:00
* @ size : the size of the buffer
2001-04-21 18:16:10 +04:00
* @ content : An element
* @ glob : 1 if one must print the englobing parenthesis , 0 otherwise
*
* This will dump the list of elements to the buffer
* Intended just for the debug routine
*/
static void
2001-08-15 16:06:36 +04:00
xmlSnprintfElements ( char * buf , int size , xmlNodePtr node , int glob ) {
2001-04-21 18:16:10 +04:00
xmlNodePtr cur ;
2001-08-15 16:06:36 +04:00
int len ;
2001-04-21 18:16:10 +04:00
if ( node = = NULL ) return ;
if ( glob ) strcat ( buf , " ( " ) ;
cur = node ;
while ( cur ! = NULL ) {
2001-08-15 16:06:36 +04:00
len = strlen ( buf ) ;
if ( size - len < 50 ) {
if ( ( size - len > 4 ) & & ( buf [ len - 1 ] ! = ' . ' ) )
strcat ( buf , " ... " ) ;
return ;
}
2001-04-21 18:16:10 +04:00
switch ( cur - > type ) {
case XML_ELEMENT_NODE :
2001-11-09 02:36:42 +03:00
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
2002-03-19 17:36:46 +03:00
if ( size - len < xmlStrlen ( cur - > ns - > prefix ) + 10 ) {
2001-11-09 02:36:42 +03:00
if ( ( size - len > 4 ) & & ( buf [ len - 1 ] ! = ' . ' ) )
strcat ( buf , " ... " ) ;
return ;
}
strcat ( buf , ( char * ) cur - > ns - > prefix ) ;
strcat ( buf , " : " ) ;
}
2002-03-19 17:36:46 +03:00
if ( size - len < xmlStrlen ( cur - > name ) + 10 ) {
2001-08-15 16:06:36 +04:00
if ( ( size - len > 4 ) & & ( buf [ len - 1 ] ! = ' . ' ) )
strcat ( buf , " ... " ) ;
return ;
}
strcat ( buf , ( char * ) cur - > name ) ;
if ( cur - > next ! = NULL )
strcat ( buf , " " ) ;
break ;
2001-04-21 18:16:10 +04:00
case XML_TEXT_NODE :
2001-08-15 16:06:36 +04:00
if ( xmlIsBlankNode ( cur ) )
break ;
2001-04-21 18:16:10 +04:00
case XML_CDATA_SECTION_NODE :
case XML_ENTITY_REF_NODE :
2001-08-15 16:06:36 +04:00
strcat ( buf , " CDATA " ) ;
if ( cur - > next ! = NULL )
strcat ( buf , " " ) ;
break ;
2001-04-21 18:16:10 +04:00
case XML_ATTRIBUTE_NODE :
case XML_DOCUMENT_NODE :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-04-21 18:16:10 +04:00
# endif
case XML_HTML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
case XML_NOTATION_NODE :
case XML_NAMESPACE_DECL :
2001-08-15 16:06:36 +04:00
strcat ( buf , " ??? " ) ;
if ( cur - > next ! = NULL )
strcat ( buf , " " ) ;
break ;
2001-04-21 18:16:10 +04:00
case XML_ENTITY_NODE :
case XML_PI_NODE :
case XML_DTD_NODE :
case XML_COMMENT_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-08-15 16:06:36 +04:00
break ;
2001-04-21 18:16:10 +04:00
}
cur = cur - > next ;
}
if ( glob ) strcat ( buf , " ) " ) ;
}
2001-04-20 17:03:48 +04:00
/**
* xmlValidateElementContent :
* @ ctxt : the validation context
* @ child : the child list
2001-11-09 02:36:42 +03:00
* @ elemDecl : pointer to the element declaration
2001-04-21 18:16:10 +04:00
* @ warn : emit the error message
2002-09-05 14:58:49 +04:00
* @ parent : the parent element ( for error reporting )
2001-04-20 17:03:48 +04:00
*
* Try to validate the content model of an element
*
* returns 1 if valid or 0 if not and - 1 in case of error
*/
static int
xmlValidateElementContent ( xmlValidCtxtPtr ctxt , xmlNodePtr child ,
2002-09-05 14:58:49 +04:00
xmlElementPtr elemDecl , int warn , xmlNodePtr parent ) {
2002-09-18 20:29:02 +04:00
int ret = 1 ;
2002-09-19 23:56:43 +04:00
# ifndef LIBXML_REGEXP_ENABLED
2002-10-09 14:20:30 +04:00
xmlNodePtr repl = NULL , last = NULL , tmp ;
2002-09-19 23:56:43 +04:00
# endif
2002-10-09 14:20:30 +04:00
xmlNodePtr cur ;
2001-11-09 02:36:42 +03:00
xmlElementContentPtr cont ;
const xmlChar * name ;
if ( elemDecl = = NULL )
return ( - 1 ) ;
cont = elemDecl - > content ;
name = elemDecl - > name ;
2001-04-20 17:03:48 +04:00
2002-09-18 01:50:03 +04:00
# ifdef LIBXML_REGEXP_ENABLED
/* Build the regexp associated to the content model */
if ( elemDecl - > contModel = = NULL )
ret = xmlValidBuildContentModel ( ctxt , elemDecl ) ;
if ( elemDecl - > contModel = = NULL ) {
2003-04-24 20:06:47 +04:00
return ( - 1 ) ;
2002-09-18 01:50:03 +04:00
} else {
xmlRegExecCtxtPtr exec ;
2003-02-05 14:01:50 +03:00
if ( ! xmlRegexpIsDeterminist ( elemDecl - > contModel ) ) {
return ( - 1 ) ;
}
2002-10-09 14:20:30 +04:00
ctxt - > nodeMax = 0 ;
ctxt - > nodeNr = 0 ;
ctxt - > nodeTab = NULL ;
2002-09-18 01:50:03 +04:00
exec = xmlRegNewExecCtxt ( elemDecl - > contModel , NULL , NULL ) ;
if ( exec ! = NULL ) {
cur = child ;
while ( cur ! = NULL ) {
switch ( cur - > type ) {
case XML_ENTITY_REF_NODE :
/*
* Push the current node to be able to roll back
* and process within the entity
*/
if ( ( cur - > children ! = NULL ) & &
( cur - > children - > children ! = NULL ) ) {
nodeVPush ( ctxt , cur ) ;
cur = cur - > children - > children ;
continue ;
}
break ;
case XML_TEXT_NODE :
if ( xmlIsBlankNode ( cur ) )
break ;
ret = 0 ;
goto fail ;
case XML_CDATA_SECTION_NODE :
2002-12-20 03:16:24 +03:00
/* TODO */
2002-09-18 01:50:03 +04:00
ret = 0 ;
goto fail ;
case XML_ELEMENT_NODE :
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( cur - > name ,
cur - > ns - > prefix , fn , 50 ) ;
if ( fullname = = NULL ) {
2002-09-18 01:50:03 +04:00
ret = - 1 ;
goto fail ;
}
2003-04-07 14:22:39 +04:00
ret = xmlRegExecPushString ( exec , fullname , NULL ) ;
if ( ( fullname ! = fn ) & & ( fullname ! = cur - > name ) )
xmlFree ( fullname ) ;
2002-09-18 01:50:03 +04:00
} else {
ret = xmlRegExecPushString ( exec , cur - > name , NULL ) ;
}
break ;
default :
break ;
}
/*
* Switch to next element
*/
cur = cur - > next ;
while ( cur = = NULL ) {
cur = nodeVPop ( ctxt ) ;
if ( cur = = NULL )
break ;
cur = cur - > next ;
}
}
ret = xmlRegExecPushString ( exec , NULL , NULL ) ;
fail :
xmlRegFreeExecCtxt ( exec ) ;
}
}
# else /* LIBXML_REGEXP_ENABLED */
2001-04-20 17:03:48 +04:00
/*
2001-04-21 14:28:59 +04:00
* Allocate the stack
2001-04-20 17:03:48 +04:00
*/
ctxt - > vstateMax = 8 ;
ctxt - > vstateTab = ( xmlValidState * ) xmlMalloc (
ctxt - > vstateMax * sizeof ( ctxt - > vstateTab [ 0 ] ) ) ;
if ( ctxt - > vstateTab = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2001-04-21 14:28:59 +04:00
return ( - 1 ) ;
2001-04-20 17:03:48 +04:00
}
/*
* The first entry in the stack is reserved to the current state
*/
2001-06-19 15:07:54 +04:00
ctxt - > nodeMax = 0 ;
ctxt - > nodeNr = 0 ;
2001-04-24 17:55:12 +04:00
ctxt - > nodeTab = NULL ;
2001-04-20 17:03:48 +04:00
ctxt - > vstate = & ctxt - > vstateTab [ 0 ] ;
ctxt - > vstateNr = 1 ;
CONT = cont ;
NODE = child ;
DEPTH = 0 ;
OCCURS = 0 ;
STATE = 0 ;
ret = xmlValidateElementType ( ctxt ) ;
2001-05-08 00:50:47 +04:00
if ( ( ret = = - 3 ) & & ( warn ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidWarning ( ctxt , child , XML_DTD_CONTENT_NOT_DETERMINIST ,
" Content model for Element %s is ambiguous \n " ,
2003-10-13 18:00:21 +04:00
name , NULL , NULL ) ;
2001-05-08 00:50:47 +04:00
} else if ( ret = = - 2 ) {
2001-04-21 14:28:59 +04:00
/*
* An entities reference appeared at this level .
* Buid a minimal representation of this node content
* sufficient to run the validation process on it
*/
DEBUG_VALID_MSG ( " Found an entity reference, linearizing " ) ;
2001-04-21 18:16:10 +04:00
cur = child ;
while ( cur ! = NULL ) {
switch ( cur - > type ) {
2001-04-21 14:28:59 +04:00
case XML_ENTITY_REF_NODE :
/*
* Push the current node to be able to roll back
* and process within the entity
*/
2001-04-21 18:16:10 +04:00
if ( ( cur - > children ! = NULL ) & &
( cur - > children - > children ! = NULL ) ) {
nodeVPush ( ctxt , cur ) ;
cur = cur - > children - > children ;
2001-04-21 14:28:59 +04:00
continue ;
}
2001-06-17 21:20:21 +04:00
break ;
2001-04-21 14:28:59 +04:00
case XML_TEXT_NODE :
2001-04-21 18:16:10 +04:00
if ( xmlIsBlankNode ( cur ) )
2001-04-21 14:28:59 +04:00
break ;
2001-07-10 00:07:25 +04:00
/* no break on purpose */
2002-02-19 17:18:08 +03:00
case XML_CDATA_SECTION_NODE :
/* no break on purpose */
2001-04-21 14:28:59 +04:00
case XML_ELEMENT_NODE :
/*
* Allocate a new node and minimally fills in
* what ' s required
*/
tmp = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( tmp = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " malloc failed " ) ;
2001-04-21 14:28:59 +04:00
xmlFreeNodeList ( repl ) ;
ret = - 1 ;
goto done ;
}
2001-04-21 18:16:10 +04:00
tmp - > type = cur - > type ;
tmp - > name = cur - > name ;
tmp - > ns = cur - > ns ;
2001-04-21 14:28:59 +04:00
tmp - > next = NULL ;
2001-12-13 11:48:14 +03:00
tmp - > content = NULL ;
2001-04-21 14:28:59 +04:00
if ( repl = = NULL )
repl = last = tmp ;
else {
last - > next = tmp ;
last = tmp ;
}
2002-02-19 17:18:08 +03:00
if ( cur - > type = = XML_CDATA_SECTION_NODE ) {
/*
* E59 spaces in CDATA does not match the
* nonterminal S
*/
tmp - > content = xmlStrdup ( BAD_CAST " CDATA " ) ;
}
2001-04-21 14:28:59 +04:00
break ;
default :
break ;
}
/*
* Switch to next element
*/
2001-04-21 18:16:10 +04:00
cur = cur - > next ;
while ( cur = = NULL ) {
cur = nodeVPop ( ctxt ) ;
if ( cur = = NULL )
2001-04-21 14:28:59 +04:00
break ;
2001-04-21 18:16:10 +04:00
cur = cur - > next ;
2001-04-21 14:28:59 +04:00
}
}
/*
* Relaunch the validation
*/
ctxt - > vstate = & ctxt - > vstateTab [ 0 ] ;
ctxt - > vstateNr = 1 ;
CONT = cont ;
NODE = repl ;
DEPTH = 0 ;
OCCURS = 0 ;
STATE = 0 ;
ret = xmlValidateElementType ( ctxt ) ;
}
2002-09-18 01:50:03 +04:00
# endif /* LIBXML_REGEXP_ENABLED */
2001-05-08 00:50:47 +04:00
if ( ( warn ) & & ( ( ret ! = 1 ) & & ( ret ! = - 3 ) ) ) {
2006-10-11 20:43:06 +04:00
if ( ctxt ! = NULL ) {
2001-11-20 12:37:09 +03:00
char expr [ 5000 ] ;
char list [ 5000 ] ;
expr [ 0 ] = 0 ;
2003-04-24 20:06:47 +04:00
xmlSnprintfElementContent ( & expr [ 0 ] , 5000 , cont , 1 ) ;
2001-11-20 12:37:09 +03:00
list [ 0 ] = 0 ;
2002-10-09 14:20:30 +04:00
# ifndef LIBXML_REGEXP_ENABLED
2001-11-20 12:37:09 +03:00
if ( repl ! = NULL )
2003-04-24 20:06:47 +04:00
xmlSnprintfElements ( & list [ 0 ] , 5000 , repl , 1 ) ;
2001-11-20 12:37:09 +03:00
else
2002-10-09 14:20:30 +04:00
# endif /* LIBXML_REGEXP_ENABLED */
2003-04-24 20:06:47 +04:00
xmlSnprintfElements ( & list [ 0 ] , 5000 , child , 1 ) ;
2001-11-20 12:37:09 +03:00
if ( name ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , parent , XML_DTD_CONTENT_MODEL ,
" Element %s content does not follow the DTD, expecting %s, got %s \n " ,
name , BAD_CAST expr , BAD_CAST list ) ;
2001-11-20 12:37:09 +03:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , parent , XML_DTD_CONTENT_MODEL ,
" Element content does not follow the DTD, expecting %s, got %s \n " ,
BAD_CAST expr , BAD_CAST list , NULL ) ;
2001-11-20 12:37:09 +03:00
}
2001-04-21 18:16:10 +04:00
} else {
2001-11-20 12:37:09 +03:00
if ( name ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , parent , XML_DTD_CONTENT_MODEL ,
2002-08-03 02:19:49 +04:00
" Element %s content does not follow the DTD \n " ,
2003-10-04 02:21:51 +04:00
name , NULL , NULL ) ;
2001-11-20 12:37:09 +03:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , parent , XML_DTD_CONTENT_MODEL ,
" Element content does not follow the DTD \n " ,
NULL , NULL , NULL ) ;
2001-11-20 12:37:09 +03:00
}
2001-04-21 18:16:10 +04:00
}
ret = 0 ;
}
2001-05-08 00:50:47 +04:00
if ( ret = = - 3 )
ret = 1 ;
2001-04-21 14:28:59 +04:00
2002-09-19 23:56:43 +04:00
# ifndef LIBXML_REGEXP_ENABLED
2001-04-21 14:28:59 +04:00
done :
/*
* Deallocate the copy if done , and free up the validation stack
*/
while ( repl ! = NULL ) {
tmp = repl - > next ;
xmlFree ( repl ) ;
repl = tmp ;
}
2001-04-20 17:03:48 +04:00
ctxt - > vstateMax = 0 ;
2001-04-21 18:16:10 +04:00
if ( ctxt - > vstateTab ! = NULL ) {
xmlFree ( ctxt - > vstateTab ) ;
ctxt - > vstateTab = NULL ;
}
2002-10-09 14:20:30 +04:00
# endif
2001-04-21 18:16:10 +04:00
ctxt - > nodeMax = 0 ;
2001-06-19 15:07:54 +04:00
ctxt - > nodeNr = 0 ;
2001-04-21 18:16:10 +04:00
if ( ctxt - > nodeTab ! = NULL ) {
xmlFree ( ctxt - > nodeTab ) ;
ctxt - > nodeTab = NULL ;
}
2001-04-20 17:03:48 +04:00
return ( ret ) ;
2001-04-21 14:28:59 +04:00
2001-04-20 17:03:48 +04:00
}
2001-07-10 00:07:25 +04:00
/**
* xmlValidateCdataElement :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
*
* Check that an element follows # CDATA
*
* returns 1 if valid or 0 otherwise
*/
static int
xmlValidateOneCdataElement ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlNodePtr elem ) {
int ret = 1 ;
xmlNodePtr cur , child ;
2002-10-04 15:46:37 +04:00
if ( ( ctxt = = NULL ) | | ( doc = = NULL ) | | ( elem = = NULL ) )
2001-07-10 00:07:25 +04:00
return ( 0 ) ;
child = elem - > children ;
cur = child ;
while ( cur ! = NULL ) {
switch ( cur - > type ) {
case XML_ENTITY_REF_NODE :
/*
* Push the current node to be able to roll back
* and process within the entity
*/
if ( ( cur - > children ! = NULL ) & &
( cur - > children - > children ! = NULL ) ) {
nodeVPush ( ctxt , cur ) ;
cur = cur - > children - > children ;
continue ;
}
break ;
case XML_COMMENT_NODE :
case XML_PI_NODE :
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
break ;
default :
ret = 0 ;
goto done ;
}
/*
* Switch to next element
*/
cur = cur - > next ;
while ( cur = = NULL ) {
cur = nodeVPop ( ctxt ) ;
if ( cur = = NULL )
break ;
cur = cur - > next ;
}
}
done :
ctxt - > nodeMax = 0 ;
ctxt - > nodeNr = 0 ;
if ( ctxt - > nodeTab ! = NULL ) {
xmlFree ( ctxt - > nodeTab ) ;
ctxt - > nodeTab = NULL ;
}
return ( ret ) ;
}
2002-12-20 03:16:24 +03:00
/**
* xmlValidateCheckMixed :
* @ ctxt : the validation context
* @ cont : the mixed content model
* @ qname : the qualified name as appearing in the serialization
*
* Check if the given node is part of the content model .
*
* Returns 1 if yes , 0 if no , - 1 in case of error
*/
static int
2004-02-06 10:36:04 +03:00
xmlValidateCheckMixed ( xmlValidCtxtPtr ctxt ,
2002-12-20 03:16:24 +03:00
xmlElementContentPtr cont , const xmlChar * qname ) {
2003-08-04 05:06:15 +04:00
const xmlChar * name ;
int plen ;
name = xmlSplitQName3 ( qname , & plen ) ;
if ( name = = NULL ) {
while ( cont ! = NULL ) {
if ( cont - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
if ( ( cont - > prefix = = NULL ) & & ( xmlStrEqual ( cont - > name , qname ) ) )
return ( 1 ) ;
} else if ( ( cont - > type = = XML_ELEMENT_CONTENT_OR ) & &
( cont - > c1 ! = NULL ) & &
( cont - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) ) {
if ( ( cont - > c1 - > prefix = = NULL ) & &
( xmlStrEqual ( cont - > c1 - > name , qname ) ) )
return ( 1 ) ;
} else if ( ( cont - > type ! = XML_ELEMENT_CONTENT_OR ) | |
( cont - > c1 = = NULL ) | |
( cont - > c1 - > type ! = XML_ELEMENT_CONTENT_PCDATA ) ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_DTD_MIXED_CORRUPT ,
" Internal: MIXED struct corrupted \n " ,
NULL ) ;
2003-08-04 05:06:15 +04:00
break ;
}
cont = cont - > c2 ;
}
} else {
while ( cont ! = NULL ) {
if ( cont - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
if ( ( cont - > prefix ! = NULL ) & &
( xmlStrncmp ( cont - > prefix , qname , plen ) = = 0 ) & &
( xmlStrEqual ( cont - > name , name ) ) )
return ( 1 ) ;
} else if ( ( cont - > type = = XML_ELEMENT_CONTENT_OR ) & &
( cont - > c1 ! = NULL ) & &
( cont - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) ) {
if ( ( cont - > c1 - > prefix ! = NULL ) & &
( xmlStrncmp ( cont - > c1 - > prefix , qname , plen ) = = 0 ) & &
( xmlStrEqual ( cont - > c1 - > name , name ) ) )
return ( 1 ) ;
} else if ( ( cont - > type ! = XML_ELEMENT_CONTENT_OR ) | |
( cont - > c1 = = NULL ) | |
( cont - > c1 - > type ! = XML_ELEMENT_CONTENT_PCDATA ) ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_DTD_MIXED_CORRUPT ,
" Internal: MIXED struct corrupted \n " ,
NULL ) ;
2003-08-04 05:06:15 +04:00
break ;
}
cont = cont - > c2 ;
2002-12-20 03:16:24 +03:00
}
}
return ( 0 ) ;
}
/**
* xmlValidGetElemDecl :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
* @ extsubset : pointer , ( out ) indicate if the declaration was found
* in the external subset .
*
* Finds a declaration associated to an element in the document .
*
* returns the pointer to the declaration or NULL if not found .
*/
static xmlElementPtr
xmlValidGetElemDecl ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlNodePtr elem , int * extsubset ) {
xmlElementPtr elemDecl = NULL ;
const xmlChar * prefix = NULL ;
2004-11-03 22:16:55 +03:00
if ( ( ctxt = = NULL ) | | ( doc = = NULL ) | |
( elem = = NULL ) | | ( elem - > name = = NULL ) )
return ( NULL ) ;
2002-12-20 03:16:24 +03:00
if ( extsubset ! = NULL )
* extsubset = 0 ;
/*
* Fetch the declaration for the qualified name
*/
if ( ( elem - > ns ! = NULL ) & & ( elem - > ns - > prefix ! = NULL ) )
prefix = elem - > ns - > prefix ;
if ( prefix ! = NULL ) {
elemDecl = xmlGetDtdQElementDesc ( doc - > intSubset ,
elem - > name , prefix ) ;
if ( ( elemDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) ) {
elemDecl = xmlGetDtdQElementDesc ( doc - > extSubset ,
elem - > name , prefix ) ;
if ( ( elemDecl ! = NULL ) & & ( extsubset ! = NULL ) )
* extsubset = 1 ;
}
}
/*
* Fetch the declaration for the non qualified name
* This is " non-strict " validation should be done on the
* full QName but in that case being flexible makes sense .
*/
if ( elemDecl = = NULL ) {
elemDecl = xmlGetDtdElementDesc ( doc - > intSubset , elem - > name ) ;
if ( ( elemDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) ) {
elemDecl = xmlGetDtdElementDesc ( doc - > extSubset , elem - > name ) ;
if ( ( elemDecl ! = NULL ) & & ( extsubset ! = NULL ) )
* extsubset = 1 ;
}
}
if ( elemDecl = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem ,
XML_DTD_UNKNOWN_ELEM ,
" No declaration for element %s \n " ,
elem - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
}
return ( elemDecl ) ;
}
2003-02-04 19:14:33 +03:00
# ifdef LIBXML_REGEXP_ENABLED
2002-12-20 03:16:24 +03:00
/**
* xmlValidatePushElement :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
* @ qname : the qualified name as appearing in the serialization
*
* Push a new element start on the validation stack .
*
* returns 1 if no validation problem was found or 0 otherwise
*/
int
xmlValidatePushElement ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlNodePtr elem , const xmlChar * qname ) {
int ret = 1 ;
xmlElementPtr eDecl ;
int extsubset = 0 ;
2004-11-03 22:16:55 +03:00
if ( ctxt = = NULL )
return ( 0 ) ;
2003-03-23 15:02:56 +03:00
/* printf("PushElem %s\n", qname); */
2002-12-20 03:16:24 +03:00
if ( ( ctxt - > vstateNr > 0 ) & & ( ctxt - > vstate ! = NULL ) ) {
xmlValidStatePtr state = ctxt - > vstate ;
xmlElementPtr elemDecl ;
/*
* Check the new element agaisnt the content model of the new elem .
*/
if ( state - > elemDecl ! = NULL ) {
elemDecl = state - > elemDecl ;
switch ( elemDecl - > etype ) {
case XML_ELEMENT_TYPE_UNDEFINED :
ret = 0 ;
break ;
case XML_ELEMENT_TYPE_EMPTY :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_NOT_EMPTY ,
2002-12-20 03:16:24 +03:00
" Element %s was declared EMPTY this one has content \n " ,
2003-10-04 02:21:51 +04:00
state - > node - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
ret = 0 ;
break ;
case XML_ELEMENT_TYPE_ANY :
/* I don't think anything is required then */
break ;
case XML_ELEMENT_TYPE_MIXED :
/* simple case of declared as #PCDATA */
if ( ( elemDecl - > content ! = NULL ) & &
( elemDecl - > content - > type = =
XML_ELEMENT_CONTENT_PCDATA ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_NOT_PCDATA ,
2002-12-20 03:16:24 +03:00
" Element %s was declared #PCDATA but contains non text nodes \n " ,
2003-10-04 02:21:51 +04:00
state - > node - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
ret = 0 ;
} else {
ret = xmlValidateCheckMixed ( ctxt , elemDecl - > content ,
qname ) ;
if ( ret ! = 1 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_INVALID_CHILD ,
2002-12-20 03:16:24 +03:00
" Element %s is not declared in %s list of possible children \n " ,
2003-10-04 02:21:51 +04:00
qname , state - > node - > name , NULL ) ;
2002-12-20 03:16:24 +03:00
}
}
break ;
case XML_ELEMENT_TYPE_ELEMENT :
/*
* TODO :
* VC : Standalone Document Declaration
* - element types with element content , if white space
* occurs directly within any instance of those types .
*/
if ( state - > exec ! = NULL ) {
ret = xmlRegExecPushString ( state - > exec , qname , NULL ) ;
if ( ret < 0 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_CONTENT_MODEL ,
" Element %s content does not follow the DTD, Misplaced %s \n " ,
state - > node - > name , qname , NULL ) ;
2002-12-20 03:16:24 +03:00
ret = 0 ;
} else {
ret = 1 ;
}
}
break ;
}
}
}
eDecl = xmlValidGetElemDecl ( ctxt , doc , elem , & extsubset ) ;
vstateVPush ( ctxt , eDecl , elem ) ;
return ( ret ) ;
}
/**
* xmlValidatePushCData :
* @ ctxt : the validation context
* @ data : some character data read
* @ len : the lenght of the data
*
* check the CData parsed for validation in the current stack
*
* returns 1 if no validation problem was found or 0 otherwise
*/
int
xmlValidatePushCData ( xmlValidCtxtPtr ctxt , const xmlChar * data , int len ) {
int ret = 1 ;
2003-03-23 15:02:56 +03:00
/* printf("CDATA %s %d\n", data, len); */
2004-11-03 22:16:55 +03:00
if ( ctxt = = NULL )
return ( 0 ) ;
2002-12-20 03:16:24 +03:00
if ( len < = 0 )
return ( ret ) ;
if ( ( ctxt - > vstateNr > 0 ) & & ( ctxt - > vstate ! = NULL ) ) {
xmlValidStatePtr state = ctxt - > vstate ;
xmlElementPtr elemDecl ;
/*
* Check the new element agaisnt the content model of the new elem .
*/
if ( state - > elemDecl ! = NULL ) {
elemDecl = state - > elemDecl ;
switch ( elemDecl - > etype ) {
case XML_ELEMENT_TYPE_UNDEFINED :
ret = 0 ;
break ;
case XML_ELEMENT_TYPE_EMPTY :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_NOT_EMPTY ,
2002-12-20 03:16:24 +03:00
" Element %s was declared EMPTY this one has content \n " ,
2003-10-04 02:21:51 +04:00
state - > node - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
ret = 0 ;
break ;
case XML_ELEMENT_TYPE_ANY :
break ;
case XML_ELEMENT_TYPE_MIXED :
break ;
case XML_ELEMENT_TYPE_ELEMENT :
if ( len > 0 ) {
int i ;
for ( i = 0 ; i < len ; i + + ) {
2003-10-18 20:20:14 +04:00
if ( ! IS_BLANK_CH ( data [ i ] ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_CONTENT_MODEL ,
" Element %s content does not follow the DTD, Text not allowed \n " ,
state - > node - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
ret = 0 ;
goto done ;
}
}
/*
* TODO :
* VC : Standalone Document Declaration
* element types with element content , if white space
* occurs directly within any instance of those types .
*/
}
break ;
}
}
}
done :
return ( ret ) ;
}
/**
* xmlValidatePopElement :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
* @ qname : the qualified name as appearing in the serialization
*
* Pop the element end from the validation stack .
*
* returns 1 if no validation problem was found or 0 otherwise
*/
int
xmlValidatePopElement ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ATTRIBUTE_UNUSED ,
2003-03-22 00:22:48 +03:00
xmlNodePtr elem ATTRIBUTE_UNUSED ,
const xmlChar * qname ATTRIBUTE_UNUSED ) {
2002-12-20 03:16:24 +03:00
int ret = 1 ;
2004-11-03 22:16:55 +03:00
if ( ctxt = = NULL )
return ( 0 ) ;
2003-03-23 15:02:56 +03:00
/* printf("PopElem %s\n", qname); */
2002-12-20 03:16:24 +03:00
if ( ( ctxt - > vstateNr > 0 ) & & ( ctxt - > vstate ! = NULL ) ) {
xmlValidStatePtr state = ctxt - > vstate ;
xmlElementPtr elemDecl ;
/*
* Check the new element agaisnt the content model of the new elem .
*/
if ( state - > elemDecl ! = NULL ) {
elemDecl = state - > elemDecl ;
if ( elemDecl - > etype = = XML_ELEMENT_TYPE_ELEMENT ) {
if ( state - > exec ! = NULL ) {
ret = xmlRegExecPushString ( state - > exec , NULL , NULL ) ;
if ( ret = = 0 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , state - > node ,
XML_DTD_CONTENT_MODEL ,
" Element %s content does not follow the DTD, Expecting more child \n " ,
state - > node - > name , NULL , NULL ) ;
2002-12-20 03:16:24 +03:00
} else {
/*
* previous validation errors should not generate
* a new one here
*/
ret = 1 ;
}
}
}
}
vstateVPop ( ctxt ) ;
}
return ( ret ) ;
}
2003-02-04 19:14:33 +03:00
# endif /* LIBXML_REGEXP_ENABLED */
2002-12-20 03:16:24 +03:00
2001-02-23 20:55:21 +03:00
/**
* xmlValidateOneElement :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
*
* Try to validate a single element and it ' s attributes ,
* basically it does the following checks as described by the
* XML - 1.0 recommendation :
* - [ VC : Element Valid ]
* - [ VC : Required Attribute ]
* Then call xmlValidateOneAttribute ( ) for each attribute present .
*
* The ID / IDREF checkings are done separately
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateOneElement ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ,
xmlNodePtr elem ) {
xmlElementPtr elemDecl = NULL ;
xmlElementContentPtr cont ;
xmlAttributePtr attr ;
xmlNodePtr child ;
2002-02-20 00:08:48 +03:00
int ret = 1 , tmp ;
2001-02-23 20:55:21 +03:00
const xmlChar * name ;
2002-02-20 00:08:48 +03:00
int extsubset = 0 ;
2001-02-23 20:55:21 +03:00
CHECK_DTD ;
if ( elem = = NULL ) return ( 0 ) ;
switch ( elem - > type ) {
case XML_ATTRIBUTE_NODE :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Attribute element not expected \n " , NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
case XML_TEXT_NODE :
if ( elem - > children ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Text element has children ! \n " ,
NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
if ( elem - > ns ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Text element has namespace ! \n " ,
NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
if ( elem - > content = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Text element has no content ! \n " ,
NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
return ( 1 ) ;
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
return ( 1 ) ;
case XML_CDATA_SECTION_NODE :
case XML_ENTITY_REF_NODE :
case XML_PI_NODE :
case XML_COMMENT_NODE :
return ( 1 ) ;
case XML_ENTITY_NODE :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Entity element not expected \n " , NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
case XML_NOTATION_NODE :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Notation element not expected \n " , NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
case XML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" Document element not expected \n " , NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
case XML_HTML_DOCUMENT_NODE :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" HTML Document not expected \n " , NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
case XML_ELEMENT_NODE :
break ;
default :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_ERR_INTERNAL_ERROR ,
" unknown element type \n " , NULL , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/*
2002-12-20 03:16:24 +03:00
* Fetch the declaration
2001-02-23 20:55:21 +03:00
*/
2002-12-20 03:16:24 +03:00
elemDecl = xmlValidGetElemDecl ( ctxt , doc , elem , & extsubset ) ;
if ( elemDecl = = NULL )
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
/*
2002-12-20 03:16:24 +03:00
* If vstateNr is not zero that means continuous validation is
* activated , do not try to check the content model at that level .
2001-02-23 20:55:21 +03:00
*/
2002-12-20 03:16:24 +03:00
if ( ctxt - > vstateNr = = 0 ) {
2001-12-31 19:16:02 +03:00
/* Check that the element content matches the definition */
2001-02-23 20:55:21 +03:00
switch ( elemDecl - > etype ) {
2001-04-18 17:09:01 +04:00
case XML_ELEMENT_TYPE_UNDEFINED :
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_UNKNOWN_ELEM ,
" No declaration for element %s \n " ,
elem - > name , NULL , NULL ) ;
2001-04-18 17:09:01 +04:00
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
case XML_ELEMENT_TYPE_EMPTY :
if ( elem - > children ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_NOT_EMPTY ,
2001-02-23 20:55:21 +03:00
" Element %s was declared EMPTY this one has content \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , NULL , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
break ;
case XML_ELEMENT_TYPE_ANY :
/* I don't think anything is required then */
break ;
case XML_ELEMENT_TYPE_MIXED :
2002-02-20 00:08:48 +03:00
2001-07-10 00:07:25 +04:00
/* simple case of declared as #PCDATA */
if ( ( elemDecl - > content ! = NULL ) & &
( elemDecl - > content - > type = = XML_ELEMENT_CONTENT_PCDATA ) ) {
ret = xmlValidateOneCdataElement ( ctxt , doc , elem ) ;
if ( ! ret ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_NOT_PCDATA ,
2001-07-10 00:07:25 +04:00
" Element %s was declared #PCDATA but contains non text nodes \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , NULL , NULL ) ;
2001-07-10 00:07:25 +04:00
}
break ;
}
2001-02-23 20:55:21 +03:00
child = elem - > children ;
2001-07-10 00:07:25 +04:00
/* Hum, this start to get messy */
2001-02-23 20:55:21 +03:00
while ( child ! = NULL ) {
if ( child - > type = = XML_ELEMENT_NODE ) {
name = child - > name ;
if ( ( child - > ns ! = NULL ) & & ( child - > ns - > prefix ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( child - > name , child - > ns - > prefix ,
fn , 50 ) ;
if ( fullname = = NULL )
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
cont = elemDecl - > content ;
while ( cont ! = NULL ) {
if ( cont - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
2003-04-07 14:22:39 +04:00
if ( xmlStrEqual ( cont - > name , fullname ) )
break ;
2001-02-23 20:55:21 +03:00
} else if ( ( cont - > type = = XML_ELEMENT_CONTENT_OR ) & &
( cont - > c1 ! = NULL ) & &
( cont - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) ) {
2003-04-07 14:22:39 +04:00
if ( xmlStrEqual ( cont - > c1 - > name , fullname ) )
break ;
2001-02-23 20:55:21 +03:00
} else if ( ( cont - > type ! = XML_ELEMENT_CONTENT_OR ) | |
( cont - > c1 = = NULL ) | |
( cont - > c1 - > type ! = XML_ELEMENT_CONTENT_PCDATA ) ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( NULL , XML_DTD_MIXED_CORRUPT ,
" Internal: MIXED struct corrupted \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
break ;
}
cont = cont - > c2 ;
}
2003-04-07 14:22:39 +04:00
if ( ( fullname ! = fn ) & & ( fullname ! = child - > name ) )
xmlFree ( fullname ) ;
2001-02-23 20:55:21 +03:00
if ( cont ! = NULL )
goto child_ok ;
}
cont = elemDecl - > content ;
while ( cont ! = NULL ) {
if ( cont - > type = = XML_ELEMENT_CONTENT_ELEMENT ) {
if ( xmlStrEqual ( cont - > name , name ) ) break ;
} else if ( ( cont - > type = = XML_ELEMENT_CONTENT_OR ) & &
( cont - > c1 ! = NULL ) & &
( cont - > c1 - > type = = XML_ELEMENT_CONTENT_ELEMENT ) ) {
if ( xmlStrEqual ( cont - > c1 - > name , name ) ) break ;
} else if ( ( cont - > type ! = XML_ELEMENT_CONTENT_OR ) | |
( cont - > c1 = = NULL ) | |
( cont - > c1 - > type ! = XML_ELEMENT_CONTENT_PCDATA ) ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_DTD_MIXED_CORRUPT ,
" Internal: MIXED struct corrupted \n " ,
NULL ) ;
2001-02-23 20:55:21 +03:00
break ;
}
cont = cont - > c2 ;
}
if ( cont = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_INVALID_CHILD ,
2002-02-09 21:03:01 +03:00
" Element %s is not declared in %s list of possible children \n " ,
2003-10-04 02:21:51 +04:00
name , elem - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
}
}
child_ok :
child = child - > next ;
}
break ;
case XML_ELEMENT_TYPE_ELEMENT :
2002-02-20 00:08:48 +03:00
if ( ( doc - > standalone = = 1 ) & & ( extsubset = = 1 ) ) {
/*
* VC : Standalone Document Declaration
* - element types with element content , if white space
* occurs directly within any instance of those types .
*/
child = elem - > children ;
while ( child ! = NULL ) {
if ( child - > type = = XML_TEXT_NODE ) {
const xmlChar * content = child - > content ;
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * content ) )
2002-02-20 00:08:48 +03:00
content + + ;
if ( * content = = 0 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem ,
XML_DTD_STANDALONE_WHITE_SPACE ,
2002-02-20 00:08:48 +03:00
" standalone: %s declared in the external subset contains white spaces nodes \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , NULL , NULL ) ;
2002-02-20 00:08:48 +03:00
ret = 0 ;
break ;
}
}
child = child - > next ;
}
}
2001-02-23 20:55:21 +03:00
child = elem - > children ;
cont = elemDecl - > content ;
2002-09-05 14:58:49 +04:00
tmp = xmlValidateElementContent ( ctxt , child , elemDecl , 1 , elem ) ;
2002-02-20 00:08:48 +03:00
if ( tmp < = 0 )
ret = tmp ;
2001-02-23 20:55:21 +03:00
break ;
}
2002-12-20 03:16:24 +03:00
} /* not continuous */
2001-02-23 20:55:21 +03:00
/* [ VC: Required Attribute ] */
attr = elemDecl - > attributes ;
while ( attr ! = NULL ) {
if ( attr - > def = = XML_ATTRIBUTE_REQUIRED ) {
int qualified = - 1 ;
2002-02-13 16:32:35 +03:00
if ( ( attr - > prefix = = NULL ) & &
( xmlStrEqual ( attr - > name , BAD_CAST " xmlns " ) ) ) {
xmlNsPtr ns ;
ns = elem - > nsDef ;
while ( ns ! = NULL ) {
if ( ns - > prefix = = NULL )
2001-02-23 20:55:21 +03:00
goto found ;
2002-02-13 16:32:35 +03:00
ns = ns - > next ;
}
} else if ( xmlStrEqual ( attr - > prefix , BAD_CAST " xmlns " ) ) {
xmlNsPtr ns ;
ns = elem - > nsDef ;
while ( ns ! = NULL ) {
if ( xmlStrEqual ( attr - > name , ns - > prefix ) )
goto found ;
ns = ns - > next ;
}
} else {
xmlAttrPtr attrib ;
attrib = elem - > properties ;
while ( attrib ! = NULL ) {
if ( xmlStrEqual ( attrib - > name , attr - > name ) ) {
if ( attr - > prefix ! = NULL ) {
xmlNsPtr nameSpace = attrib - > ns ;
if ( nameSpace = = NULL )
nameSpace = elem - > ns ;
/*
* qualified names handling is problematic , having a
* different prefix should be possible but DTDs don ' t
* allow to define the URI instead of the prefix : - (
*/
if ( nameSpace = = NULL ) {
if ( qualified < 0 )
qualified = 0 ;
} else if ( ! xmlStrEqual ( nameSpace - > prefix ,
attr - > prefix ) ) {
if ( qualified < 1 )
qualified = 1 ;
} else
goto found ;
} else {
/*
* We should allow applications to define namespaces
* for their application even if the DTD doesn ' t
* carry one , otherwise , basically we would always
* break .
*/
goto found ;
}
2001-02-23 20:55:21 +03:00
}
2002-02-13 16:32:35 +03:00
attrib = attrib - > next ;
2001-02-23 20:55:21 +03:00
}
}
if ( qualified = = - 1 ) {
if ( attr - > prefix = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_MISSING_ATTRIBUTE ,
2002-08-03 02:19:49 +04:00
" Element %s does not carry attribute %s \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , attr - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
ret = 0 ;
} else {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_MISSING_ATTRIBUTE ,
2002-08-03 02:19:49 +04:00
" Element %s does not carry attribute %s:%s \n " ,
2001-02-23 20:55:21 +03:00
elem - > name , attr - > prefix , attr - > name ) ;
ret = 0 ;
}
} else if ( qualified = = 0 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidWarning ( ctxt , elem , XML_DTD_NO_PREFIX ,
2001-02-23 20:55:21 +03:00
" Element %s required attribute %s:%s has no prefix \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , attr - > prefix , attr - > name ) ;
2001-02-23 20:55:21 +03:00
} else if ( qualified = = 1 ) {
2003-10-04 02:21:51 +04:00
xmlErrValidWarning ( ctxt , elem , XML_DTD_DIFFERENT_PREFIX ,
2001-02-23 20:55:21 +03:00
" Element %s required attribute %s:%s has different prefix \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , attr - > prefix , attr - > name ) ;
2001-02-23 20:55:21 +03:00
}
2002-02-13 16:32:35 +03:00
} else if ( attr - > def = = XML_ATTRIBUTE_FIXED ) {
/*
* Special tests checking # FIXED namespace declarations
* have the right value since this is not done as an
* attribute checking
*/
if ( ( attr - > prefix = = NULL ) & &
( xmlStrEqual ( attr - > name , BAD_CAST " xmlns " ) ) ) {
xmlNsPtr ns ;
ns = elem - > nsDef ;
while ( ns ! = NULL ) {
if ( ns - > prefix = = NULL ) {
if ( ! xmlStrEqual ( attr - > defaultValue , ns - > href ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem ,
XML_DTD_ELEM_DEFAULT_NAMESPACE ,
2002-02-13 16:32:35 +03:00
" Element %s namespace name for default namespace does not match the DTD \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , NULL , NULL ) ;
2002-02-18 01:47:37 +03:00
ret = 0 ;
2002-02-13 16:32:35 +03:00
}
goto found ;
}
ns = ns - > next ;
}
} else if ( xmlStrEqual ( attr - > prefix , BAD_CAST " xmlns " ) ) {
xmlNsPtr ns ;
ns = elem - > nsDef ;
while ( ns ! = NULL ) {
if ( xmlStrEqual ( attr - > name , ns - > prefix ) ) {
if ( ! xmlStrEqual ( attr - > defaultValue , ns - > href ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , elem , XML_DTD_ELEM_NAMESPACE ,
2002-08-03 02:19:49 +04:00
" Element %s namespace name for %s does not match the DTD \n " ,
2003-10-04 02:21:51 +04:00
elem - > name , ns - > prefix , NULL ) ;
2002-02-18 01:47:37 +03:00
ret = 0 ;
2002-02-13 16:32:35 +03:00
}
goto found ;
}
ns = ns - > next ;
}
}
2001-02-23 20:55:21 +03:00
}
found :
attr = attr - > nexth ;
}
return ( ret ) ;
}
/**
* xmlValidateRoot :
* @ ctxt : the validation context
* @ doc : a document instance
*
* Try to validate a the root element
* basically it does the following check as described by the
* XML - 1.0 recommendation :
* - [ VC : Root Element Type ]
* it doesn ' t try to recurse or apply other check to the element
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateRoot ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ) {
xmlNodePtr root ;
2003-04-07 14:22:39 +04:00
int ret ;
2001-02-23 20:55:21 +03:00
if ( doc = = NULL ) return ( 0 ) ;
root = xmlDocGetRootElement ( doc ) ;
if ( ( root = = NULL ) | | ( root - > name = = NULL ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValid ( ctxt , XML_DTD_NO_ROOT ,
" no root element \n " , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/*
* When doing post validation against a separate DTD , those may
* no internal subset has been generated
*/
if ( ( doc - > intSubset ! = NULL ) & &
( doc - > intSubset - > name ! = NULL ) ) {
/*
* Check first the document root against the NQName
*/
if ( ! xmlStrEqual ( doc - > intSubset - > name , root - > name ) ) {
if ( ( root - > ns ! = NULL ) & & ( root - > ns - > prefix ! = NULL ) ) {
2003-04-07 14:22:39 +04:00
xmlChar fn [ 50 ] ;
xmlChar * fullname ;
fullname = xmlBuildQName ( root - > name , root - > ns - > prefix , fn , 50 ) ;
if ( fullname = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , NULL ) ;
2003-04-07 14:22:39 +04:00
return ( 0 ) ;
}
ret = xmlStrEqual ( doc - > intSubset - > name , fullname ) ;
if ( ( fullname ! = fn ) & & ( fullname ! = root - > name ) )
xmlFree ( fullname ) ;
if ( ret = = 1 )
2001-02-23 20:55:21 +03:00
goto name_ok ;
}
if ( ( xmlStrEqual ( doc - > intSubset - > name , BAD_CAST " HTML " ) ) & &
( xmlStrEqual ( root - > name , BAD_CAST " html " ) ) )
goto name_ok ;
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , root , XML_DTD_ROOT_NAME ,
" root and DTD name do not match '%s' and '%s' \n " ,
root - > name , doc - > intSubset - > name , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
}
name_ok :
return ( 1 ) ;
}
/**
* xmlValidateElement :
* @ ctxt : the validation context
* @ doc : a document instance
* @ elem : an element instance
*
* Try to validate the subtree under an element
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateElement ( xmlValidCtxtPtr ctxt , xmlDocPtr doc , xmlNodePtr elem ) {
xmlNodePtr child ;
xmlAttrPtr attr ;
2003-10-30 13:42:20 +03:00
xmlNsPtr ns ;
2003-11-03 19:20:10 +03:00
const xmlChar * value ;
2001-02-23 20:55:21 +03:00
int ret = 1 ;
if ( elem = = NULL ) return ( 0 ) ;
/*
* XInclude elements were added after parsing in the infoset ,
* they don ' t really mean anything validation wise .
*/
if ( ( elem - > type = = XML_XINCLUDE_START ) | |
( elem - > type = = XML_XINCLUDE_END ) )
return ( 1 ) ;
CHECK_DTD ;
2001-06-20 17:55:33 +04:00
/*
* Entities references have to be handled separately
*/
if ( elem - > type = = XML_ENTITY_REF_NODE ) {
return ( 1 ) ;
}
2001-02-23 20:55:21 +03:00
ret & = xmlValidateOneElement ( ctxt , doc , elem ) ;
2005-08-25 17:19:21 +04:00
if ( elem - > type = = XML_ELEMENT_NODE ) {
attr = elem - > properties ;
while ( attr ! = NULL ) {
value = xmlNodeListGetString ( doc , attr - > children , 0 ) ;
ret & = xmlValidateOneAttribute ( ctxt , doc , elem , attr , value ) ;
if ( value ! = NULL )
xmlFree ( ( char * ) value ) ;
attr = attr - > next ;
}
ns = elem - > nsDef ;
while ( ns ! = NULL ) {
if ( elem - > ns = = NULL )
ret & = xmlValidateOneNamespace ( ctxt , doc , elem , NULL ,
ns , ns - > href ) ;
else
ret & = xmlValidateOneNamespace ( ctxt , doc , elem ,
elem - > ns - > prefix , ns , ns - > href ) ;
ns = ns - > next ;
}
2003-10-30 13:42:20 +03:00
}
2001-02-23 20:55:21 +03:00
child = elem - > children ;
while ( child ! = NULL ) {
ret & = xmlValidateElement ( ctxt , doc , child ) ;
child = child - > next ;
}
return ( ret ) ;
}
2001-02-26 13:49:57 +03:00
/**
* xmlValidateRef :
* @ ref : A reference to be validated
* @ ctxt : Validation context
* @ name : Name of ID we are searching for
*
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-26 13:49:57 +03:00
xmlValidateRef ( xmlRefPtr ref , xmlValidCtxtPtr ctxt ,
2001-02-23 20:55:21 +03:00
const xmlChar * name ) {
xmlAttrPtr id ;
xmlAttrPtr attr ;
if ( ref = = NULL )
return ;
2002-12-20 03:16:24 +03:00
if ( ( ref - > attr = = NULL ) & & ( ref - > name = = NULL ) )
2001-02-23 20:55:21 +03:00
return ;
2002-12-20 03:16:24 +03:00
attr = ref - > attr ;
if ( attr = = NULL ) {
xmlChar * dup , * str = NULL , * cur , save ;
dup = xmlStrdup ( name ) ;
if ( dup = = NULL ) {
ctxt - > valid = 0 ;
return ;
}
cur = dup ;
while ( * cur ! = 0 ) {
str = cur ;
2003-10-18 20:20:14 +04:00
while ( ( * cur ! = 0 ) & & ( ! IS_BLANK_CH ( * cur ) ) ) cur + + ;
2002-12-20 03:16:24 +03:00
save = * cur ;
* cur = 0 ;
id = xmlGetID ( ctxt - > doc , str ) ;
if ( id = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNodeNr ( ctxt , NULL , XML_DTD_UNKNOWN_ID ,
2002-12-20 03:16:24 +03:00
" attribute %s line %d references an unknown ID \" %s \" \n " ,
ref - > name , ref - > lineno , str ) ;
ctxt - > valid = 0 ;
}
if ( save = = 0 )
break ;
* cur = save ;
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2002-12-20 03:16:24 +03:00
}
xmlFree ( dup ) ;
} else if ( attr - > atype = = XML_ATTRIBUTE_IDREF ) {
2001-02-23 20:55:21 +03:00
id = xmlGetID ( ctxt - > doc , name ) ;
if ( id = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , attr - > parent , XML_DTD_UNKNOWN_ID ,
2002-12-20 03:16:24 +03:00
" IDREF attribute %s references an unknown ID \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
attr - > name , name , NULL ) ;
2001-02-23 20:55:21 +03:00
ctxt - > valid = 0 ;
}
} else if ( attr - > atype = = XML_ATTRIBUTE_IDREFS ) {
xmlChar * dup , * str = NULL , * cur , save ;
dup = xmlStrdup ( name ) ;
if ( dup = = NULL ) {
2003-10-06 01:33:18 +04:00
xmlVErrMemory ( ctxt , " IDREFS split " ) ;
2001-02-23 20:55:21 +03:00
ctxt - > valid = 0 ;
return ;
}
cur = dup ;
while ( * cur ! = 0 ) {
str = cur ;
2003-10-18 20:20:14 +04:00
while ( ( * cur ! = 0 ) & & ( ! IS_BLANK_CH ( * cur ) ) ) cur + + ;
2001-02-23 20:55:21 +03:00
save = * cur ;
* cur = 0 ;
id = xmlGetID ( ctxt - > doc , str ) ;
if ( id = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , attr - > parent , XML_DTD_UNKNOWN_ID ,
2002-12-20 03:16:24 +03:00
" IDREFS attribute %s references an unknown ID \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
attr - > name , str , NULL ) ;
2001-02-23 20:55:21 +03:00
ctxt - > valid = 0 ;
}
if ( save = = 0 )
break ;
* cur = save ;
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2001-02-23 20:55:21 +03:00
}
xmlFree ( dup ) ;
}
}
2001-02-26 13:49:57 +03:00
/**
* xmlWalkValidateList :
* @ data : Contents of current link
* @ user : Value supplied by the user
*
2001-12-31 19:16:02 +03:00
* Returns 0 to abort the walk or 1 to continue
2001-02-26 13:49:57 +03:00
*/
static int
xmlWalkValidateList ( const void * data , const void * user )
{
xmlValidateMemoPtr memo = ( xmlValidateMemoPtr ) user ;
xmlValidateRef ( ( xmlRefPtr ) data , memo - > ctxt , memo - > name ) ;
return 1 ;
}
/**
* xmlValidateCheckRefCallback :
* @ ref_list : List of references
* @ ctxt : Validation context
* @ name : Name of ID we are searching for
*
*/
static void
xmlValidateCheckRefCallback ( xmlListPtr ref_list , xmlValidCtxtPtr ctxt ,
const xmlChar * name ) {
xmlValidateMemo memo ;
if ( ref_list = = NULL )
return ;
memo . ctxt = ctxt ;
memo . name = name ;
xmlListWalk ( ref_list , xmlWalkValidateList , & memo ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlValidateDocumentFinal :
* @ ctxt : the validation context
* @ doc : a document instance
*
* Does the final step for the document validation once all the
* incremental validation steps have been completed
*
* basically it does the following checks described by the XML Rec
*
2003-03-18 03:31:04 +03:00
* Check all the IDREF / IDREFS attributes definition for validity
2001-02-23 20:55:21 +03:00
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateDocumentFinal ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ) {
xmlRefTablePtr table ;
2004-11-03 22:16:55 +03:00
if ( ctxt = = NULL )
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
if ( doc = = NULL ) {
2003-10-03 02:28:19 +04:00
xmlErrValid ( ctxt , XML_DTD_NO_DOC ,
" xmlValidateDocumentFinal: doc == NULL \n " , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/*
* Check all the NOTATION / NOTATIONS attributes
*/
/*
* Check all the ENTITY / ENTITIES attributes definition for validity
*/
/*
* Check all the IDREF / IDREFS attributes definition for validity
*/
table = ( xmlRefTablePtr ) doc - > refs ;
ctxt - > doc = doc ;
ctxt - > valid = 1 ;
xmlHashScan ( table , ( xmlHashScanner ) xmlValidateCheckRefCallback , ctxt ) ;
return ( ctxt - > valid ) ;
}
/**
* xmlValidateDtd :
* @ ctxt : the validation context
* @ doc : a document instance
* @ dtd : a dtd instance
*
* Try to validate the document against the dtd instance
*
2004-10-23 22:14:36 +04:00
* Basically it does check all the definitions in the DtD .
* Note the the internal subset ( if present ) is de - coupled
* ( i . e . not used ) , which could give problems if ID or IDREF
* is present .
2001-02-23 20:55:21 +03:00
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateDtd ( xmlValidCtxtPtr ctxt , xmlDocPtr doc , xmlDtdPtr dtd ) {
int ret ;
2004-10-23 22:14:36 +04:00
xmlDtdPtr oldExt , oldInt ;
2001-02-23 20:55:21 +03:00
xmlNodePtr root ;
if ( dtd = = NULL ) return ( 0 ) ;
if ( doc = = NULL ) return ( 0 ) ;
oldExt = doc - > extSubset ;
2004-10-23 22:14:36 +04:00
oldInt = doc - > intSubset ;
2001-02-23 20:55:21 +03:00
doc - > extSubset = dtd ;
2004-10-23 22:14:36 +04:00
doc - > intSubset = NULL ;
2001-02-23 20:55:21 +03:00
ret = xmlValidateRoot ( ctxt , doc ) ;
if ( ret = = 0 ) {
doc - > extSubset = oldExt ;
2004-10-23 22:14:36 +04:00
doc - > intSubset = oldInt ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
if ( doc - > ids ! = NULL ) {
xmlFreeIDTable ( doc - > ids ) ;
doc - > ids = NULL ;
}
if ( doc - > refs ! = NULL ) {
xmlFreeRefTable ( doc - > refs ) ;
doc - > refs = NULL ;
}
root = xmlDocGetRootElement ( doc ) ;
ret = xmlValidateElement ( ctxt , doc , root ) ;
ret & = xmlValidateDocumentFinal ( ctxt , doc ) ;
doc - > extSubset = oldExt ;
2004-10-23 22:14:36 +04:00
doc - > intSubset = oldInt ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2002-02-18 21:31:38 +03:00
static void
xmlValidateNotationCallback ( xmlEntityPtr cur , xmlValidCtxtPtr ctxt ,
const xmlChar * name ATTRIBUTE_UNUSED ) {
if ( cur = = NULL )
return ;
if ( cur - > etype = = XML_EXTERNAL_GENERAL_UNPARSED_ENTITY ) {
xmlChar * notation = cur - > content ;
2002-02-19 16:46:09 +03:00
if ( notation ! = NULL ) {
2002-02-18 21:31:38 +03:00
int ret ;
ret = xmlValidateNotationUse ( ctxt , cur - > doc , notation ) ;
if ( ret ! = 1 ) {
2002-02-19 16:46:09 +03:00
ctxt - > valid = 0 ;
2002-02-18 21:31:38 +03:00
}
}
}
}
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
xmlValidateAttributeCallback ( xmlAttributePtr cur , xmlValidCtxtPtr ctxt ,
2001-03-26 20:28:29 +04:00
const xmlChar * name ATTRIBUTE_UNUSED ) {
2002-02-18 21:31:38 +03:00
int ret ;
2002-02-19 16:46:09 +03:00
xmlDocPtr doc ;
2003-11-03 19:20:10 +03:00
xmlElementPtr elem = NULL ;
2002-02-18 21:31:38 +03:00
2001-02-23 20:55:21 +03:00
if ( cur = = NULL )
return ;
switch ( cur - > atype ) {
case XML_ATTRIBUTE_CDATA :
case XML_ATTRIBUTE_ID :
case XML_ATTRIBUTE_IDREF :
case XML_ATTRIBUTE_IDREFS :
case XML_ATTRIBUTE_NMTOKEN :
case XML_ATTRIBUTE_NMTOKENS :
case XML_ATTRIBUTE_ENUMERATION :
break ;
case XML_ATTRIBUTE_ENTITY :
case XML_ATTRIBUTE_ENTITIES :
case XML_ATTRIBUTE_NOTATION :
if ( cur - > defaultValue ! = NULL ) {
2002-02-18 21:31:38 +03:00
ret = xmlValidateAttributeValue2 ( ctxt , ctxt - > doc , cur - > name ,
cur - > atype , cur - > defaultValue ) ;
if ( ( ret = = 0 ) & & ( ctxt - > valid = = 1 ) )
ctxt - > valid = 0 ;
2001-02-23 20:55:21 +03:00
}
if ( cur - > tree ! = NULL ) {
xmlEnumerationPtr tree = cur - > tree ;
while ( tree ! = NULL ) {
2002-02-18 21:31:38 +03:00
ret = xmlValidateAttributeValue2 ( ctxt , ctxt - > doc ,
2001-02-23 20:55:21 +03:00
cur - > name , cur - > atype , tree - > name ) ;
2002-02-18 21:31:38 +03:00
if ( ( ret = = 0 ) & & ( ctxt - > valid = = 1 ) )
ctxt - > valid = 0 ;
2001-02-23 20:55:21 +03:00
tree = tree - > next ;
}
}
}
2002-02-19 16:46:09 +03:00
if ( cur - > atype = = XML_ATTRIBUTE_NOTATION ) {
doc = cur - > doc ;
2003-11-03 19:20:10 +03:00
if ( cur - > elem = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValid ( ctxt , XML_ERR_INTERNAL_ERROR ,
2002-02-19 16:46:09 +03:00
" xmlValidateAttributeCallback(%s): internal error \n " ,
2003-10-04 02:21:51 +04:00
( const char * ) cur - > name ) ;
2002-02-19 16:46:09 +03:00
return ;
}
2003-11-03 19:20:10 +03:00
if ( doc ! = NULL )
elem = xmlGetDtdElementDesc ( doc - > intSubset , cur - > elem ) ;
if ( ( elem = = NULL ) & & ( doc ! = NULL ) )
2002-02-19 16:46:09 +03:00
elem = xmlGetDtdElementDesc ( doc - > extSubset , cur - > elem ) ;
2003-11-03 19:20:10 +03:00
if ( ( elem = = NULL ) & & ( cur - > parent ! = NULL ) & &
( cur - > parent - > type = = XML_DTD_NODE ) )
elem = xmlGetDtdElementDesc ( ( xmlDtdPtr ) cur - > parent , cur - > elem ) ;
2002-02-19 16:46:09 +03:00
if ( elem = = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , NULL , XML_DTD_UNKNOWN_ELEM ,
2002-02-19 16:46:09 +03:00
" attribute %s: could not find decl for element %s \n " ,
2003-10-04 02:21:51 +04:00
cur - > name , cur - > elem , NULL ) ;
2002-02-19 16:46:09 +03:00
return ;
}
if ( elem - > etype = = XML_ELEMENT_TYPE_EMPTY ) {
2003-10-04 02:21:51 +04:00
xmlErrValidNode ( ctxt , NULL , XML_DTD_EMPTY_NOTATION ,
2002-08-03 02:19:49 +04:00
" NOTATION attribute %s declared for EMPTY element %s \n " ,
2003-10-04 02:21:51 +04:00
cur - > name , cur - > elem , NULL ) ;
2002-02-19 16:46:09 +03:00
ctxt - > valid = 0 ;
}
}
2001-02-23 20:55:21 +03:00
}
/**
* xmlValidateDtdFinal :
* @ ctxt : the validation context
* @ doc : a document instance
*
* Does the final step for the dtds validation once all the
* subsets have been parsed
*
* basically it does the following checks described by the XML Rec
* - check that ENTITY and ENTITIES type attributes default or
* possible values matches one of the defined entities .
* - check that NOTATION type attributes default or
* possible values matches one of the defined notations .
*
2002-02-18 21:31:38 +03:00
* returns 1 if valid or 0 if invalid and - 1 if not well - formed
2001-02-23 20:55:21 +03:00
*/
int
xmlValidateDtdFinal ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ) {
xmlDtdPtr dtd ;
xmlAttributeTablePtr table ;
2002-02-18 21:31:38 +03:00
xmlEntitiesTablePtr entities ;
2001-02-23 20:55:21 +03:00
if ( doc = = NULL ) return ( 0 ) ;
if ( ( doc - > intSubset = = NULL ) & & ( doc - > extSubset = = NULL ) )
return ( 0 ) ;
ctxt - > doc = doc ;
2002-02-18 21:31:38 +03:00
ctxt - > valid = 1 ;
2001-02-23 20:55:21 +03:00
dtd = doc - > intSubset ;
if ( ( dtd ! = NULL ) & & ( dtd - > attributes ! = NULL ) ) {
table = ( xmlAttributeTablePtr ) dtd - > attributes ;
xmlHashScan ( table , ( xmlHashScanner ) xmlValidateAttributeCallback , ctxt ) ;
2002-02-19 16:46:09 +03:00
}
if ( ( dtd ! = NULL ) & & ( dtd - > entities ! = NULL ) ) {
2002-02-18 21:31:38 +03:00
entities = ( xmlEntitiesTablePtr ) dtd - > entities ;
xmlHashScan ( entities , ( xmlHashScanner ) xmlValidateNotationCallback ,
ctxt ) ;
2001-02-23 20:55:21 +03:00
}
dtd = doc - > extSubset ;
if ( ( dtd ! = NULL ) & & ( dtd - > attributes ! = NULL ) ) {
table = ( xmlAttributeTablePtr ) dtd - > attributes ;
xmlHashScan ( table , ( xmlHashScanner ) xmlValidateAttributeCallback , ctxt ) ;
2002-02-19 16:46:09 +03:00
}
if ( ( dtd ! = NULL ) & & ( dtd - > entities ! = NULL ) ) {
2002-02-18 21:31:38 +03:00
entities = ( xmlEntitiesTablePtr ) dtd - > entities ;
xmlHashScan ( entities , ( xmlHashScanner ) xmlValidateNotationCallback ,
ctxt ) ;
2001-02-23 20:55:21 +03:00
}
return ( ctxt - > valid ) ;
}
/**
* xmlValidateDocument :
* @ ctxt : the validation context
* @ doc : a document instance
*
* Try to validate the document instance
*
* basically it does the all the checks described by the XML Rec
* i . e . validates the internal and external subset ( if present )
* and validate the document tree .
*
* returns 1 if valid or 0 otherwise
*/
int
xmlValidateDocument ( xmlValidCtxtPtr ctxt , xmlDocPtr doc ) {
int ret ;
xmlNodePtr root ;
2004-11-03 22:16:55 +03:00
if ( doc = = NULL )
return ( 0 ) ;
2002-10-16 18:32:41 +04:00
if ( ( doc - > intSubset = = NULL ) & & ( doc - > extSubset = = NULL ) ) {
2003-10-04 02:21:51 +04:00
xmlErrValid ( ctxt , XML_DTD_NO_DTD ,
" no DTD found! \n " , NULL ) ;
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
2002-10-16 18:32:41 +04:00
}
2001-02-23 20:55:21 +03:00
if ( ( doc - > intSubset ! = NULL ) & & ( ( doc - > intSubset - > SystemID ! = NULL ) | |
( doc - > intSubset - > ExternalID ! = NULL ) ) & & ( doc - > extSubset = = NULL ) ) {
2004-08-06 20:23:27 +04:00
xmlChar * sysID ;
if ( doc - > intSubset - > SystemID ! = NULL ) {
2004-08-05 10:46:47 +04:00
sysID = xmlBuildURI ( doc - > intSubset - > SystemID ,
doc - > URL ) ;
2004-08-06 20:23:27 +04:00
if ( sysID = = NULL ) {
xmlErrValid ( ctxt , XML_DTD_LOAD_ERROR ,
" Could not build URI for external subset \" %s \" \n " ,
( const char * ) doc - > intSubset - > SystemID ) ;
return 0 ;
}
} else
2004-08-05 10:46:47 +04:00
sysID = NULL ;
2004-08-06 20:23:27 +04:00
doc - > extSubset = xmlParseDTD ( doc - > intSubset - > ExternalID ,
2004-08-05 10:46:47 +04:00
( const xmlChar * ) sysID ) ;
if ( sysID ! = NULL )
xmlFree ( sysID ) ;
2001-02-23 20:55:21 +03:00
if ( doc - > extSubset = = NULL ) {
if ( doc - > intSubset - > SystemID ! = NULL ) {
2003-10-04 02:21:51 +04:00
xmlErrValid ( ctxt , XML_DTD_LOAD_ERROR ,
2001-02-23 20:55:21 +03:00
" Could not load the external subset \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
( const char * ) doc - > intSubset - > SystemID ) ;
2001-02-23 20:55:21 +03:00
} else {
2003-10-04 02:21:51 +04:00
xmlErrValid ( ctxt , XML_DTD_LOAD_ERROR ,
2001-02-23 20:55:21 +03:00
" Could not load the external subset \" %s \" \n " ,
2003-10-04 02:21:51 +04:00
( const char * ) doc - > intSubset - > ExternalID ) ;
2001-02-23 20:55:21 +03:00
}
return ( 0 ) ;
}
}
if ( doc - > ids ! = NULL ) {
xmlFreeIDTable ( doc - > ids ) ;
doc - > ids = NULL ;
}
if ( doc - > refs ! = NULL ) {
xmlFreeRefTable ( doc - > refs ) ;
doc - > refs = NULL ;
}
ret = xmlValidateDtdFinal ( ctxt , doc ) ;
if ( ! xmlValidateRoot ( ctxt , doc ) ) return ( 0 ) ;
root = xmlDocGetRootElement ( doc ) ;
ret & = xmlValidateElement ( ctxt , doc , root ) ;
ret & = xmlValidateDocumentFinal ( ctxt , doc ) ;
return ( ret ) ;
}
/************************************************************************
* *
* Routines for dynamic validation editing *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlValidGetPotentialChildren :
* @ ctree : an element content tree
2005-10-27 15:56:20 +04:00
* @ names : an array to store the list of child names
2001-02-23 20:55:21 +03:00
* @ len : a pointer to the number of element in the list
* @ max : the size of the array
*
* Build / extend a list of potential children allowed by the content tree
*
* returns the number of element in the list , or - 1 in case of error .
*/
int
2005-10-27 15:56:20 +04:00
xmlValidGetPotentialChildren ( xmlElementContent * ctree ,
const xmlChar * * names ,
2001-02-23 20:55:21 +03:00
int * len , int max ) {
int i ;
2005-10-27 15:56:20 +04:00
if ( ( ctree = = NULL ) | | ( names = = NULL ) | | ( len = = NULL ) )
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
if ( * len > = max ) return ( * len ) ;
switch ( ctree - > type ) {
case XML_ELEMENT_CONTENT_PCDATA :
for ( i = 0 ; i < * len ; i + + )
2005-10-27 15:56:20 +04:00
if ( xmlStrEqual ( BAD_CAST " #PCDATA " , names [ i ] ) ) return ( * len ) ;
names [ ( * len ) + + ] = BAD_CAST " #PCDATA " ;
2001-02-23 20:55:21 +03:00
break ;
case XML_ELEMENT_CONTENT_ELEMENT :
for ( i = 0 ; i < * len ; i + + )
2005-10-27 15:56:20 +04:00
if ( xmlStrEqual ( ctree - > name , names [ i ] ) ) return ( * len ) ;
names [ ( * len ) + + ] = ctree - > name ;
2001-02-23 20:55:21 +03:00
break ;
case XML_ELEMENT_CONTENT_SEQ :
2005-10-27 15:56:20 +04:00
xmlValidGetPotentialChildren ( ctree - > c1 , names , len , max ) ;
xmlValidGetPotentialChildren ( ctree - > c2 , names , len , max ) ;
2001-02-23 20:55:21 +03:00
break ;
case XML_ELEMENT_CONTENT_OR :
2005-10-27 15:56:20 +04:00
xmlValidGetPotentialChildren ( ctree - > c1 , names , len , max ) ;
xmlValidGetPotentialChildren ( ctree - > c2 , names , len , max ) ;
2001-02-23 20:55:21 +03:00
break ;
}
return ( * len ) ;
}
2004-06-24 12:33:40 +04:00
/*
* Dummy function to suppress messages while we try out valid elements
*/
2005-07-21 17:24:09 +04:00
static void XMLCDECL xmlNoValidityErr ( void * ctx ATTRIBUTE_UNUSED ,
2004-06-24 12:33:40 +04:00
const char * msg ATTRIBUTE_UNUSED , . . . ) {
return ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlValidGetValidElements :
* @ prev : an element to insert after
* @ next : an element to insert next
2004-05-08 06:32:07 +04:00
* @ names : an array to store the list of child names
2001-02-23 20:55:21 +03:00
* @ max : the size of the array
*
* This function returns the list of authorized children to insert
* within an existing tree while respecting the validity constraints
* forced by the Dtd . The insertion point is defined using @ prev and
* @ next in the following ways :
* to insert before ' node ' : xmlValidGetValidElements ( node - > prev , node , . . .
* to insert next ' node ' : xmlValidGetValidElements ( node , node - > next , . . .
* to replace ' node ' : xmlValidGetValidElements ( node - > prev , node - > next , . . .
* to prepend a child to ' node ' : xmlValidGetValidElements ( NULL , node - > childs ,
* to append a child to ' node ' : xmlValidGetValidElements ( node - > last , NULL , . . .
*
* pointers to the element names are inserted at the beginning of the array
* and do not need to be freed .
*
* returns the number of element in the list , or - 1 in case of error . If
* the function returns the value @ max the caller is invited to grow the
* receiving array and retry .
*/
int
2004-05-08 06:32:07 +04:00
xmlValidGetValidElements ( xmlNode * prev , xmlNode * next , const xmlChar * * names ,
2001-02-23 20:55:21 +03:00
int max ) {
2001-05-19 17:24:56 +04:00
xmlValidCtxt vctxt ;
2001-02-23 20:55:21 +03:00
int nb_valid_elements = 0 ;
const xmlChar * elements [ 256 ] ;
int nb_elements = 0 , i ;
2002-02-09 21:03:01 +03:00
const xmlChar * name ;
2001-02-23 20:55:21 +03:00
xmlNode * ref_node ;
xmlNode * parent ;
xmlNode * test_node ;
xmlNode * prev_next ;
xmlNode * next_prev ;
xmlNode * parent_childs ;
xmlNode * parent_last ;
xmlElement * element_desc ;
if ( prev = = NULL & & next = = NULL )
return ( - 1 ) ;
2004-05-08 06:32:07 +04:00
if ( names = = NULL ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
if ( max < = 0 ) return ( - 1 ) ;
2004-06-24 12:33:40 +04:00
memset ( & vctxt , 0 , sizeof ( xmlValidCtxt ) ) ;
vctxt . error = xmlNoValidityErr ; /* this suppresses err/warn output */
2001-02-23 20:55:21 +03:00
nb_valid_elements = 0 ;
ref_node = prev ? prev : next ;
parent = ref_node - > parent ;
/*
* Retrieves the parent element declaration
*/
element_desc = xmlGetDtdElementDesc ( parent - > doc - > intSubset ,
parent - > name ) ;
if ( ( element_desc = = NULL ) & & ( parent - > doc - > extSubset ! = NULL ) )
element_desc = xmlGetDtdElementDesc ( parent - > doc - > extSubset ,
parent - > name ) ;
if ( element_desc = = NULL ) return ( - 1 ) ;
/*
* Do a backup of the current tree structure
*/
prev_next = prev ? prev - > next : NULL ;
next_prev = next ? next - > prev : NULL ;
parent_childs = parent - > children ;
parent_last = parent - > last ;
/*
* Creates a dummy node and insert it into the tree
*/
2004-10-27 01:53:55 +04:00
test_node = xmlNewDocNode ( ref_node - > doc , NULL , BAD_CAST " <!dummy?> " , NULL ) ;
2001-02-23 20:55:21 +03:00
test_node - > parent = parent ;
test_node - > prev = prev ;
test_node - > next = next ;
2002-02-08 16:37:46 +03:00
name = test_node - > name ;
2001-02-23 20:55:21 +03:00
if ( prev ) prev - > next = test_node ;
else parent - > children = test_node ;
if ( next ) next - > prev = test_node ;
else parent - > last = test_node ;
/*
* Insert each potential child node and check if the parent is
* still valid
*/
nb_elements = xmlValidGetPotentialChildren ( element_desc - > content ,
elements , & nb_elements , 256 ) ;
for ( i = 0 ; i < nb_elements ; i + + ) {
test_node - > name = elements [ i ] ;
2001-05-19 17:24:56 +04:00
if ( xmlValidateOneElement ( & vctxt , parent - > doc , parent ) ) {
2001-02-23 20:55:21 +03:00
int j ;
for ( j = 0 ; j < nb_valid_elements ; j + + )
2004-05-08 06:32:07 +04:00
if ( xmlStrEqual ( elements [ i ] , names [ j ] ) ) break ;
names [ nb_valid_elements + + ] = elements [ i ] ;
2001-02-23 20:55:21 +03:00
if ( nb_valid_elements > = max ) break ;
}
}
/*
* Restore the tree structure
*/
if ( prev ) prev - > next = prev_next ;
if ( next ) next - > prev = next_prev ;
parent - > children = parent_childs ;
parent - > last = parent_last ;
2002-02-08 16:37:46 +03:00
/*
* Free up the dummy node
*/
test_node - > name = name ;
xmlFreeNode ( test_node ) ;
2001-02-23 20:55:21 +03:00
return ( nb_valid_elements ) ;
}
2003-09-28 22:58:27 +04:00
# endif /* LIBXML_VALID_ENABLED */
2005-04-01 17:11:58 +04:00
# define bottom_valid
# include "elfgcchack.h"