1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-02-25 09:57:23 +03:00

updated the policy on private mail answers more work on Relax-NG

* README: updated the policy on private mail answers
* relaxng.c: more work on Relax-NG
* test/relaxng/* result/relaxng/*: augmented/updated the
  regression tests
Daniel
This commit is contained in:
Daniel Veillard 2003-01-25 18:01:32 +00:00
parent 831e8fdd04
commit dd1655c579
25 changed files with 524 additions and 18 deletions

View File

@ -1,3 +1,10 @@
Sat Jan 25 18:59:54 CET 2003 Daniel Veillard <daniel@veillard.com>
* README: updated the policy on private mail answers
* relaxng.c: more work on Relax-NG
* test/relaxng/* result/relaxng/*: augmented/updated the
regression tests
Fri Jan 24 15:12:44 CET 2003 Daniel Veillard <daniel@veillard.com>
* error.c parser.c tree.c: applied a documentation patch from

4
README
View File

@ -15,6 +15,10 @@ A mailing-list xml@gnome.org is available, to subscribe:
The list archive is at:
http://mail.gnome.org/archives/xml/
All technical answers asked privately will be automatically answered on
the list and archived for public access unless pricacy is explicitely
required and justified.
Daniel Veillard
$Id$

438
relaxng.c
View File

@ -74,11 +74,6 @@ struct _xmlRelaxNGGrammar {
};
#if 0
struct _xmlRelaxNGSchema {
};
#endif
typedef enum {
XML_RELAXNG_EMPTY = 0, /* an empty pattern */
XML_RELAXNG_NOT_ALLOWED, /* not allowed top */
@ -103,6 +98,7 @@ struct _xmlRelaxNGDefine {
xmlNodePtr node; /* the node in the source */
xmlChar *name; /* the element local name if present */
xmlChar *ns; /* the namespace local name if present */
void *data; /* data lib or specific pointer */
xmlRelaxNGDefinePtr content;/* the expected content */
xmlRelaxNGDefinePtr next; /* list within grouping sequences */
xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */
@ -195,6 +191,61 @@ struct _xmlRelaxNGValidCtxt {
int flags; /* validation flags */
};
/************************************************************************
* *
* Preliminary type checking interfaces *
* *
************************************************************************/
/**
* xmlRelaxNGTypeHave:
* @data: data needed for the library
* @type: the type name
* @value: the value to check
*
* Function provided by a type library to check if a type is exported
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar *type);
/**
* xmlRelaxNGTypeCheck:
* @data: data needed for the library
* @type: the type name
* @value: the value to check
*
* Function provided by a type library to check if a value match a type
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar *type,
const xmlChar *value);
/**
* xmlRelaxNGTypeCompare:
* @data: data needed for the library
* @type: the type name
* @value1: the first value
* @value2: the second value
*
* Function provided by a type library to compare two values accordingly
* to a type.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar *type,
const xmlChar *value1,
const xmlChar *value2);
typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
struct _xmlRelaxNGTypeLibrary {
const xmlChar *namespace; /* the datatypeLibrary value */
void *data; /* data needed for the library */
xmlRelaxNGTypeHave have; /* the export function */
xmlRelaxNGTypeCheck check; /* the checking function */
xmlRelaxNGTypeCompare comp; /* the compare function */
};
/************************************************************************
* *
* Allocation functions *
@ -600,8 +651,226 @@ xmlRelaxNGErrorContext(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGPtr schema,
* *
************************************************************************/
/**
* xmlRelaxNGSchemaTypeHave:
* @data: data needed for the library
* @type: the type name
*
* Check if the given type is provided by
* the W3C XMLSchema Datatype library.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
static int
xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED,
const xmlChar *type ATTRIBUTE_UNUSED) {
TODO
return(1);
}
/**
* xmlRelaxNGSchemaTypeCheck:
* @data: data needed for the library
* @type: the type name
* @value: the value to check
*
* Check if the given type and value are validated by
* the W3C XMLSchema Datatype library.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
static int
xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
const xmlChar *type ATTRIBUTE_UNUSED,
const xmlChar *value ATTRIBUTE_UNUSED) {
TODO
return(1);
}
/**
* xmlRelaxNGSchemaTypeCompare:
* @data: data needed for the library
* @type: the type name
* @value1: the first value
* @value2: the second value
*
* Compare two values accordingly a type from the W3C XMLSchema
* Datatype library.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
static int
xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
const xmlChar *type ATTRIBUTE_UNUSED,
const xmlChar *value1 ATTRIBUTE_UNUSED,
const xmlChar *value2 ATTRIBUTE_UNUSED) {
TODO
return(1);
}
/**
* xmlRelaxNGDefaultTypeHave:
* @data: data needed for the library
* @type: the type name
*
* Check if the given type is provided by
* the default datatype library.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
static int
xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar *type) {
if (type == NULL)
return(-1);
if (xmlStrEqual(type, BAD_CAST "string"))
return(1);
if (xmlStrEqual(type, BAD_CAST "token"))
return(1);
return(0);
}
/**
* xmlRelaxNGDefaultTypeCheck:
* @data: data needed for the library
* @type: the type name
* @value: the value to check
*
* Check if the given type and value are validated by
* the default datatype library.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
static int
xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
const xmlChar *type ATTRIBUTE_UNUSED,
const xmlChar *value ATTRIBUTE_UNUSED) {
return(1);
}
/**
* xmlRelaxNGDefaultTypeCompare:
* @data: data needed for the library
* @type: the type name
* @value1: the first value
* @value2: the second value
*
* Compare two values accordingly a type from the default
* datatype library.
*
* Returns 1 if yes, 0 if no and -1 in case of error.
*/
static int
xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
const xmlChar *type ATTRIBUTE_UNUSED,
const xmlChar *value1 ATTRIBUTE_UNUSED,
const xmlChar *value2 ATTRIBUTE_UNUSED) {
TODO
return(1);
}
static int xmlRelaxNGTypeInitialized = 0;
static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
/**
* xmlRelaxNGFreeTypeLibrary:
* @lib: the type library structure
* @namespace: the URI bound to the library
*
* Free the structure associated to the type library
*/
static void
xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
const xmlChar *namespace ATTRIBUTE_UNUSED) {
if (lib == NULL)
return;
if (lib->namespace != NULL)
xmlFree((xmlChar *)lib->namespace);
xmlFree(lib);
}
/**
* xmlRelaxNGRegisterTypeLibrary:
* @namespace: the URI bound to the library
* @data: data associated to the library
* @have: the provide function
* @check: the checking function
* @comp: the comparison function
*
* Register a new type library
*
* Returns 0 in case of success and -1 in case of error.
*/
static int
xmlRelaxNGRegisterTypeLibrary(const xmlChar *namespace, void *data,
xmlRelaxNGTypeHave have, xmlRelaxNGTypeCheck check,
xmlRelaxNGTypeCompare comp) {
xmlRelaxNGTypeLibraryPtr lib;
int ret;
if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
(check == NULL) || (comp == NULL))
return(-1);
if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
xmlGenericError(xmlGenericErrorContext,
"Relax-NG types library '%s' already registered\n",
namespace);
return(-1);
}
lib = (xmlRelaxNGTypeLibraryPtr) xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
if (lib == NULL) {
xmlGenericError(xmlGenericErrorContext,
"Relax-NG types library '%s' malloc() failed\n",
namespace);
return (-1);
}
memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
lib->namespace = xmlStrdup(namespace);
lib->data = data;
lib->have = have;
lib->comp = comp;
lib->check = check;
ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
if (ret < 0) {
xmlGenericError(xmlGenericErrorContext,
"Relax-NG types library failed to register '%s'\n",
namespace);
xmlRelaxNGFreeTypeLibrary(lib, namespace);
return(-1);
}
return(0);
}
/**
* xmlRelaxNGInitTypes:
*
* Initilize the default type libraries.
*
* Returns 0 in case of success and -1 in case of error.
*/
static int
xmlRelaxNGInitTypes(void) {
if (xmlRelaxNGTypeInitialized != 0)
return(0);
xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
if (xmlRelaxNGRegisteredTypes == NULL) {
xmlGenericError(xmlGenericErrorContext,
"Failed to allocate sh table for Relax-NG types\n");
return(-1);
}
xmlRelaxNGRegisterTypeLibrary(
BAD_CAST "http://www.w3.org/2001/XMLSchema-datatypes",
NULL,
xmlRelaxNGSchemaTypeHave,
xmlRelaxNGSchemaTypeCheck,
xmlRelaxNGSchemaTypeCompare);
xmlRelaxNGRegisterTypeLibrary(
xmlRelaxNGNs,
NULL,
xmlRelaxNGDefaultTypeHave,
xmlRelaxNGDefaultTypeCheck,
xmlRelaxNGDefaultTypeCompare);
xmlRelaxNGTypeInitialized = 1;
return(0);
}
/**
@ -611,7 +880,12 @@ xmlRelaxNGInitTypes(void) {
*/
void
xmlRelaxNGCleanupTypes(void) {
if (xmlRelaxNGTypeInitialized == 0)
return;
xmlSchemaCleanupTypes();
xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
xmlRelaxNGFreeTypeLibrary);
xmlRelaxNGTypeInitialized = 0;
}
/************************************************************************
@ -650,7 +924,6 @@ xmlRelaxNGIsBlank(xmlChar *str) {
return(1);
}
#if 0
/**
* xmlRelaxNGGetDataTypeLibrary:
* @ctxt: a Relax-NG parser context
@ -665,15 +938,10 @@ xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
xmlNodePtr node) {
xmlChar *ret, *escape;
#ifdef DEBUG
xmlGenericError(xmlGenericErrorContext,
"xmlRelaxNGGetDataTypeLibrary()\n");
#endif
if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
if (ret != NULL) {
escape = xmlURIEscapeStr(ret, BAD_CAST "");
escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
if (escape == NULL) {
return(ret);
}
@ -686,7 +954,7 @@ xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
if (IS_RELAXNG(node, "element")) {
ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
if (ret != NULL) {
escape = xmlURIEscapeStr(ret, BAD_CAST "");
escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
if (escape == NULL) {
return(ret);
}
@ -698,7 +966,81 @@ xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
}
return(NULL);
}
#endif
/**
* xmlRelaxNGParseData:
* @ctxt: a Relax-NG parser context
* @node: the data node.
*
* parse the content of a RelaxNG data node.
*
* Returns the definition pointer or NULL in case of error
*/
static xmlRelaxNGDefinePtr
xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
xmlRelaxNGDefinePtr def = NULL;
xmlRelaxNGTypeLibraryPtr lib;
xmlChar *type;
xmlChar *library;
xmlNodePtr content;
int tmp;
type = xmlGetProp(node, BAD_CAST "type");
if (type == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"data has no type\n");
ctxt->nbErrors++;
return(NULL);
}
library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
if (library == NULL)
library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
def = xmlRelaxNGNewDefine(ctxt, node);
if (def == NULL) {
xmlFree(type);
return(NULL);
}
def->type = XML_RELAXNG_DATATYPE;
def->name = type;
def->ns = library;
lib = (xmlRelaxNGTypeLibraryPtr)
xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
if (lib == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Use of unregistered type library '%s'\n",
library);
ctxt->nbErrors++;
def->data = NULL;
} else {
def->data = lib;
if (lib->have == NULL) {
ctxt->error(ctxt->userData,
"Internal error with type library '%s': no 'have'\n",
library);
ctxt->nbErrors++;
} else {
tmp = lib->have(lib->data, def->name);
if (tmp != 1) {
ctxt->error(ctxt->userData,
"Error type '%s' is not exported by type library '%s'\n",
def->name, library);
ctxt->nbErrors++;
}
}
}
content = node->children;
while (content != NULL) {
TODO
content = content->next;
}
return(def);
}
/**
* xmlRelaxNGParseDefine:
@ -887,6 +1229,8 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
}
}
}
} else if (IS_RELAXNG(node, "data")) {
def = xmlRelaxNGParseData(ctxt, node);
} else if (IS_RELAXNG(node, "define")) {
xmlRelaxNGParseDefine(ctxt, node);
def = NULL;
@ -2201,6 +2545,45 @@ xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
return(node);
}
/**
* xmlRelaxNGValidateDatatype:
* @ctxt: a Relax-NG validation context
* @value: the string value
* @type: the datatype definition
*
* Validate the given value against the dataype
*
* Returns 0 if the validation succeeded or an error code.
*/
static int
xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value,
xmlRelaxNGDefinePtr define) {
int ret;
xmlRelaxNGTypeLibraryPtr lib;
if ((define == NULL) || (define->data == NULL)) {
return(-1);
}
lib = (xmlRelaxNGTypeLibraryPtr) define->data;
if (lib->check != NULL)
ret = lib->check(lib->data, define->name, value);
else
ret = -1;
if (ret < 0) {
VALID_CTXT();
VALID_ERROR("Internal: failed to validate type %s\n", define->name);
return(-1);
} else if (ret == 1) {
ret = 0;
} else {
VALID_CTXT();
VALID_ERROR("Type %s doesn't allow value %s\n", define->name, value);
return(-1);
ret = -1;
}
return(ret);
}
/**
* xmlRelaxNGValidateValue:
* @ctxt: a Relax-NG validation context
@ -2590,7 +2973,32 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
case XML_RELAXNG_DEF:
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
break;
case XML_RELAXNG_DATATYPE:
case XML_RELAXNG_DATATYPE: {
xmlChar *content;
content = xmlNodeGetContent(node);
ret = xmlRelaxNGValidateDatatype(ctxt, content, define);
if (ret == -1) {
VALID_CTXT();
VALID_ERROR("internal error validating %s\n", define->name);
} else if (ret == 0) {
ctxt->state->seq = node->next;
}
/*
* TODO cover the problems with
* <p>12<!-- comment -->34</p>
* TODO detect full element coverage at compilation time.
*/
if ((node != NULL) && (node->next != NULL)) {
VALID_CTXT();
VALID_ERROR("The data does not cover the full element %s\n",
node->parent->name);
ret = -1;
}
if (content != NULL)
xmlFree(content);
break;
}
case XML_RELAXNG_VALUE:
TODO
break;

