diff --git a/ChangeLog b/ChangeLog index 8fa14cf5..bff2a754 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Apr 9 13:21:48 CEST 2003 Daniel Veillard + + * xmlschemas.c xmlschemastypes.c include/libxml/xmlschemas.h: + update from Charles Bozeman for date and duration types + * test/schemas/date_0.* test/schemas/dur_0.* + result/schemas/date_0.* result/schemas/dur_0.*: updated too + Mon Apr 7 12:19:26 CEST 2003 Daniel Veillard * tree.c valid.c xpath.c include/libxml/tree.h include/libxml/valid.h: diff --git a/include/libxml/xmlschemas.h b/include/libxml/xmlschemas.h index 081d8a25..1fc525aa 100644 --- a/include/libxml/xmlschemas.h +++ b/include/libxml/xmlschemas.h @@ -45,6 +45,7 @@ typedef enum { XML_SCHEMAS_ERR_ATTRUNKNOWN, XML_SCHEMAS_ERR_ATTRINVALID, XML_SCHEMAS_ERR_VALUE, + XML_SCHEMAS_ERR_FACET, XML_SCHEMAS_ERR_, XML_SCHEMAS_ERR_XXX } xmlSchemaValidError; diff --git a/result/schemas/date_0_0.err b/result/schemas/date_0_0.err index 6a9efe5f..7d8d2255 100644 --- a/result/schemas/date_0_0.err +++ b/result/schemas/date_0_0.err @@ -17,13 +17,13 @@ Type of restriction 13 : ./test/schemas/date_0.xsd:47 :empty Type of restriction 19 : ./test/schemas/date_0.xsd:72 :empty Type of simpletype8 : ./test/schemas/date_0.xsd:30 :simple Type of simpletype18 : ./test/schemas/date_0.xsd:71 :simple -Type of holidays : ./test/schemas/date_0.xsd:98 :simple +Type of holidays : ./test/schemas/date_0.xsd:99 :simple Type of restriction 11 : ./test/schemas/date_0.xsd:39 :empty Type of simpletype16 : ./test/schemas/date_0.xsd:63 :simple Type of sequence 2 : ./test/schemas/date_0.xsd:10 :elements Type of choice 3 : ./test/schemas/date_0.xsd:11 :elements Type of restriction 17 : ./test/schemas/date_0.xsd:64 :empty -Type of restriction 24 : ./test/schemas/date_0.xsd:102 :empty +Type of restriction 24 : ./test/schemas/date_0.xsd:103 :empty Building content model for date xmlSchemaValidateCallback: time, time, time xmlSchemaValidateCallback: time1, time1, time1 @@ -40,10 +40,11 @@ xmlSchemaValidateCallback: dt2, dt2, dt2 xmlSchemaValidateCallback: hol, hol, hol xmlSchemaValidateCallback: hol, hol, hol xmlSchemaValidateCallback: hol, hol, hol -xmlSchemaValidateCallback: hol, hol, hol xmlSchemaValidateCallback: year1, year1, year1 xmlSchemaValidateCallback: yearmon1, yearmon1, yearmon1 xmlSchemaValidateCallback: mon1, mon1, mon1 xmlSchemaValidateCallback: day1, day1, day1 +xmlSchemaValidateCallback: monthday1, monthday1, monthday1 +xmlSchemaValidateCallback: monthday1, monthday1, monthday1 xmlSchemaValidateCallback: dt2, dt2, dt2 Element date content check succeeded diff --git a/result/schemas/dur_0_0.err b/result/schemas/dur_0_0.err index 1aa3a82b..d2d3138e 100644 --- a/result/schemas/dur_0_0.err +++ b/result/schemas/dur_0_0.err @@ -1,17 +1,3 @@ -compilation error: file ./test/schemas/dur_0.xsd line 67 element minOccurs -Restriction restriction 16 has unexpected content -compilation error -Schemas: element year1 have both type and subtype -compilation error -Schemas: element second2 have both type and subtype -compilation error -Schemas: element month1 have both type and subtype -compilation error -Schemas: element year2 have both type and subtype -compilation error -Schemas: element second1 have both type and subtype -compilation error -Schemas: element month2 have both type and subtype Type of restriction 7 : ./test/schemas/dur_0.xsd:22 :empty Type of restriction 9 : ./test/schemas/dur_0.xsd:30 :empty Type of simpletype14 : ./test/schemas/dur_0.xsd:54 :simple diff --git a/test/schemas/date_0.xml b/test/schemas/date_0.xml index 3099d5e9..fbef1e5e 100644 --- a/test/schemas/date_0.xml +++ b/test/schemas/date_0.xml @@ -2,23 +2,24 @@ 01:02:59 - 12:59:59 - 11:59:59.01 + 12:59:59.0001 + 12:00:00 + 1996-05-20 2002-05-18 - 2002-05-19 1996-05-19Z - 1996-05 + 2002-05-19Z 2002-05-18Z 2000-05-18Z - 2000-05-18 + 2000-05-18T00:00:00 2002-05-19T21:30:00.99 --01-01 --07-04 --12-25 - --05-19 2002 2002-05 - --05-- + --05Z ---31 + --02-28Z + --12-31-06:00 2003-04-30T18:00:00-06:00 diff --git a/test/schemas/date_0.xsd b/test/schemas/date_0.xsd index 87842122..7247394a 100644 --- a/test/schemas/date_0.xsd +++ b/test/schemas/date_0.xsd @@ -78,19 +78,20 @@ - - + + - - + + + diff --git a/test/schemas/dur_0.xml b/test/schemas/dur_0.xml index 9e3d2fad..be849437 100644 --- a/test/schemas/dur_0.xml +++ b/test/schemas/dur_0.xml @@ -6,8 +6,8 @@ P0Y27D P27DT23H59M59S P0Y - P366DT23H59M59S - P12M + P367DT23H59M59S + P13M P12M - PT86400S + PT86399S diff --git a/test/schemas/dur_0.xsd b/test/schemas/dur_0.xsd index 5d33fba0..374c038a 100644 --- a/test/schemas/dur_0.xsd +++ b/test/schemas/dur_0.xsd @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -33,7 +33,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -50,7 +50,7 @@ - + @@ -64,7 +64,6 @@ - diff --git a/xmlschemas.c b/xmlschemas.c index 6c9e2f4d..55cdef54 100644 --- a/xmlschemas.c +++ b/xmlschemas.c @@ -4167,6 +4167,101 @@ xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt, ctxt->userData = ctx; } +/** + * xmlSchemaFacetTypeToString: + * @type: the facet type + * + * Convert the xmlSchemaTypeType to a char string. + * + * Returns the char string representation of the facet type if the + * type is a facet and an "Internal Error" string otherwise. + */ +static const char * +xmlSchemaFacetTypeToString(xmlSchemaTypeType type) +{ + switch (type) { + case XML_SCHEMA_FACET_PATTERN: + return ("pattern"); + case XML_SCHEMA_FACET_MAXEXCLUSIVE: + return ("maxExclusive"); + case XML_SCHEMA_FACET_MAXINCLUSIVE: + return ("maxInclusive"); + case XML_SCHEMA_FACET_MINEXCLUSIVE: + return ("minExclusive"); + case XML_SCHEMA_FACET_MININCLUSIVE: + return ("minInclusive"); + case XML_SCHEMA_FACET_WHITESPACE: + return ("whiteSpace"); + case XML_SCHEMA_FACET_ENUMERATION: + return ("enumeration"); + case XML_SCHEMA_FACET_LENGTH: + return ("length"); + case XML_SCHEMA_FACET_MAXLENGTH: + return ("maxLength"); + case XML_SCHEMA_FACET_MINLENGTH: + return ("minLength"); + case XML_SCHEMA_FACET_TOTALDIGITS: + return ("totalDigits"); + case XML_SCHEMA_FACET_FRACTIONDIGITS: + return ("fractionDigits"); + default: + break; + } + return ("Internal Error"); +} + +/** + * xmlSchemaValidateFacets: + * @ctxt: a schema validation context + * @base: the base type + * @facets: the list of facets to check + * @value: the lexical repr of the value to validate + * @val: the precomputed value + * + * Check a value against all facet conditions + * + * Returns 0 if the element is schemas valid, a positive error code + * number otherwise and -1 in case of internal or API error. + */ +static int +xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, + xmlSchemaTypePtr base, + xmlSchemaFacetPtr facets, + xmlChar *value) { + int ret = 0; + int tmp = 0; + xmlSchemaTypeType type; + xmlSchemaFacetPtr facet = facets; + + while (facet != NULL) { + type = facet->type; + if (type == XML_SCHEMA_FACET_ENUMERATION) { + tmp = 1; + + while (facet != NULL) { + tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value); + if (tmp == 0) { + return 0; + } + facet = facet->next; + } + } else + tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value); + + if (tmp != 0) { + ret = tmp; + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to validate type with facet %s\n", + xmlSchemaFacetTypeToString(type)); + ctxt->err = XML_SCHEMAS_ERR_FACET; + } + if (facet != NULL) + facet = facet->next; + } + return (ret); +} + /************************************************************************ * * * Simple type validation * @@ -4203,10 +4298,15 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, ctxt->value = NULL; } ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value)); + if (ret != 0) { + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Failed to validate basic type %s\n", type->name); + ctxt->err = XML_SCHEMAS_ERR_VALUE; + } } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) { xmlSchemaTypePtr base; xmlSchemaFacetPtr facet; - int tmp; base = type->baseType; if (base != NULL) { @@ -4220,29 +4320,7 @@ xmlSchemaValidateSimpleValue(xmlSchemaValidCtxtPtr ctxt, if (ctxt->schema != NULL) { if (ret == 0) { facet = type->facets; - if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) && - (facet != NULL) && - (facet->type == XML_SCHEMA_FACET_ENUMERATION)) { - while (facet != NULL) { - ret = 1; - - tmp = xmlSchemaValidateFacet(base, facet, value, - ctxt->value); - if (tmp == 0) { - ret = 0; - break; - } - facet = facet->next; - } - } else { - while (facet != NULL) { - tmp = xmlSchemaValidateFacet(base, facet, value, - ctxt->value); - if (tmp != 0) - ret = tmp; - facet = facet->next; - } - } + ret = xmlSchemaValidateFacets(ctxt, base, facet, value); } } } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) { @@ -4391,7 +4469,7 @@ xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr child; xmlSchemaTypePtr type, base; xmlChar *value; - int ret = 0, tmp; + int ret = 0; child = ctxt->node; type = ctxt->type; @@ -4413,13 +4491,7 @@ xmlSchemaValidateSimpleContent(xmlSchemaValidCtxtPtr ctxt, } if (ret == 0) { facet = type->facets; - while (facet != NULL) { - tmp = xmlSchemaValidateFacet(base, facet, value, - ctxt->value); - if (tmp != 0) - ret = tmp; - facet = facet->next; - } + ret = xmlSchemaValidateFacets(ctxt, base, facet, value); } break; } @@ -4853,9 +4925,10 @@ xmlSchemaValidateBasicType(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node) { if (value != NULL) xmlFree(value); if (ret != 0) { - ctxt->error(ctxt->userData, - "Element %s: failed to validate basic type %s\n", - node->name, type->name); + if (ctxt->error != NULL) + ctxt->error(ctxt->userData, + "Element %s: failed to validate basic type %s\n", + node->name, type->name); ctxt->err = XML_SCHEMAS_ERR_VALUE; } return(ret); diff --git a/xmlschemastypes.c b/xmlschemastypes.c index 4a659a39..29b069b0 100644 --- a/xmlschemastypes.c +++ b/xmlschemastypes.c @@ -903,19 +903,42 @@ xmlSchemaValidateDates (xmlSchemaValType type, if (ret != 0) goto error; - if (*cur != '-') { - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH); - goto error; - } - if (type == XML_SCHEMAS_GMONTH) - goto error; - /* it should be an xs:gMonthDay */ - cur++; - ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); - if (ret != 0) - goto error; + /* + * a '-' char could indicate this type is xs:gMonthDay or + * a negative time zone offset. Check for xs:gMonthDay first. + * Also the first three char's of a negative tzo (-MM:SS) can + * appear to be a valid day; so even if the day portion + * of the xs:gMonthDay verifies, we must insure it was not + * a tzo. + */ + if (*cur == '-') { + const xmlChar *rewnd = cur; + cur++; - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY); + ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); + if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) { + + /* + * we can use the VALID_MDAY macro to validate the month + * and day because the leap year test will flag year zero + * as a leap year (even though zero is an invalid year). + */ + if (VALID_MDAY((&(dt->value.date)))) { + + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY); + + goto error; + } + } + + /* + * not xs:gMonthDay so rewind and check if just xs:gMonth + * with an optional time zone. + */ + cur = rewnd; + } + + RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH); goto error; } @@ -981,9 +1004,37 @@ xmlSchemaValidateDates (xmlSchemaValType type, dt->type = XML_SCHEMAS_DATETIME; done: -#if 0 - if ((type != XML_SCHEMAS_UNKNOWN) && (type != XML_SCHEMAS_DATETIME)) - goto error; +#if 1 + if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) + goto error; +#else + /* + * insure the parsed type is equal to or less significant (right + * truncated) than the desired type. + */ + if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) { + + /* time only matches time */ + if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME)) + goto error; + + if ((type == XML_SCHEMAS_DATETIME) && + ((dt->type != XML_SCHEMAS_DATE) || + (dt->type != XML_SCHEMAS_GYEARMONTH) || + (dt->type != XML_SCHEMAS_GYEAR))) + goto error; + + if ((type == XML_SCHEMAS_DATE) && + ((dt->type != XML_SCHEMAS_GYEAR) || + (dt->type != XML_SCHEMAS_GYEARMONTH))) + goto error; + + if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR)) + goto error; + + if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH)) + goto error; + } #endif if (val != NULL) @@ -1018,6 +1069,10 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED, xmlSchemaValPtr dur; int isneg = 0; unsigned int seq = 0; + double num; + int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */ + const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'}; + const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0}; if (duration == NULL) return -1; @@ -1039,10 +1094,6 @@ xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED, return -1; while (*cur != 0) { - double num; - int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */ - const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'}; - const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0}; /* input string should be empty or invalid date/time item */ if (seq >= sizeof(desig)) @@ -1328,7 +1379,7 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value, xmlSchemaValPtr *val, xmlNodePtr node, int flags) { xmlSchemaValPtr v; xmlChar *norm = NULL; - int ret; + int ret = 0; if (xmlSchemaTypesInitialized == 0) return(-1);