xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
{
    xmlSchemaTypePtr type = vctxt->inode->typeDef;
    xmlSchemaItemListPtr attrUseList;
    xmlSchemaAttributeUsePtr attrUse = NULL;
    xmlSchemaAttributePtr attrDecl = NULL;
    xmlSchemaAttrInfoPtr iattr, tmpiattr;
    int i, j, found, nbAttrs, nbUses;
    int xpathRes = 0, res, wildIDs = 0, fixed;
    xmlNodePtr defAttrOwnerElem = NULL;

    /*
    * SPEC (cvc-attribute)
    * (1) "The declaration must not be `absent` (see Missing
    * Sub-components ($5.3) for how this can fail to be
    * the case)."
    * (2) "Its {type definition} must not be absent."
    *
    * NOTE (1) + (2): This is not handled here, since we currently do not
    * allow validation against schemas which have missing sub-components.
    *
    * SPEC (cvc-complex-type)
    * (3) "For each attribute information item in the element information
    * item's [attributes] excepting those whose [namespace name] is
    * identical to http://www.w3.org/2001/XMLSchema-instance and whose
    * [local name] is one of type, nil, schemaLocation or
    * noNamespaceSchemaLocation, the appropriate case among the following
    * must be true:
    *
    */
    attrUseList = (xmlSchemaItemListPtr) type->attrUses;
    /*
    * @nbAttrs is the number of attributes present in the instance.
    */
    nbAttrs = vctxt->nbAttrInfos;
    if (attrUseList != NULL)
	nbUses = attrUseList->nbItems;
    else
	nbUses = 0;
    for (i = 0; i < nbUses; i++) {
        found = 0;
	attrUse = attrUseList->items[i];
	attrDecl = WXS_ATTRUSE_DECL(attrUse);
        for (j = 0; j < nbAttrs; j++) {
	    iattr = vctxt->attrInfos[j];
	    /*
	    * SPEC (cvc-complex-type) (3)
	    * Skip meta attributes.
	    */
	    if (iattr->metaType)
		continue;
	    if (iattr->localName[0] != attrDecl->name[0])
		continue;
	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
		continue;
	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
		continue;
	    found = 1;
	    /*
	    * SPEC (cvc-complex-type)
	    * (3.1) "If there is among the {attribute uses} an attribute
	    * use with an {attribute declaration} whose {name} matches
	    * the attribute information item's [local name] and whose
	    * {target namespace} is identical to the attribute information
	    * item's [namespace name] (where an `absent` {target namespace}
	    * is taken to be identical to a [namespace name] with no value),
	    * then the attribute information must be `valid` with respect
	    * to that attribute use as per Attribute Locally Valid (Use)
	    * ($3.5.4). In this case the {attribute declaration} of that
	    * attribute use is the `context-determined declaration` for the
	    * attribute information item with respect to Schema-Validity
	    * Assessment (Attribute) ($3.2.4) and
	    * Assessment Outcome (Attribute) ($3.2.5).
	    */
	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
	    iattr->use = attrUse;
	    /*
	    * Context-determined declaration.
	    */
	    iattr->decl = attrDecl;
	    iattr->typeDef = attrDecl->subtypes;
	    break;
	}

	if (found)
	    continue;

	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
	    /*
	    * Handle non-existent, required attributes.
	    *
	    * SPEC (cvc-complex-type)
	    * (4) "The {attribute declaration} of each attribute use in
	    * the {attribute uses} whose {required} is true matches one
	    * of the attribute information items in the element information
	    * item's [attributes] as per clause 3.1 above."
	    */
	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
	    if (tmpiattr == NULL) {
		VERROR_INT(
		    "xmlSchemaVAttributesComplex",
		    "calling xmlSchemaGetFreshAttrInfo()");
		return (-1);
	    }
	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
	    tmpiattr->use = attrUse;
	    tmpiattr->decl = attrDecl;
	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
	    ((attrUse->defValue != NULL) ||
	     (attrDecl->defValue != NULL))) {
	    /*
	    * Handle non-existent, optional, default/fixed attributes.
	    */
	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
	    if (tmpiattr == NULL) {
		VERROR_INT(
		    "xmlSchemaVAttributesComplex",
		    "calling xmlSchemaGetFreshAttrInfo()");
		return (-1);
	    }
	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
	    tmpiattr->use = attrUse;
	    tmpiattr->decl = attrDecl;
	    tmpiattr->typeDef = attrDecl->subtypes;
	    tmpiattr->localName = attrDecl->name;
	    tmpiattr->nsName = attrDecl->targetNamespace;
	}
    }

    if (vctxt->nbAttrInfos == 0)
	return (0);
    /*
    * Validate against the wildcard.
    */
    if (type->attributeWildcard != NULL) {
	/*
	* SPEC (cvc-complex-type)
	* (3.2.1) "There must be an {attribute wildcard}."
	*/
	for (i = 0; i < nbAttrs; i++) {
	    iattr = vctxt->attrInfos[i];
	    /*
	    * SPEC (cvc-complex-type) (3)
	    * Skip meta attributes.
	    */
	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
		continue;
	    /*
	    * SPEC (cvc-complex-type)
	    * (3.2.2) "The attribute information item must be `valid` with
	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
	    *
	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
	    * "... its [namespace name] must be `valid` with respect to
	    * the wildcard constraint, as defined in Wildcard allows
	    * Namespace Name ($3.10.4)."
	    */
	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
		    iattr->nsName) == 0) {
		/*
		* Handle processContents.
		*
		* SPEC (cvc-wildcard):
		* processContents | context-determined declaration:
		* "strict"          "mustFind"
		* "lax"             "none"
		* "skip"            "skip"
		*/
		if (type->attributeWildcard->processContents ==
		    XML_SCHEMAS_ANY_SKIP) {
		     /*
		    * context-determined declaration = "skip"
		    *
		    * SPEC PSVI Assessment Outcome (Attribute)
		    * [validity] = "notKnown"
		    * [validation attempted] = "none"
		    */
		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
		    continue;
		}
		/*
		* Find an attribute declaration.
		*/
		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
		    iattr->localName, iattr->nsName);
		if (iattr->decl != NULL) {
		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
		    /*
		    * SPEC (cvc-complex-type)
		    * (5) "Let [Definition:]  the wild IDs be the set of
		    * all attribute information item to which clause 3.2
		    * applied and whose `validation` resulted in a
		    * `context-determined declaration` of mustFind or no
		    * `context-determined declaration` at all, and whose
		    * [local name] and [namespace name] resolve (as
		    * defined by QName resolution (Instance) ($3.15.4)) to
		    * an attribute declaration whose {type definition} is
		    * or is derived from ID. Then all of the following
		    * must be true:"
		    */
		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
		    if (xmlSchemaIsDerivedFromBuiltInType(
			iattr->typeDef, XML_SCHEMAS_ID)) {
			/*
			* SPEC (5.1) "There must be no more than one
			* item in `wild IDs`."
			*/
			if (wildIDs != 0) {
			    /* VAL TODO */
			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
			    TODO
			    continue;
			}
			wildIDs++;
			/*
			* SPEC (cvc-complex-type)
			* (5.2) "If `wild IDs` is non-empty, there must not
			* be any attribute uses among the {attribute uses}
			* whose {attribute declaration}'s {type definition}
			* is or is derived from ID."
			*/
                        if (attrUseList != NULL) {
                            for (j = 0; j < attrUseList->nbItems; j++) {
                                if (xmlSchemaIsDerivedFromBuiltInType(
                                    WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
                                    XML_SCHEMAS_ID)) {
                                    /* URGENT VAL TODO: implement */
                            iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
                                    TODO
                                    break;
                                }
                            }
                        }
		    }
		} else if (type->attributeWildcard->processContents ==
		    XML_SCHEMAS_ANY_LAX) {
		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
		    /*
		    * SPEC PSVI Assessment Outcome (Attribute)
		    * [validity] = "notKnown"
		    * [validation attempted] = "none"
		    */
		} else {
		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
		}
	    }
	}
    }

    if (vctxt->nbAttrInfos == 0)
	return (0);

    /*
    * Get the owner element; needed for creation of default attributes.
    * This fixes bug #341337, reported by David Grohmann.
    */
    if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
	if (ielem && ielem->node && ielem->node->doc)
	    defAttrOwnerElem = ielem->node;
    }
    /*
    * Validate values, create default attributes, evaluate IDCs.
    */
    for (i = 0; i < vctxt->nbAttrInfos; i++) {
	iattr = vctxt->attrInfos[i];
	/*
	* VAL TODO: Note that we won't try to resolve IDCs to
	* "lax" and "skip" validated attributes. Check what to
	* do in this case.
	*/
	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
	    continue;
	/*
	* VAL TODO: What to do if the type definition is missing?
	*/
	if (iattr->typeDef == NULL) {
	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
	    continue;
	}

	ACTIVATE_ATTRIBUTE(iattr);
	fixed = 0;
	xpathRes = 0;

	if (vctxt->xpathStates != NULL) {
	    /*
	    * Evaluate IDCs.
	    */
	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
		XML_ATTRIBUTE_NODE);
	    if (xpathRes == -1) {
		VERROR_INT("xmlSchemaVAttributesComplex",
		    "calling xmlSchemaXPathEvaluate()");
		goto internal_error;
	    }
	}

	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
	    /*
	    * Default/fixed attributes.
	    * We need the value only if we need to resolve IDCs or
	    * will create default attributes.
	    */
	    if ((xpathRes) || (defAttrOwnerElem)) {
		if (iattr->use->defValue != NULL) {
		    iattr->value = (xmlChar *) iattr->use->defValue;
		    iattr->val = iattr->use->defVal;
		} else {
		    iattr->value = (xmlChar *) iattr->decl->defValue;
		    iattr->val = iattr->decl->defVal;
		}
		/*
		* IDCs will consume the precomputed default value,
		* so we need to clone it.
		*/
		if (iattr->val == NULL) {
		    VERROR_INT("xmlSchemaVAttributesComplex",
			"default/fixed value on an attribute use was "
			"not precomputed");
		    goto internal_error;
		}
		iattr->val = xmlSchemaCopyValue(iattr->val);
		if (iattr->val == NULL) {
		    VERROR_INT("xmlSchemaVAttributesComplex",
			"calling xmlSchemaCopyValue()");
		    goto internal_error;
		}
	    }
	    /*
	    * PSVI: Add the default attribute to the current element.
	    * VAL TODO: Should we use the *normalized* value? This currently
	    *   uses the *initial* value.
	    */

	    if (defAttrOwnerElem) {
		xmlChar *normValue;
		const xmlChar *value;

		value = iattr->value;
		/*
		* Normalize the value.
		*/
		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
		    iattr->value);
		if (normValue != NULL)
		    value = BAD_CAST normValue;

		if (iattr->nsName == NULL) {
		    if (xmlNewProp(defAttrOwnerElem,
			iattr->localName, value) == NULL) {
			VERROR_INT("xmlSchemaVAttributesComplex",
			    "calling xmlNewProp()");
			if (normValue != NULL)
			    xmlFree(normValue);
			goto internal_error;
		    }
		} else {
		    xmlNsPtr ns;

		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
			defAttrOwnerElem, iattr->nsName);
		    if (ns == NULL) {
			xmlChar prefix[12];
			int counter = 0;

			/*
			* Create a namespace declaration on the validation
			* root node if no namespace declaration is in scope.
			*/
			do {
			    snprintf((char *) prefix, 12, "p%d", counter++);
			    ns = xmlSearchNs(defAttrOwnerElem->doc,
				defAttrOwnerElem, BAD_CAST prefix);
			    if (counter > 1000) {
				VERROR_INT(
				    "xmlSchemaVAttributesComplex",
				    "could not compute a ns prefix for a "
				    "default/fixed attribute");
				if (normValue != NULL)
				    xmlFree(normValue);
				goto internal_error;
			    }
			} while (ns != NULL);
			ns = xmlNewNs(vctxt->validationRoot,
			    iattr->nsName, BAD_CAST prefix);
		    }
		    /*
		    * TODO:
		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
		    * If we have QNames: do we need to ensure there's a
		    * prefix defined for the QName?
		    */
		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
		}
		if (normValue != NULL)
		    xmlFree(normValue);
	    }
	    /*
	    * Go directly to IDC evaluation.
	    */
	    goto eval_idcs;
	}
	/*
	* Validate the value.
	*/
	if (vctxt->value != NULL) {
	    /*
	    * Free last computed value; just for safety reasons.
	    */
	    xmlSchemaFreeValue(vctxt->value);
	    vctxt->value = NULL;
	}
	/*
	* Note that the attribute *use* can be unavailable, if
	* the attribute was a wild attribute.
	*/
	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
	    ((iattr->use != NULL) &&
	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
	    fixed = 1;
	else
	    fixed = 0;
	/*
	* SPEC (cvc-attribute)
	* (3) "The item's `normalized value` must be locally `valid`
	* with respect to that {type definition} as per
	* String Valid ($3.14.4)."
	*
	* VAL TODO: Do we already have the
	* "normalized attribute value" here?
	*/
	if (xpathRes || fixed) {
	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
	    /*
	    * Request a computed value.
	    */
	    res = xmlSchemaVCheckCVCSimpleType(
		ACTXT_CAST vctxt,
		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
		1, 1, 0);
	} else {
	    res = xmlSchemaVCheckCVCSimpleType(
		ACTXT_CAST vctxt,
		iattr->node, iattr->typeDef, iattr->value, NULL,
		1, 0, 0);
	}

	if (res != 0) {
	    if (res == -1) {
		VERROR_INT("xmlSchemaVAttributesComplex",
		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
		goto internal_error;
	    }
	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
	    /*
	    * SPEC PSVI Assessment Outcome (Attribute)
	    * [validity] = "invalid"
	    */
	    goto eval_idcs;
	}

	if (fixed) {
	    /*
	    * SPEC Attribute Locally Valid (Use) (cvc-au)
	    * "For an attribute information item to be `valid`
	    * with respect to an attribute use its *normalized*
	    * value must match the *canonical* lexical
	    * representation of the attribute use's {value
	    * constraint}value, if it is present and fixed."
	    *
	    * VAL TODO: The requirement for the *canonical* value
	    * will be removed in XML Schema 1.1.
	    */
	    /*
	    * SPEC Attribute Locally Valid (cvc-attribute)
	    * (4) "The item's *actual* value must match the *value* of
	    * the {value constraint}, if it is present and fixed."
	    */
	    if (iattr->val == NULL) {
		/* VAL TODO: A value was not precomputed. */
		TODO
		goto eval_idcs;
	    }
	    if ((iattr->use != NULL) &&
		(iattr->use->defValue != NULL)) {
		if (iattr->use->defVal == NULL) {
		    /* VAL TODO: A default value was not precomputed. */
		    TODO
		    goto eval_idcs;
		}
		iattr->vcValue = iattr->use->defValue;
		/*
		if (xmlSchemaCompareValuesWhtsp(attr->val,
		    (xmlSchemaWhitespaceValueType) ws,
		    attr->use->defVal,
		    (xmlSchemaWhitespaceValueType) ws) != 0) {
		*/
		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
	    } else {
		if (iattr->decl->defVal == NULL) {
		    /* VAL TODO: A default value was not precomputed. */
		    TODO
		    goto eval_idcs;
		}
		iattr->vcValue = iattr->decl->defValue;
		/*
		if (xmlSchemaCompareValuesWhtsp(attr->val,
		    (xmlSchemaWhitespaceValueType) ws,
		    attrDecl->defVal,
		    (xmlSchemaWhitespaceValueType) ws) != 0) {
		*/
		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
	    }
	    /*
	    * [validity] = "valid"
	    */
	}
eval_idcs:
	/*
	* Evaluate IDCs.
	*/
	if (xpathRes) {
	    if (xmlSchemaXPathProcessHistory(vctxt,
		vctxt->depth +1) == -1) {
		VERROR_INT("xmlSchemaVAttributesComplex",
		    "calling xmlSchemaXPathEvaluate()");
		goto internal_error;
	    }
	} else if (vctxt->xpathStates != NULL)
	    xmlSchemaXPathPop(vctxt);
    }

    /*
    * Report errors.
    */
    for (i = 0; i < vctxt->nbAttrInfos; i++) {
	iattr = vctxt->attrInfos[i];
	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
	    continue;
	ACTIVATE_ATTRIBUTE(iattr);
	switch (iattr->state) {
	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
		    xmlChar *str = NULL;
		    ACTIVATE_ELEM;
		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
			"The attribute '%s' is required but missing",
			xmlSchemaFormatQName(&str,
			    iattr->decl->targetNamespace,
			    iattr->decl->name),
			NULL);
		    FREE_AND_NULL(str)
		    break;
		}
	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
		    "The type definition is absent");
		break;
	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
		xmlSchemaCustomErr(ACTXT_CAST vctxt,
		    XML_SCHEMAV_CVC_AU, NULL, NULL,
		    "The value '%s' does not match the fixed "
		    "value constraint '%s'",
		    iattr->value, iattr->vcValue);
		break;
	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
		    "No matching global attribute declaration available, but "
		    "demanded by the strict wildcard");
		break;
	    case XML_SCHEMAS_ATTR_UNKNOWN:
		if (iattr->metaType)
		    break;
		/*
		* MAYBE VAL TODO: One might report different error messages
		* for the following errors.
		*/
		if (type->attributeWildcard == NULL) {
		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
		} else {
		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
		}
		break;
	    default:
		break;
	}
    }

    ACTIVATE_ELEM;
    return (0);
internal_error:
    ACTIVATE_ELEM;
    return (-1);
}