View File

@ -1,3 +1,3 @@
error detected at relaxng.c:2429
error detected at relaxng.c:2477
error detected at relaxng.c:2812
error detected at relaxng.c:2860
xmlRelaxNGValidateDefinition(): validated card : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(name): -1
xmlRelaxNGValidateDefinition(): validated email : 0
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:2477
error detected at relaxng.c:2860
xmlRelaxNGValidateDefinition(): validated addressBook : -1

View File

@ -0,0 +1 @@
./test/relaxng/tutor5_1_1.xml validates

View File

@ -0,0 +1,3 @@
Unimplemented block at relaxng.c:667
Unimplemented block at relaxng.c:686
xmlRelaxNGValidateDefinition(): validated number : 0

View File

@ -0,0 +1 @@
./test/relaxng/tutor5_2_1.xml validates

View File

@ -0,0 +1,7 @@
Unimplemented block at relaxng.c:667
Unimplemented block at relaxng.c:667
Unimplemented block at relaxng.c:686
xmlRelaxNGValidateDefinition(): validated x : 0
Unimplemented block at relaxng.c:686
xmlRelaxNGValidateDefinition(): validated y : 0
xmlRelaxNGValidateDefinition(): validated point : 0

View File

@ -0,0 +1,2 @@
The data does not cover the full element bad
./test/relaxng/tutor5_3_1.xml validation generated an internal error

