Commit 6e224f12 authored by Kasimier T. Buchcik's avatar Kasimier T. Buchcik
Browse files

Fixed comparison for default/fixed attribute values, if the type was

* xmlschemas.c: Fixed comparison for default/fixed attribute
  values, if the type was 'xsd:string'. Changed the comparison
  for IDCs to use the whitespace aware comparison function.
* xmlschemastypes.c include/libxml/xmlschemastypes.h:
  Added xmlSchemaGetCanonValue, xmlSchemaNewStringValue and
  xmlSchemaCompareValuesWhtsp to the API. Added functions
  to compare strings with whitespace combinations of "preserve",
  "replace" and "collapse".
parent bd2a7d16
Thu Feb 17 12:03:46 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
* xmlschemas.c: Fixed comparison for default/fixed attribute
values, if the type was 'xsd:string'. Changed the comparison
for IDCs to use the whitespace aware comparison function.
* xmlschemastypes.c include/libxml/xmlschemastypes.h:
Added xmlSchemaGetCanonValue, xmlSchemaNewStringValue and
xmlSchemaCompareValuesWhtsp to the API. Added functions
to compare strings with whitespace combinations of "preserve",
"replace" and "collapse".
Wed Feb 16 13:24:35 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
 
* xmlschemas.c: Further work on IDCs, especially evaluation for
......
......@@ -23,6 +23,13 @@
extern "C" {
#endif
typedef enum {
XML_SCHEMA_WHITESPACE_UNKNOWN = 0,
XML_SCHEMA_WHITESPACE_PRESERVE = 1,
XML_SCHEMA_WHITESPACE_REPLACE = 2,
XML_SCHEMA_WHITESPACE_COLLAPSE = 3
} xmlSchemaWhitespaceValueType;
XMLPUBFUN void XMLCALL
xmlSchemaInitTypes (void);
XMLPUBFUN void XMLCALL
......@@ -87,6 +94,17 @@ XMLPUBFUN int XMLCALL
const xmlChar *value,
xmlSchemaValPtr *val,
xmlNodePtr node);
XMLPUBFUN int XMLCALL
xmlSchemaGetCanonValue (xmlSchemaValPtr val,
const xmlChar **retValue);
XMLPUBFUN xmlSchemaValPtr XMLCALL
xmlSchemaNewStringValue (xmlSchemaValType type,
const xmlChar *value);
XMLPUBFUN int XMLCALL
xmlSchemaCompareValuesWhtsp (xmlSchemaValPtr x,
xmlSchemaWhitespaceValueType xws,
xmlSchemaValPtr y,
xmlSchemaWhitespaceValueType yws);
#ifdef __cplusplus
}
......
......@@ -7,7 +7,7 @@
* Daniel Veillard <veillard@redhat.com>
*/
 
/*
/*
* TODO:
* - when types are redefined in includes, check that all
* types in the redef list are equal
......@@ -54,7 +54,7 @@
 
#define ELEM_INFO_ENABLED 1
 
/* #define IDC_ENABLED 1 */
/* #define IDC_ENABLED 1 */
 
/* #define IDC_VALUE_SUPPORT 1 */
 
......@@ -117,9 +117,11 @@ static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
((item->type == XML_SCHEMA_TYPE_BASIC) && \
(item->builtInType != XML_SCHEMAS_ANYTYPE)))
 
/*
#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
*/
 
#define XML_SCHEMAS_PARSE_ERROR 1
 
......@@ -384,9 +386,6 @@ struct _xmlSchemaIDCMatcher {
xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
elements */
int sizeKeySeqs;
xmlSchemaPSVIIDCKeyPtr **refKeySeqs;
int nbRefKeySeqs;
int sizeRefKeySeqs;
int targetDepth;
};
 
......@@ -10268,7 +10267,7 @@ xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
}
 
/**
* xmlSchemaIsDerivedFromBuiltInType:
* xmlSchemaGetPrimitiveType:
* @type: the simpleType definition
*
* Returns the primitive type of the given type or
......@@ -10286,6 +10285,25 @@ xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
return (NULL);
}
 
/**
* xmlSchemaGetBuiltInTypeAncestor:
* @type: the simpleType definition
*
* Returns the primitive type of the given type or
* NULL in case of error.
*/
static xmlSchemaTypePtr
xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
{
while (type != NULL) {
if (type->type == XML_SCHEMA_TYPE_BASIC)
return (type);
type = type->baseType;
}
return (NULL);
}
 
