File:
[Public] /
XML /
schema.c
Revision
1.3:
download - view:
text,
annotated -
select for diffs
Wed Oct 25 19:26:53 2000 UTC (23 years, 7 months ago) by
veillard
Branches:
MAIN
CVS tags:
LIBXML_2_2_8,
HEAD
Message cleanup Jumbo Diff:
- in xmlerror.h : I added the export of an error context type (void *)
an error handler type xmlGenericErrorFunc
there is an interface
xmlSetGenericErrorFunc (void *ctx, xmlGenericErrorFunc handler);
to reset the error handling routine and its argument
(by default it's equivalent to respectively fprintf and stderr.
- in all the c files, all wild accesses to stderr or stdout within
the library have been replaced to the handler.
- removed slashrdf.c now obsolete
Daniel
/*
* schema.c : implementation of the XML Schema handling and
* schema validity checking
*
* See Copyright for the status of this software.
*
* Daniel.Veillard@w3.org
*/
#ifdef WIN32
#include "win32config.h"
#else
#include "config.h"
#endif
#include <libxml/schema.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#define DEBUG 1 /* very verobose output */
/*
* The XML Schemas namespaces
*/
static const xmlChar *xmlSchemaNs = (const xmlChar *)
"http://www.w3.org/1999/XMLSchema";
#define IS_SCHEMA(node, type) \
((node != NULL) && (node->ns != NULL) && \
(xmlStrEqual(node->name, (const xmlChar *) type)) && \
(xmlStrEqual(node->ns->href, xmlSchemaNs)))
/******
static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
"http://www.w3.org/1999/XMLSchema-instance";
#define IS_SCHEMA_INSTANCE(node, type) \
((node != NULL) && (node->ns != NULL) && \
(xmlStrEqual(node->name, (const xmlChar *) type)) && \
(xmlStrEqual(node->ns->href, xmlSchemaInstanceNs)))
******/
/*
* XML Schemas defines multiple type of types.
*/
typedef enum {
XML_SCHEMA_TYPE_BASIC = 1,
XML_SCHEMA_TYPE_SIMPLE,
XML_SCHEMA_TYPE_COMPLEX,
XML_SCHEMA_TYPE_UR,
XML_SCHEMA_TYPE_RESTRICTION,
XML_SCHEMA_TYPE_EXTENTION
} xmlSchemaTypeType;
/**
* A facet definition
typedef struct _xmlSchemaFacet xmlSchemaFacet;
typedef xmlSchemaFacet *xmlSchemaFacetPtr;
struct _xmlSchemaFacet {
};
*/
/**
* A content type definition
typedef struct _xmlSchemaContentType xmlSchemaContentType;
typedef xmlSchemaContentType *xmlSchemaContentTypePtr;
struct _xmlSchemaContentType {
};
*/
/**
* Simple type definition.
*/
typedef struct _xmlSchemaType xmlSchemaType;
typedef xmlSchemaType *xmlSchemaTypePtr;
struct _xmlSchemaType {
const xmlChar *name; /* The type name */
const xmlChar *annot; /* the annotation */
struct _xmlSchemaType *next; /* Next in the list */
xmlSchemaTypeType type; /* The kind of schema type */
};
/**
* Derived type definition.
*/
typedef struct _xmlSchemaDerivedType xmlSchemaDerivedType;
typedef xmlSchemaDerivedType *xmlSchemaDerivedTypePtr;
struct _xmlSchemaDerivedType {
const xmlChar *name;
const xmlChar *annot; /* the annotation */
};
/**
* A notation definition.
*/
typedef struct _xmlSchemaNotation xmlSchemaNotation;
typedef xmlSchemaNotation *xmlSchemaNotationPtr;
struct _xmlSchemaNotation {
const xmlChar *name;
const xmlChar *annot; /* the annotation */
struct _xmlSchemaNotation *next; /* Next in the list */
const xmlChar *identifier;
};
/**
* An attribute definition.
*/
typedef struct _xmlSchemaAttribute xmlSchemaAttribute;
typedef xmlSchemaAttribute *xmlSchemaAttributePtr;
struct _xmlSchemaAttribute {
const xmlChar *name;
const xmlChar *annot; /* the annotation */
struct _xmlSchemaAttribute *next; /* Next in the list */
xmlSchemaTypePtr base;
int occurs;
const xmlChar *defValue;
};
/**
* An element definition.
*/
typedef struct _xmlSchemaElement xmlSchemaElement;
typedef xmlSchemaElement *xmlSchemaElementPtr;
struct _xmlSchemaElement {
const xmlChar *name;
const xmlChar *annot; /* the annotation */
struct _xmlSchemaElement *next; /* Next in the list */
};
/**
* A Schemas definition
*/
struct _xmlSchema {
const xmlChar *name; /* schema name */
const xmlChar *annot; /* the annotation */
const xmlChar *targetNameSpace; /* the target namespace */
xmlSchemaTypePtr typeDefs; /* the list of types definitions */
xmlSchemaAttributePtr attrDecl; /* attributes declarations */
xmlSchemaElementPtr elemDecl; /* elements declarations */
};
/************************************************************************
* *
* Allocation functions *
* *
************************************************************************/
/**
* xmlSchemaNewSchema:
* @ctxt: a schema validation context (optional)
*
* Allocate a new Schema structure.
*
* Returns the newly allocated structure or NULL in case or error
*/
xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaValidCtxtPtr ctxt) {
xmlSchemaPtr ret;
ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
if (ret == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Out of memory\n");
return(NULL);
}
memset(ret, 0, sizeof(xmlSchema));
return(ret);
}
/**
* xmlSchemaFreeAttribute:
* @schema: a schema attribute structure
*
* Deallocate a Schema Attribute structure.
*/
void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr) {
if (attr == NULL)
return;
if (attr->name != NULL)
xmlFree((xmlChar *) attr->name);
memset(attr, -1, sizeof(xmlSchemaAttribute));
xmlFree(attr);
}
/**
* xmlSchemaFreeAttributeList:
* @cur: a schema attribute list structure
*
* Deallocate a Schema Attribute structure.
*/
void
xmlSchemaFreeAttributeList(xmlSchemaAttributePtr cur) {
xmlSchemaAttributePtr next;
if (cur == NULL)
return;
while (cur != NULL) {
next = cur->next;
xmlSchemaFreeAttribute(cur);
cur = next;
}
}
/**
* xmlSchemaFreeElement:
* @schema: a schema element structure
*
* Deallocate a Schema Element structure.
*/
void
xmlSchemaFreeElement(xmlSchemaElementPtr elem) {
if (elem == NULL)
return;
if (elem->name != NULL)
xmlFree((xmlChar *) elem->name);
memset(elem, -1, sizeof(xmlSchemaElement));
xmlFree(elem);
}
/**
* xmlSchemaFreeElementList:
* @cur: a schema element list structure
*
* Deallocate a Schema Element structure.
*/
void
xmlSchemaFreeElementList(xmlSchemaElementPtr cur) {
xmlSchemaElementPtr next;
if (cur == NULL)
return;
while (cur != NULL) {
next = cur->next;
xmlSchemaFreeElement(cur);
cur = next;
}
}
/**
* xmlSchemaFree:
* @schema: a schema structure
*
* Deallocate a Schema structure.
*/
void
xmlSchemaFree(xmlSchemaPtr schema) {
if (schema == NULL)
return;
if (schema->name != NULL)
xmlFree((xmlChar *) schema->name);
if (schema->attrDecl != NULL)
xmlSchemaFreeAttributeList(schema->attrDecl);
if (schema->elemDecl != NULL)
xmlSchemaFreeElementList(schema->elemDecl);
memset(schema, -1, sizeof(xmlSchema));
xmlFree(schema);
}
/**
* xmlSchemaAddAttribute:
* @ctxt: a schema validation context
* @schema: the schema being built
* @name: the item name
*
* Add an XML schema Attrribute declaration
* *WARNING* this interface is highly subject to change
*
* Returns the new struture or NULL in case of error
*/
xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
const xmlChar *name) {
xmlSchemaAttributePtr ret = NULL;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddAttribute()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return(NULL);
ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
if (ret == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Out of memory\n");
return(NULL);
}
memset(ret, 0, sizeof(xmlSchemaAttribute));
ret->name = name;
ret->next = schema->attrDecl;
schema->attrDecl = ret;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddAttribute() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaAddElement:
* @ctxt: a schema validation context
* @schema: the schema being built
* @name: the item name
*
* Add an XML schema Element declaration
* *WARNING* this interface is highly subject to change
*
* Returns the new struture or NULL in case of error
*/
xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
const xmlChar *name) {
xmlSchemaElementPtr ret = NULL;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddElement()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return(NULL);
ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
if (ret == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Out of memory\n");
return(NULL);
}
memset(ret, 0, sizeof(xmlSchemaElement));
ret->name = name;
ret->next = schema->elemDecl;
schema->elemDecl = ret;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddElement() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaAddSimpleType:
* @ctxt: a schema validation context
* @schema: the schema being built
* @name: the item name
*
* Add an XML schema Simple Type definition
* *WARNING* this interface is highly subject to change
*
* Returns the new struture or NULL in case of error
*/
xmlSchemaTypePtr
xmlSchemaAddSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
const xmlChar *name) {
xmlSchemaTypePtr ret = NULL;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddSimpleType()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return(NULL);
ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
if (ret == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Out of memory\n");
return(NULL);
}
memset(ret, 0, sizeof(xmlSchemaType));
ret->name = name;
ret->type = XML_SCHEMA_TYPE_SIMPLE;
ret->next = schema->typeDefs;
schema->typeDefs = ret;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddSimpleType() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaAddComplexType:
* @ctxt: a schema validation context
* @schema: the schema being built
* @name: the item name
*
* Add an XML schema Complex Type definition
* *WARNING* this interface is highly subject to change
*
* Returns the new struture or NULL in case of error
*/
xmlSchemaTypePtr
xmlSchemaAddComplexType(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
const xmlChar *name) {
xmlSchemaTypePtr ret = NULL;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddComplexType()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
return(NULL);
ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
if (ret == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Out of memory\n");
return(NULL);
}
memset(ret, 0, sizeof(xmlSchemaType));
ret->name = name;
ret->type = XML_SCHEMA_TYPE_COMPLEX;
ret->next = schema->typeDefs;
schema->typeDefs = ret;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaAddComplexType() finished\n");
#endif
return(ret);
}
/************************************************************************
* *
* Shema extraction from an Infoset *
* *
************************************************************************/
/**
* xmlSchemaParseAnnotation:
* @ctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
*
* parse a XML schema Attrribute declaration
* *WARNING* this interface is highly subject to change
*
* Returns -1 in case of error, 0 if the declaration is inproper and
* 1 in case of success.
*/
int
xmlSchemaParseAnnotation(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node) {
int ret = 0;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseAnnotation()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return(-1);
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseAnnotation() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaParseAttribute:
* @ctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
*
* parse a XML schema Attrribute declaration
* *WARNING* this interface is highly subject to change
*
* Returns -1 in case of error, 0 if the declaration is inproper and
* 1 in case of success.
*/
xmlSchemaAttributePtr
xmlSchemaParseAttribute(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node) {
xmlChar *name;
xmlSchemaAttributePtr ret;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseAttribute()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return(NULL);
name = xmlGetProp(node, (const xmlChar *) "name");
if (name == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Attribute has no name\n");
return(NULL);
}
ret = xmlSchemaAddAttribute(ctxt, schema, name);
if (ret == NULL) {
xmlFree(name);
return(NULL);
}
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseAttribute() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaParseElement:
* @ctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
*
* parse a XML schema Element declaration
* *WARNING* this interface is highly subject to change
*
* Returns -1 in case of error, 0 if the declaration is inproper and
* 1 in case of success.
*/
xmlSchemaElementPtr
xmlSchemaParseElement(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node) {
xmlChar *name;
xmlSchemaElementPtr ret;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseElement()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return(NULL);
name = xmlGetProp(node, (const xmlChar *) "name");
if (name == NULL) {
if ((ctxt != NULL) && (ctxt->error != NULL))
ctxt->error(ctxt->userData, "Element has no name\n");
return(NULL);
}
ret = xmlSchemaAddElement(ctxt, schema, name);
if (ret == NULL) {
xmlFree(name);
return(NULL);
}
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseElement() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaParseSimpleType:
* @ctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
*
* parse a XML schema Simple Type definition
* *WARNING* this interface is highly subject to change
*
* Returns -1 in case of error, 0 if the declaration is inproper and
* 1 in case of success.
*/
int
xmlSchemaParseSimpleType(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node) {
int ret = 0;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseSimpleType()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return(-1);
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseSimpleType() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaParseComplexType:
* @ctxt: a schema validation context
* @schema: the schema being built
* @node: a subtree containing XML Schema informations
*
* parse a XML schema Complex Type definition
* *WARNING* this interface is highly subject to change
*
* Returns -1 in case of error, 0 if the declaration is inproper and
* 1 in case of success.
*/
int
xmlSchemaParseComplexType(xmlSchemaValidCtxtPtr ctxt, xmlSchemaPtr schema,
xmlNodePtr node) {
int ret = 0;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseComplexType()\n");
#endif
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
return(-1);
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParseComplexType() finished\n");
#endif
return(ret);
}
/**
* xmlSchemaParse:
* @ctxt: a schema validation context
* @node: a subtree containing XML Schema informations
*
* parse a XML schema definition from a node set
* *WARNING* this interface is highly subject to change
*
* Returns the internal XML Schema structure built from the resource or
* NULL in case of error
*/
xmlSchemaPtr
xmlSchemaParse(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) {
xmlSchemaPtr schema = NULL;
xmlNodePtr child;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParse()\n");
#endif
if ((ctxt == NULL) || (node == NULL))
return(NULL);
if (IS_SCHEMA(node, "schema")) {
schema = xmlSchemaNewSchema(ctxt);
child = node->children;
while (child != NULL) {
if (IS_SCHEMA(child, "element"))
xmlSchemaParseElement(ctxt, schema, child);
else if (IS_SCHEMA(child, "attribute"))
xmlSchemaParseAttribute(ctxt, schema, child);
else if (IS_SCHEMA(child, "annotation"))
xmlSchemaParseAnnotation(ctxt, schema, child);
else if (IS_SCHEMA(child, "complexType"))
xmlSchemaParseComplexType(ctxt, schema, child);
else if (IS_SCHEMA(child, "simpleType"))
xmlSchemaParseSimpleType(ctxt, schema, child);
child = child->next;
}
}
#ifdef DEBUG
if (schema == NULL)
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParse() failed\n");
else
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaParse() finished\n");
#endif
return(schema);
}
/************************************************************************
* *
* Reading/Writing Schemas *
* *
************************************************************************/
/**
* xmlSchemaLoad:
* @ctxt: a schema validation context
* @URL: the location of the schema
*
* Load, XML parse a schema definition resource and build an internal
* XML Shema struture which can be used to validate instances.
* *WARNING* this interface is highly subject to change
*
* Returns the internal XML Schema structure built from the resource or
* NULL in case of error
*/
xmlSchemaPtr
xmlSchemaLoad(xmlSchemaValidCtxtPtr ctxt, const char *URL) {
xmlSchemaPtr ret;
xmlDocPtr doc;
xmlNodePtr root;
if ((URL == NULL) || (ctxt == NULL))
return(NULL);
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaLoad(%s)\n", URL);
#endif
/*
* First step is to parse the input document into an DOM/Infoset
* TODO: do error redirections
*/
doc = xmlParseFile(URL);
if (doc == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData, "xmlSchemaLoad: %s is not WellFormed\n",
URL);
return(NULL);
}
/*
* Then extract the root and Schema parse it
*/
root = xmlDocGetRootElement(doc);
if (root == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData, "xmlSchemaLoad: %s is empty\n",
URL);
return(NULL);
}
ret = xmlSchemaParse(ctxt, root);
/*
* Cleanup
*/
xmlFreeDoc(doc);
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaLoad(%s) finished\n", URL);
#endif
return(ret);
}
/**
* xmlSchemaValidate:
* @ctxt: a schema validation context
* @instance: the subtree (infoset) instance to validate.
* @schema: the internal XML Schema structure
*
* Attempts to schema validate an instance against an XML Schema
*
* Returns -1 in case of general error, 0 if the instance does not validate
* and 1 if it validates
*/
int
xmlSchemaValidate(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr instance,
xmlSchemaPtr schema) {
int ret = 0;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaValidate()\n");
#endif
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlSchemaValidate() finished : %d\n", ret);
#endif
return(ret);
}
Webmaster