View File

@ -0,0 +1,3 @@
error detected at relaxng.c:2993
xmlRelaxNGValidateDefinition(): validated note : 0
xmlRelaxNGValidateDefinition(): validated bad : -1

View File

@ -0,0 +1 @@
./test/relaxng/tutor5_4_1.xml validates

View File

@ -0,0 +1,2 @@
xmlRelaxNGValidateAttribute(note): 0
xmlRelaxNGValidateDefinition(): validated ok : 0

View File

@ -0,0 +1,3 @@
<element name="number" xmlns="http://relaxng.org/ns/structure/1.0">
<data type="integer" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"/>
</element>

View File

@ -0,0 +1 @@
<number>5</number>

View File

@ -0,0 +1,9 @@
<element name="point" xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<element name="x">
<data type="double"/>
</element>
<element name="y">
<data type="double"/>
</element>
</element>

View File

@ -0,0 +1 @@
<point><x>1</x><y>5.20</y></point>

View File

@ -0,0 +1,6 @@
<element name="bad" xmlns="http://relaxng.org/ns/structure/1.0">
<data type="string"/>
<element name="note">
<text/>
</element>
</element>

View File

@ -0,0 +1 @@
<bad>5<note>fails</note></bad>

View File

@ -0,0 +1,6 @@
<element name="ok" xmlns="http://relaxng.org/ns/structure/1.0">
<data type="string"/>
<attribute name="note">
<text/>
</attribute>
</element>

