[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[xml] WXS patches



I started to make what I thought was a simple fix and ended up finding
more problems with WXS date types.

xmlschemas.c
Changed to set ctxt->err and print message when type validation fails on
restricted types. Sets ctxt->err and prints message when facet
validation fails.

xmlschemastypes.c
gMonthDay values with a time zone offset were failing validation (i.e.
--02-28-06:00) so I fixed that. Also added verification of the month and
day values for gMonthDay (i.e. --02-30 should not validate).
refactored duration parsing to be a tad more efficient.
fixed a warning in xmlSchemaValAtomicType.

date_0.xsd, date_0.xml, dur_0.xsd, dur_0.xml
The above changes exposed errors in my date and duration regression
tests, so I fixed them.

I still need to update the EXSLT date code when I get time.

The context diff patches are against the code in CVS. Let me know if
there are any problems.


-- 
Charles Bozeman <cbozeman hiwaay net>
Index: xmlschemas.c
===================================================================
RCS file: /cvs/gnome/libxml2/xmlschemas.c,v
retrieving revision 1.26
diff -c -r1.26 xmlschemas.c
*** xmlschemas.c	27 Mar 2003 23:44:40 -0000	1.26
--- xmlschemas.c	4 Apr 2003 02:34:42 -0000
***************
*** 4167,4172 ****
--- 4167,4267 ----
      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,4212 ****
  	    ctxt->value = NULL;
  	}
  	ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
      } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
  	xmlSchemaTypePtr base;
  	xmlSchemaFacetPtr facet;
- 	int tmp;
  
  	base = type->baseType;
  	if (base != NULL) {
--- 4298,4312 ----
  	    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;
  
  	base = type->baseType;
  	if (base != NULL) {
***************
*** 4220,4248 ****
  	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;
! 		    }
! 		}
  	    }
  	}
      } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
--- 4320,4326 ----
  	if (ctxt->schema != NULL) {
  	    if (ret == 0) {
  		facet = type->facets;
!                 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
  	    }
  	}
      } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
***************
*** 4391,4397 ****
      xmlNodePtr child;
      xmlSchemaTypePtr type, base;
      xmlChar *value;
!     int ret = 0, tmp;
  
      child = ctxt->node;
      type = ctxt->type;
--- 4469,4475 ----
      xmlNodePtr child;
      xmlSchemaTypePtr type, base;
      xmlChar *value;
!     int ret = 0;
  
      child = ctxt->node;
      type = ctxt->type;
***************
*** 4413,4425 ****
  	    }
  	    if (ret == 0) {
  		facet = type->facets;
! 		while (facet != NULL) {
! 		    tmp = xmlSchemaValidateFacet(base, facet, value,
! 			                         ctxt->value);
! 		    if (tmp != 0)
! 			ret = tmp;
! 		    facet = facet->next;
! 		}
  	    }
  	    break;
  	}
--- 4491,4497 ----
  	    }
  	    if (ret == 0) {
  		facet = type->facets;
!                 ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
  	    }
  	    break;
  	}
***************
*** 4853,4861 ****
      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);
  	ctxt->err = XML_SCHEMAS_ERR_VALUE;
      }
      return(ret);
--- 4925,4934 ----
      if (value != NULL)
  	xmlFree(value);
      if (ret != 0) {
!         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);
Index: xmlschemastypes.c
===================================================================
RCS file: /cvs/gnome/libxml2/xmlschemastypes.c,v
retrieving revision 1.35
diff -c -r1.35 xmlschemastypes.c
*** xmlschemastypes.c	31 Mar 2003 11:22:25 -0000	1.35
--- xmlschemastypes.c	4 Apr 2003 02:34:19 -0000
***************
*** 903,921 ****
  	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;
  
! 	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
  
  	goto error;
      }
--- 903,944 ----
  	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 *rewind = cur;
!             cur++;
! 
!   	    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 = rewind;
!         }
  
! 	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
  
  	goto error;
      }
***************
*** 981,989 ****
      dt->type = XML_SCHEMAS_DATETIME;
  
  done:
! #if 0
!     if ((type != XML_SCHEMAS_UNKNOWN) && (type != XML_SCHEMAS_DATETIME))
! 	goto error;
  #endif
  
      if (val != NULL)
--- 1004,1040 ----
      dt->type = XML_SCHEMAS_DATETIME;
  
  done:
! #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,1023 ****
--- 1069,1078 ----
      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,1048 ****
  	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))
--- 1094,1099 ----
***************
*** 1328,1334 ****
  	               xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
      xmlSchemaValPtr v;
      xmlChar *norm = NULL;
!     int ret;
  
      if (xmlSchemaTypesInitialized == 0)
  	return(-1);
--- 1379,1385 ----
  	               xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
      xmlSchemaValPtr v;
      xmlChar *norm = NULL;
!     int ret = 0;
  
      if (xmlSchemaTypesInitialized == 0)
  	return(-1);
Index: test/schemas/date_0.xml
===================================================================
RCS file: /cvs/gnome/libxml2/test/schemas/date_0.xml,v
retrieving revision 1.1
diff -c -r1.1 date_0.xml
*** test/schemas/date_0.xml	22 May 2002 06:40:27 -0000	1.1
--- test/schemas/date_0.xml	4 Apr 2003 02:37:06 -0000
***************
*** 2,24 ****
  <date>
    <time>01:02:59</time>
    <time1>01:02:59</time1>
!   <time2>12:59:59</time2>
!   <time2>11:59:59.01</time2>
    <date1>2002-05-18</date1>
-   <date1>2002-05-19</date1>
    <date2>1996-05-19Z</date2>
!   <date2>1996-05</date2>
    <date1>2002-05-18Z</date1>
    <date1>2000-05-18Z</date1>
!   <dt1>2000-05-18</dt1>
    <dt2>2002-05-19T21:30:00.99</dt2>
    <hol>--01-01</hol>
    <hol>--07-04</hol>
    <hol>--12-25</hol>
-   <hol>--05-19</hol>
    <year1>2002</year1>
    <yearmon1>2002-05</yearmon1>
!   <mon1>--05--</mon1>
    <day1>---31</day1>
    <dt2>2003-04-30T18:00:00-06:00</dt2>
  </date>
--- 2,25 ----
  <date>
    <time>01:02:59</time>
    <time1>01:02:59</time1>
!   <time2>12:59:59.0001</time2>
!   <time2>12:00:00</time2>
!   <date1>1996-05-20</date1>
    <date1>2002-05-18</date1>
    <date2>1996-05-19Z</date2>
!   <date2>2002-05-19Z</date2>
    <date1>2002-05-18Z</date1>
    <date1>2000-05-18Z</date1>
!   <dt1>2000-05-18T00:00:00</dt1>
    <dt2>2002-05-19T21:30:00.99</dt2>
    <hol>--01-01</hol>
    <hol>--07-04</hol>
    <hol>--12-25</hol>
    <year1>2002</year1>
    <yearmon1>2002-05</yearmon1>
!   <mon1>--05Z</mon1>
    <day1>---31</day1>
+   <monthday1>--02-28Z</monthday1>
+   <monthday1>--12-31-06:00</monthday1>
    <dt2>2003-04-30T18:00:00-06:00</dt2>
  </date>
Index: test/schemas/date_0.xsd
===================================================================
RCS file: /cvs/gnome/libxml2/test/schemas/date_0.xsd,v
retrieving revision 1.2
diff -c -r1.2 date_0.xsd
*** test/schemas/date_0.xsd	31 Mar 2003 16:09:37 -0000	1.2
--- test/schemas/date_0.xsd	4 Apr 2003 02:36:49 -0000
***************
*** 78,96 ****
            <xsd:element name="mon1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:gMonth">
!                 <xsd:maxInclusive value="--01Z"/>
!                 <xsd:minInclusive value="--05Z"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="day1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:gDay">
!                 <xsd:maxInclusive value="---28"/>
!                 <xsd:minInclusive value="---31"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
          </xsd:choice>
        </xsd:sequence>
      </xsd:complexType>