/**
* xmlSchemaBuildAttributeUsesOwned:
......@@ -14763,8 +14781,6 @@ xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
return ("Internal Error");
}
 
static int
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
{
......@@ -14776,24 +14792,24 @@ xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
*/
if (type->type == XML_SCHEMA_TYPE_BASIC) {
if (type->builtInType == XML_SCHEMAS_STRING)
return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
return(XML_SCHEMAS_FACET_PRESERVE);
else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
return(XML_SCHEMAS_VAL_WTSP_REPLACE);
return(XML_SCHEMAS_FACET_REPLACE);
else {
/*
* For all atomic datatypes other than string (and types derived
* by restriction from it) the value of whiteSpace is fixed to
* collapse
*/
return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
return(XML_SCHEMAS_FACET_COLLAPSE);
}
} else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
/*
* For list types the facet "whiteSpace" is fixed to "collapse".
*/
return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
return (XML_SCHEMAS_FACET_COLLAPSE);
} else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
return (-1);
return (XML_SCHEMAS_FACET_UNKNOWN);
} else if (type->facetSet != NULL) {
xmlSchemaTypePtr anyST;
xmlSchemaFacetLinkPtr lin;
......@@ -14815,14 +14831,7 @@ xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
lin = type->facetSet;
do {
if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
if (lin->facet->whitespace ==
XML_SCHEMAS_FACET_COLLAPSE) {
return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
} else if (lin->facet->whitespace ==
XML_SCHEMAS_FACET_REPLACE) {
return(XML_SCHEMAS_VAL_WTSP_REPLACE);
} else
return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
return(lin->facet->whitespace);
break;
}
lin = lin->next;
......@@ -14831,7 +14840,7 @@ xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
}
anc = anc->baseType;
} while (anc != anyST);
return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
return (XML_SCHEMAS_FACET_COLLAPSE);
}
return (-1);
}
......@@ -15667,11 +15676,11 @@ xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
* Normalize the value.
*/
if (normalize &&
(ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
(ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
if ((norm != -1) && (norm > ctxt->valueWS)) {
if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
if (norm == XML_SCHEMAS_FACET_COLLAPSE)
normValue = xmlSchemaCollapseString(value);
else
normValue = xmlSchemaWhiteSpaceReplace(value);
......@@ -15992,7 +16001,7 @@ xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
}
mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
if (mws > ctxt->valueWS) {
if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
if (mws == XML_SCHEMAS_FACET_COLLAPSE)
normValue = xmlSchemaCollapseString(value);
else
normValue = xmlSchemaWhiteSpaceReplace(value);
......@@ -16636,7 +16645,14 @@ compareValue:
{
#ifdef IDC_VALUE_SUPPORT
int ret;
ret = xmlSchemaCompareValues(a, b);
int aws, bws;
aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
ret = xmlSchemaCompareValuesWhtsp(
a, (xmlSchemaWhitespaceValueType) aws,
b, (xmlSchemaWhitespaceValueType) bws);
if (ret == 0)
return(1);
else if (ret == -2) {
......@@ -16962,11 +16978,19 @@ xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
* Failed to provide the normalized value; maby
* the value was invalid.
*/
xmlSchemaVErr(vctxt, NULL,
xmlSchemaVCustomErr(vctxt,
XML_SCHEMAV_CVC_IDC,
vctxt->nodeInfo->node,
(xmlSchemaTypePtr) sto->matcher->aidc->def,
"Warning: No precomputed value available, the value "
"was either invalid or something strange happend", NULL);
/*
xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
XML_SCHEMAV_INTERNAL,
"Internal error: xmlSchemaXPathProcessHistory, "
"computed value not available.\n",
NULL, NULL);
*/
sto->nbHistory--;
goto deregister_check;
} else {
......@@ -18308,7 +18332,7 @@ xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
XML_SCHEMAV_INTERNAL,
elem, actualType,
"Internal error: xmlSchemaValidateElementByDeclaration, "
"validating a default value", NULL);
"calling validation by type", NULL);
return (-1);
}
/*
......@@ -19083,7 +19107,6 @@ xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
return (ret);
}
 
static int
xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
xmlSchemaAttrStatePtr state)
......@@ -19126,6 +19149,10 @@ xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
if (xmlSchemaGetEffectiveValueConstraint(
(xmlSchemaAttributePtr) ctxt->attrInfo->decl,
&fixed, &defValue, &defVal) && (fixed == 1)) {
int ws = xmlSchemaGetWhiteSpaceFacetValue(
ctxt->attrInfo->typeDef);
/*
* cvc-au : Attribute Locally Valid (Use)
* For an attribute information item to bevalid
......@@ -19142,12 +19169,45 @@ xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
* TODO: Use the *normalized* value and the *canonical* fixed
* value.
*/
if (((ctxt->value != NULL) &&
(xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
((ctxt->value == NULL) &&
(! xmlStrEqual(defValue, BAD_CAST value)))) {
if (ctxt->value != NULL) {
if (defVal == NULL) {
xmlSchemaTypePtr prim;
/*
* Oops, the value was not computed.
*/
prim = xmlSchemaGetPrimitiveType(ctxt->attrInfo->typeDef);
if (prim->builtInType == XML_SCHEMAS_STRING) {
xmlSchemaTypePtr builtIn;
builtIn = xmlSchemaGetBuiltInTypeAncestor(
ctxt->attrInfo->typeDef);
defVal = xmlSchemaNewStringValue(
builtIn->builtInType, value);
((xmlSchemaAttributePtr) ctxt->attrInfo->decl)->defVal =
defVal;
value = NULL;
} else {
xmlSchemaVErr(ctxt, ctxt->attrInfo->node,
XML_SCHEMAV_INTERNAL,
"Internal error: xmlSchemaCheckAttrLocallyValid, "
"could not aquire a precomputed vale",
NULL, NULL);
}
}
if (defVal != NULL) {
if (xmlSchemaCompareValuesWhtsp(ctxt->value,
(xmlSchemaWhitespaceValueType) ws,
defVal, (xmlSchemaWhitespaceValueType) ws) != 0)
state->state =
XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
}
} else if (! xmlStrEqual(defValue, BAD_CAST value)) {
/*
* TODO: Remove this and ensure computed values to be
* existent.
*/
state->state =
XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
}
}
}
......
......@@ -45,6 +45,11 @@ extern double xmlXPathNINF;
#define XML_SCHEMAS_NAMESPACE_NAME \
(const xmlChar *)"http://www.w3.org/2001/XMLSchema"
#define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \
((c) == 0xd))
#define IS_WSP_SPACE_CH(c) ((c) == 0x20)
static unsigned long powten[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
......@@ -676,6 +681,34 @@ xmlSchemaNewValue(xmlSchemaValType type) {
return(value);
}
/**
* xmlSchemaNewStringValue:
* @type: the value type
*
* Allocate a new simple type value. The type can be
* of XML_SCHEMAS_STRING.
*
* Returns a pointer to the new value or NULL in case of error
*/
xmlSchemaValPtr
xmlSchemaNewStringValue(xmlSchemaValType type,
const xmlChar *value)
{
xmlSchemaValPtr val;
if (type != XML_SCHEMAS_STRING)
return(NULL);
val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
if (val == NULL) {
return(NULL);
}
memset(val, 0, sizeof(xmlSchemaVal));
val->type = type;
val->value.str = (xmlChar *) value;
return(val);
}
/**
* xmlSchemaFreeValue:
* @value: the value to free
......@@ -2210,7 +2243,11 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
case XML_SCHEMAS_IDREF:
ret = xmlValidateNCName(value, 1);
if ((ret == 0) && (val != NULL)) {
TODO;
v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
if (v == NULL)
goto error;
v->value.str = xmlStrdup(value);
*val = v;
}
if ((ret == 0) && (node != NULL) &&
(node->type == XML_ATTRIBUTE_NODE)) {
......@@ -3477,6 +3514,333 @@ xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
return 0;
}
/**
* xmlSchemaComparePreserveReplaceStrings:
* @x: a first string value
* @y: a second string value
* @invert: inverts the result if x < y or x > y.
*
* Compare 2 string for their normalized values.
* @x is a string with whitespace of "preserve", @y is
* a string with a whitespace of "replace". I.e. @x could
* be an "xsd:string" and @y an "xsd:normalizedString".
*
* Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
* case of error
*/
static int
xmlSchemaComparePreserveReplaceStrings(xmlSchemaValPtr x, xmlSchemaValPtr y,
int invert)
{
const xmlChar *utf1;
const xmlChar *utf2;
int tmp;
if ((x == NULL) || (y == NULL))
return(-2);
utf1 = x->value.str;
utf2 = y->value.str;
while ((*utf1 != 0) && (*utf2 != 0)) {
if (IS_WSP_REPLACE_CH(*utf2)) {
if (! IS_WSP_SPACE_CH(*utf1)) {
if ((*utf1 - 0x20) < 0) {
if (invert)
return(1);
else
return(-1);
} else {
if (invert)
return(-1);
else
return(1);
}
}
} else {
tmp = *utf1 - *utf2;
if (tmp < 0) {
if (invert)
return(1);
else
return(-1);
}
if (tmp > 0) {
if (invert)
return(-1);
else
return(1);
}
}
utf1++;
utf2++;
}
if (*utf1 != 0) {
if (invert)
return(-1);
else
return(1);
}
if (*utf2 != 0) {
if (invert)
return(1);
else
return(-1);
}
return(0);
}
/**
* xmlSchemaComparePreserveCollapseStrings:
* @x: a first string value
* @y: a second string value
*
* Compare 2 string for their normalized values.
* @x is a string with whitespace of "preserve", @y is
* a string with a whitespace of "collapse". I.e. @x could
* be an "xsd:string" and @y an "xsd:normalizedString".
*
* Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
* case of error
*/
static int
xmlSchemaComparePreserveCollapseStrings(xmlSchemaValPtr x, xmlSchemaValPtr y,
int invert)
{
const xmlChar *utf1;
const xmlChar *utf2;
int tmp;
if ((x == NULL) || (y == NULL))
return(-2);
utf1 = x->value.str;
utf2 = y->value.str;
/*
* Skip leading blank chars of the collapsed string.
*/
while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
utf2++;
while ((*utf1 != 0) && (*utf2 != 0)) {
if (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2)) {
if (! IS_WSP_SPACE_CH(*utf1)) {
/*
* The utf2 character would have been replaced to 0x20.
*/
if ((*utf1 - 0x20) < 0) {
if (invert)
return(1);
else
return(-1);
} else {
if (invert)
return(-1);
else
return(1);
}
}
utf1++;
utf2++;
/*
* Skip contiguous blank chars of the collapsed string.
*/
while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
utf2++;
} else {
tmp = *utf1++ - *utf2++;
if (tmp < 0) {
if (invert)
return(1);
else
return(-1);
}
if (tmp > 0) {
if (invert)
return(-1);
else
return(1);
}
}
}
if (*utf1 != 0) {
if (invert)
return(-1);
else
return(1);
}
if (*utf2 != 0) {
/*
* Skip trailing blank chars of the collapsed string.
*/
while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
utf2++;
if (*utf2 != 0) {
if (invert)
return(1);
else
return(-1);
}
}
return(0);
}
/**
* xmlSchemaComparePreserveCollapseStrings:
* @x: a first string value
* @y: a second string value
*
* Compare 2 string for their normalized values.
* @x is a string with whitespace of "preserve", @y is
* a string with a whitespace of "collapse". I.e. @x could
* be an "xsd:string" and @y an "xsd:normalizedString".
*
* Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
* case of error
*/
static int
xmlSchemaCompareReplaceCollapseStrings(xmlSchemaValPtr x, xmlSchemaValPtr y,
int invert)
{
const xmlChar *utf1;
const xmlChar *utf2;
int tmp;
if ((x == NULL) || (y == NULL))
return(-2);
utf1 = x->value.str;
utf2 = y->value.str;
/*
* Skip leading blank chars of the collapsed string.
*/
while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
utf2++;
while ((*utf1 != 0) && (*utf2 != 0)) {
if (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2)) {
if (! (IS_WSP_SPACE_CH(*utf1) || IS_WSP_REPLACE_CH(*utf1))) {
/*
* The utf2 character would have been replaced to 0x20.
*/
if ((*utf1 - 0x20) < 0) {
if (invert)
return(1);
else
return(-1);
} else {
if (invert)
return(-1);
else
return(1);
}
}
utf1++;
utf2++;
/*
* Skip contiguous blank chars of the collapsed string.
*/
while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
utf2++;
} else {
if (IS_WSP_SPACE_CH(*utf1) || IS_WSP_REPLACE_CH(*utf1)) {
/*
* The utf1 character would have been replaced to 0x20.
*/
if ((0x20 - *utf2) < 0) {
if (invert)
return(1);
else
return(-1);
} else {
if (invert)
return(-1);
else
return(1);
}
}
tmp = *utf1++ - *utf2++;
if (tmp < 0)
return(-1);
if (tmp > 0)
return(1);
}
}
if (*utf1 != 0) {
if (invert)
return(-1);
else
return(1);
}
if (*utf2 != 0) {
/*
* Skip trailing blank chars of the collapsed string.
*/
while (IS_WSP_SPACE_CH(*utf2) || IS_WSP_REPLACE_CH(*utf2))
utf2++;
if (*utf2 != 0) {
if (invert)
return(1);
else
return(-1);
}
}