View File

@ -0,0 +1 @@
<ok note="foo">5</ok>

View File

@ -0,0 +1,5 @@
<element name="email" xmlns="http://relaxng.org/ns/structure/1.0">
<data type="string">
<param name="maxLength">127</param>
</data>
</element>

10
test/relaxng/tutor6_1.rng Normal file
View File

@ -0,0 +1,10 @@
<element name="card" xmlns="http://relaxng.org/ns/structure/1.0">
<attribute name="name"/>
<attribute name="email"/>
<attribute name="preferredFormat">
<choice>
<value>html</value>
<value>text</value>
</choice>
</attribute>
</element>

14
test/relaxng/tutor6_2.rng Normal file
View File

@ -0,0 +1,14 @@
<element name="card" xmlns="http://relaxng.org/ns/structure/1.0">
<element name="name">
<text/>
</element>
<element name="email">
<text/>
</element>
<element name="preferredFormat">
<choice>
<value>html</value>
<value>text</value>
</choice>
</element>
</element>

10
test/relaxng/tutor6_3.rng Normal file
View File

@ -0,0 +1,10 @@
<element name="card" xmlns="http://relaxng.org/ns/structure/1.0">
<attribute name="name"/>
<attribute name="email"/>
<attribute name="preferredFormat">
<choice>
<value type="string">html</value>
<value type="string">text</value>
</choice>
</attribute>
</element>