--- 78,97 ----
            <xsd:element name="mon1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:gMonth">
!                 <xsd:minInclusive value="--01Z"/>
!                 <xsd:maxInclusive value="--05Z"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="day1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:gDay">
!                 <xsd:minInclusive value="---28"/>
!                 <xsd:maxInclusive value="---31"/>
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
+           <xsd:element name="monthday1" type="xsd:gMonthDay"/>
          </xsd:choice>
        </xsd:sequence>
      </xsd:complexType>
Index: test/schemas/dur_0.xml
===================================================================
RCS file: /cvs/gnome/libxml2/test/schemas/dur_0.xml,v
retrieving revision 1.1
diff -c -r1.1 dur_0.xml
*** test/schemas/dur_0.xml	3 May 2002 07:29:38 -0000	1.1
--- test/schemas/dur_0.xml	4 Apr 2003 02:36:33 -0000
***************
*** 6,13 ****
    <month1>P0Y27D</month1>
    <month1>P27DT23H59M59S</month1>
    <month2>P0Y</month2>
!   <year1>P366DT23H59M59S</year1>
!   <year1>P12M</year1>
    <year2>P12M</year2>
!   <month3>PT86400S</month3>
  </duration>
--- 6,13 ----
    <month1>P0Y27D</month1>
    <month1>P27DT23H59M59S</month1>
    <month2>P0Y</month2>
!   <year1>P367DT23H59M59S</year1>
!   <year1>P13M</year1>
    <year2>P12M</year2>
!   <month3>PT86399S</month3>
  </duration>
Index: test/schemas/dur_0.xsd
===================================================================
RCS file: /cvs/gnome/libxml2/test/schemas/dur_0.xsd,v
retrieving revision 1.1
diff -c -r1.1 dur_0.xsd
*** test/schemas/dur_0.xsd	3 May 2002 07:29:38 -0000	1.1
--- test/schemas/dur_0.xsd	4 Apr 2003 02:36:48 -0000
***************
*** 9,15 ****
      <xsd:complexType>
        <xsd:sequence>
          <xsd:choice minOccurs="1" maxOccurs="unbounded">
!           <xsd:element name="second1" type="xsd:duration">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxExclusive value="PT1S"/>
--- 9,15 ----
      <xsd:complexType>
        <xsd:sequence>
          <xsd:choice minOccurs="1" maxOccurs="unbounded">
!           <xsd:element name="second1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxExclusive value="PT1S"/>
***************
*** 17,23 ****
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="second2" type="xsd:duration">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxInclusive value="PT1S"/>
--- 17,23 ----
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="second2">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxInclusive value="PT1S"/>
***************
*** 25,31 ****
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="month1" type="xsd:duration">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxExclusive value="P1M"/>
--- 25,31 ----
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="month1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxExclusive value="P1M"/>
***************
*** 33,39 ****
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="month2" type="xsd:duration">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxInclusive value="P1M"/>
--- 33,39 ----
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="month2">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxInclusive value="P1M"/>
***************
*** 42,48 ****
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="month3" type="MSD"/>
!           <xsd:element name="year1" type="xsd:duration">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxExclusive value="P2Y"/>
--- 42,48 ----
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="month3" type="MSD"/>
!           <xsd:element name="year1">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxExclusive value="P2Y"/>
***************
*** 50,56 ****
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="year2" type="xsd:duration">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxInclusive value="P2Y"/>
--- 50,56 ----
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
!           <xsd:element name="year2">
              <xsd:simpleType>
                <xsd:restriction base="xsd:duration">
                  <xsd:maxInclusive value="P2Y"/>
***************
*** 64,70 ****
    </xsd:element>
    <xsd:simpleType name="MSD">
      <xsd:restriction base="xsd:duration">
-       <xsd:minOccurs value="0"/>
        <xsd:maxExclusive value="PT24H"/>
        <xsd:minExclusive value="-PT24H"/>
      </xsd:restriction>
--- 64,69 ----


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]