1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-29 11:41:22 +03:00

added Datatype ID and IDREF, usable from RelaxNG now need to add a new

* relaxng.c valid.c xmlschemastypes.c: added Datatype ID
  and IDREF, usable from RelaxNG now
* include/libxml/xmlschemastypes.h: need to add a new interface
  because the validation modifies the infoset
* test/relaxng/testsuite.xml: extended the testsuite
Daniel
This commit is contained in:
Daniel Veillard
2003-03-18 00:31:04 +00:00
parent 952379b780
commit c3da18a148
7 changed files with 226 additions and 30 deletions

View File

@ -1,3 +1,11 @@
Tue Mar 18 01:28:15 CET 2003 Daniel Veillard <daniel@veillard.com>
* relaxng.c valid.c xmlschemastypes.c: added Datatype ID
and IDREF, usable from RelaxNG now
* include/libxml/xmlschemastypes.h: need to add a new interface
because the validation modifies the infoset
* test/relaxng/testsuite.xml: extended the testsuite
Mon Mar 17 16:34:07 CET 2003 Daniel Veillard <daniel@veillard.com>
* relaxng.c: fixed the last core RelaxNG bug known #107083,

View File

@ -37,6 +37,7 @@ typedef enum {
XML_RELAXNG_ERR_MEMORY,
XML_RELAXNG_ERR_TYPE,
XML_RELAXNG_ERR_TYPEVAL,
XML_RELAXNG_ERR_DUPID,
XML_RELAXNG_ERR_TYPECMP,
XML_RELAXNG_ERR_NOSTATE,
XML_RELAXNG_ERR_NODEFINE,

View File

@ -29,6 +29,10 @@ xmlSchemaTypePtr xmlSchemaGetPredefinedType (const xmlChar *name,
int xmlSchemaValidatePredefinedType (xmlSchemaTypePtr type,
const xmlChar *value,
xmlSchemaValPtr *val);
int xmlSchemaValPredefTypeNode (xmlSchemaTypePtr type,
const xmlChar *value,
xmlSchemaValPtr *val,
xmlNodePtr node);
int xmlSchemaValidateFacet (xmlSchemaTypePtr base,
xmlSchemaFacetPtr facet,
const xmlChar *value,

128
relaxng.c
View File

@ -154,16 +154,19 @@ struct _xmlRelaxNGDefine {
* A RelaxNGs definition
*/
struct _xmlRelaxNG {
void *_private; /* unused by the library for users or bindings */
xmlRelaxNGGrammarPtr topgrammar;
xmlDocPtr doc;
int idref; /* requires idref checking */
xmlHashTablePtr defs; /* define */
xmlHashTablePtr refs; /* references */
xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
xmlRelaxNGIncludePtr includes; /* all the includes loaded */
int defNr; /* number of defines used */
xmlRelaxNGDefinePtr *defTab;/* pointer to the allocated definitions */
void *_private; /* unused by the library for users or bindings */
};
#define XML_RELAXNG_IN_ATTRIBUTE (1 << 0)
@ -218,6 +221,8 @@ struct _xmlRelaxNGParserCtxt {
int incNr; /* Depth of the include parsing stack */
int incMax; /* Max depth of the parsing stack */
xmlRelaxNGIncludePtr *incTab; /* array of incs */
int idref; /* requires idref checking */
};
#define FLAGS_IGNORABLE 1
@ -279,6 +284,7 @@ struct _xmlRelaxNGStates {
xmlRelaxNGValidStatePtr *tabState;
};
#define ERROR_IS_DUP 1
/**
* xmlRelaxNGValidError:
*
@ -288,6 +294,7 @@ typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
struct _xmlRelaxNGValidError {
xmlRelaxNGValidErr err; /* the error number */
int flags; /* flags */
xmlNodePtr node; /* the current node */
xmlNodePtr seq; /* the current child */
const xmlChar * arg1; /* first arg */
@ -309,6 +316,7 @@ struct _xmlRelaxNGValidCtxt {
xmlDocPtr doc; /* the document being validated */
int flags; /* validation flags */
int depth; /* validation depth */
int idref; /* requires idref checking */
/*
* Errors accumulated in branches may have to be stacked to be
@ -379,7 +387,8 @@ typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar *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, void **result);
const xmlChar *value, void **result,
xmlNodePtr node);
/**
* xmlRelaxNGFacetCheck:
@ -1355,6 +1364,7 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *URL,
* @err: the error code
* @arg1: the first string argument
* @arg2: the second string argument
* @dup: arg need to be duplicated
*
* Pushes a new error on top of the error stack
*
@ -1362,7 +1372,7 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *URL,
*/
static int
xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
const xmlChar *arg1, const xmlChar *arg2)
const xmlChar *arg1, const xmlChar *arg2, int dup)
{
xmlRelaxNGValidErrorPtr cur;
if (ctxt->errTab == NULL) {
@ -1391,8 +1401,15 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
return(ctxt->errNr);
cur = &ctxt->errTab[ctxt->errNr];
cur->err = err;
cur->arg1 = arg1;
cur->arg2 = arg2;
if (dup) {
cur->arg1 = xmlStrdup(arg1);
cur->arg2 = xmlStrdup(arg2);
cur->flags = ERROR_IS_DUP;
} else {
cur->arg1 = arg1;
cur->arg2 = arg2;
cur->flags = 0;
}
if (ctxt->state != NULL) {
cur->node = ctxt->state->node;
cur->seq = ctxt->state->seq;
@ -1409,23 +1426,27 @@ xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
* @ctxt: the validation context
*
* Pops the top error from the error stack
*
* Returns the error just removed
*/
static xmlRelaxNGValidErrorPtr
static void
xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
{
xmlRelaxNGValidErrorPtr ret;
xmlRelaxNGValidErrorPtr cur;
if (ctxt->errNr <= 0)
return (NULL);
return;
ctxt->errNr--;
if (ctxt->errNr > 0)
ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
else
ctxt->err = NULL;
ret = &ctxt->errTab[ctxt->errNr];
return (ret);
cur = &ctxt->errTab[ctxt->errNr];
if (cur->flags & ERROR_IS_DUP) {
xmlFree((xmlChar *)cur->arg1);
cur->arg1 = NULL;
xmlFree((xmlChar *)cur->arg2);
cur->arg2 = NULL;
cur->flags = 0;
}
}
/**
@ -1593,9 +1614,11 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *URL,
* *
************************************************************************/
#define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL);
#define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL);
#define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c);
#define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
#define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
#define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
#define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
#define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
#ifdef DEBUG
static const char *
@ -1662,6 +1685,9 @@ xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar *arg1,
case XML_RELAXNG_ERR_TYPEVAL:
snprintf(msg, 1000, "Type %s doesn't allow value %s", arg1, arg2);
break;
case XML_RELAXNG_ERR_DUPID:
snprintf(msg, 1000, "ID %s redefined", arg1);
break;
case XML_RELAXNG_ERR_TYPECMP:
snprintf(msg, 1000, "failed to compare type %s", arg1);
break;
@ -1867,6 +1893,15 @@ xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt) {
err = &ctxt->errTab[i];
xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
err->arg1, err->arg2);
if (err->flags & ERROR_IS_DUP) {
if (err->arg1 != NULL)
xmlFree((xmlChar *)err->arg1);
err->arg1 = NULL;
if (err->arg2 != NULL)
xmlFree((xmlChar *)err->arg2);
err->arg2 = NULL;
err->flags = 0;
}
}
ctxt->errNr = 0;
}
@ -1876,13 +1911,14 @@ xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt) {
* @err: the error number
* @arg1: the first argument
* @arg2: the second argument
* @dup: need to dup the args
*
* Register a validation error, either generating it if it's sure
* or stacking it for later handling if unsure.
*/
static void
xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
const xmlChar *arg1, const xmlChar *arg2)
const xmlChar *arg1, const xmlChar *arg2, int dup)
{
if ((ctxt == NULL) || (ctxt->error == NULL))
return;
@ -1910,7 +1946,7 @@ xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
* Stack the error for later processing if needed
*/
else {
xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2);
xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
}
}
@ -1952,6 +1988,7 @@ xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED,
* @data: data needed for the library
* @type: the type name
* @value: the value to check
* @node: the node
*
* Check if the given type and value are validated by
* the W3C XMLSchema Datatype library.
@ -1962,7 +1999,8 @@ static int
xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
const xmlChar *type,
const xmlChar *value,
void **result) {
void **result,
xmlNodePtr node) {
xmlSchemaTypePtr typ;
int ret;
@ -1978,8 +2016,10 @@ xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
BAD_CAST "http://www.w3.org/2001/XMLSchema");
if (typ == NULL)
return(-1);
ret = xmlSchemaValidatePredefinedType(typ, value,
(xmlSchemaValPtr *) result);
ret = xmlSchemaValPredefTypeNode(typ, value,
(xmlSchemaValPtr *) result, node);
if (ret == 2) /* special ID error code */
return(2);
if (ret == 0)
return(1);
if (ret > 0)
@ -2107,6 +2147,7 @@ xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar *type) {
* @data: data needed for the library
* @type: the type name
* @value: the value to check
* @node: the node
*
* Check if the given type and value are validated by
* the default datatype library.
@ -2117,7 +2158,8 @@ static int
xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
const xmlChar *type ATTRIBUTE_UNUSED,
const xmlChar *value ATTRIBUTE_UNUSED,
void **result ATTRIBUTE_UNUSED) {
void **result ATTRIBUTE_UNUSED,
xmlNodePtr node ATTRIBUTE_UNUSED) {
if (value == NULL)
return(-1);
if (xmlStrEqual(type, BAD_CAST "string"))
@ -2707,6 +2749,11 @@ xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
"Error type '%s' is not exported by type library '%s'\n",
def->name, library);
ctxt->nbErrors++;
} else if ((xmlStrEqual(library, BAD_CAST
"http://www.w3.org/2001/XMLSchema-datatypes")) &&
((xmlStrEqual(def->name, BAD_CAST "IDREF")) ||
(xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
ctxt->idref = 1;
}
}
}
@ -6317,6 +6364,8 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
ret->defNr = ctxt->defNr;
ret->defTab = ctxt->defTab;
ctxt->defTab = NULL;
if (ctxt->idref == 1)
ret->idref = 1;
return (ret);
}
@ -6659,6 +6708,7 @@ xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *str) {
* @ctxt: a Relax-NG validation context
* @value: the string value
* @type: the datatype definition
* @node: the node
*
* Validate the given value against the dataype
*
@ -6666,7 +6716,7 @@ xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *str) {
*/
static int
xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value,
xmlRelaxNGDefinePtr define) {
xmlRelaxNGDefinePtr define, xmlNodePtr node) {
int ret, tmp;
xmlRelaxNGTypeLibraryPtr lib;
void *result = NULL;
@ -6679,9 +6729,9 @@ xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value,
if (lib->check != NULL) {
if ((define->attrs != NULL) &&
(define->attrs->type == XML_RELAXNG_PARAM)) {
ret = lib->check(lib->data, define->name, value, &result);
ret = lib->check(lib->data, define->name, value, &result, node);
} else {
ret = lib->check(lib->data, define->name, value, NULL);
ret = lib->check(lib->data, define->name, value, NULL, node);
}
} else
ret = -1;
@ -6692,8 +6742,10 @@ xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value,
return(-1);
} else if (ret == 1) {
ret = 0;
} else if (ret == 2) {
VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value);
} else {
VALID_ERR3(XML_RELAXNG_ERR_TYPEVAL, define->name, value);
VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value);
ret = -1;
}
cur = define->attrs;
@ -6845,7 +6897,8 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
break;
}
case XML_RELAXNG_DATATYPE: {
ret = xmlRelaxNGValidateDatatype(ctxt, value, define);
ret = xmlRelaxNGValidateDatatype(ctxt, value, define,
ctxt->state->seq);
if (ret == 0)
xmlRelaxNGNextValue(ctxt);
@ -7112,6 +7165,7 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
int ret = 0, i;
xmlChar *value, *oldvalue;
xmlAttrPtr prop = NULL, tmp;
xmlNodePtr oldseq;
if (ctxt->state->nbAttrLeft <= 0)
return(-1);
@ -7131,6 +7185,8 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
if (prop != NULL) {
value = xmlNodeListGetString(prop->doc, prop->children, 1);
oldvalue = ctxt->state->value;
oldseq = ctxt->state->seq;
ctxt->state->seq = (xmlNodePtr) prop;
ctxt->state->value = value;
ctxt->state->endvalue = NULL;
ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
@ -7139,6 +7195,7 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
if (value != NULL)
xmlFree(value);
ctxt->state->value = oldvalue;
ctxt->state->seq = oldseq;
if (ret == 0) {
/*
* flag the attribute as processed
@ -7165,6 +7222,8 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
if (prop != NULL) {
value = xmlNodeListGetString(prop->doc, prop->children, 1);
oldvalue = ctxt->state->value;
oldseq = ctxt->state->seq;
ctxt->state->seq = (xmlNodePtr) prop;
ctxt->state->value = value;
ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
if (ctxt->state->value != NULL)
@ -7172,6 +7231,7 @@ xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
if (value != NULL)
xmlFree(value);
ctxt->state->value = oldvalue;
ctxt->state->seq = oldseq;
if (ret == 0) {
/*
* flag the attribute as processed
@ -8050,7 +8110,8 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
break;
}
}
ret = xmlRelaxNGValidateDatatype(ctxt, content, define);
ret = xmlRelaxNGValidateDatatype(ctxt, content, define,
ctxt->state->seq);
if (ret == -1) {
VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
} else if (ret == 0) {
@ -8374,6 +8435,18 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) {
xmlRelaxNGFreeValidState(state);
if (ret != 0)
xmlRelaxNGDumpValidError(ctxt);
if (ctxt->idref == 1) {
xmlValidCtxt vctxt;
memset(&vctxt, 0, sizeof(xmlValidCtxt));
vctxt.valid = 1;
vctxt.error = ctxt->error;
vctxt.warning = ctxt->warning;
vctxt.userData = ctxt->userData;
if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
ret = -1;
}
return(ret);
}
@ -8409,6 +8482,7 @@ xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema) {
ret->errMax = 0;
ret->err = NULL;
ret->errTab = NULL;
ret->idref = schema->idref;
return (ret);
}

View File

@ -1331,4 +1331,62 @@
</valid>
</testCase>
</testSuite>
<testSuite>
<documentation>Test of ID/IDREF</documentation>
<testCase>
<correct>
<element name="top" xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<zeroOrMore>
<choice>
<element name="ref">
<attribute name="id">
<data type="ID"/>
</attribute>
<text/>
</element>
<element name="xref">
<attribute name="link">
<data type="IDREF"/>
</attribute>
<text/>
</element>
</choice>
</zeroOrMore>
</element>
</correct>
<valid>
<top>
</top>
</valid>
<invalid>
<top>
<xref link="id1"/>
</top>
</invalid>
<valid>
<top>
<ref id="id1"/>
</top>
</valid>
<valid>
<top>
<xref link="id1"/>
<ref id="id1"/>
</top>
</valid>
<valid>
<top>
<ref id="id1"/>
<xref link="id1"/>
</top>
</valid>
<invalid>
<top>
<ref id="id1"/>
<ref id="id1"/>
</top>
</invalid>
</testCase>
</testSuite>
</testSuite>

View File

@ -5988,6 +5988,7 @@ xmlValidateCheckRefCallback(xmlListPtr ref_list, xmlValidCtxtPtr ctxt,
*
* basically it does the following checks described by the XML Rec
*
* Check all the IDREF/IDREFS attributes definition for validity
*
* returns 1 if valid or 0 otherwise
*/

View File

@ -1057,10 +1057,11 @@ error:
/**
* xmlSchemaValidatePredefinedType:
* xmlSchemaValPredefTypeNode:
* @type: the predefined type
* @value: the value to check
* @val: the return computed value
* @node: the node containing the value
*
* Check that a value conforms to the lexical space of the predefined type.
* if true a value is computed and returned in @val.
@ -1069,8 +1070,8 @@ error:
* and -1 in case of internal or API error.
*/
int
xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
xmlSchemaValPtr *val) {
xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
xmlSchemaValPtr *val, xmlNodePtr node) {
xmlSchemaValPtr v;
int ret;
@ -1411,6 +1412,37 @@ xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
}
}
return(0);
} else if (type == xmlSchemaTypeIdrefDef) {
ret = xmlValidateNCName(value, 1);
if ((ret == 0) && (val != NULL)) {
TODO;
}
if ((ret == 0) && (node != NULL) &&
(node->type == XML_ATTRIBUTE_NODE)) {
xmlAttrPtr attr = (xmlAttrPtr) node;
xmlAddRef(NULL, node->doc, value, attr);
attr->atype = XML_ATTRIBUTE_IDREF;
}
return(ret);
} else if (type == xmlSchemaTypeIdDef) {
ret = xmlValidateNCName(value, 1);
if ((ret == 0) && (val != NULL)) {
TODO;
}
if ((ret == 0) && (node != NULL) &&
(node->type == XML_ATTRIBUTE_NODE)) {
xmlAttrPtr attr = (xmlAttrPtr) node;
xmlIDPtr res;
res = xmlAddID(NULL, node->doc, value, attr);
if (res == NULL) {
ret = 2;
} else {
attr->atype = XML_ATTRIBUTE_ID;
}
}
return(ret);
} else {
TODO
return(0);
@ -1418,6 +1450,24 @@ xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
return(-1);
}
/**
* xmlSchemaValidatePredefinedType:
* @type: the predefined type
* @value: the value to check
* @val: the return computed value
*
* Check that a value conforms to the lexical space of the predefined type.
* if true a value is computed and returned in @val.
*
* Returns 0 if this validates, a positive error code number otherwise
* and -1 in case of internal or API error.
*/
int
xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
xmlSchemaValPtr *val) {
return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
}
/**
* xmlSchemaCompareDecimals:
* @x: a first decimal value