xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
{
    int ret = 0;
    xmlSchemaNodeInfoPtr inode = vctxt->inode;

    if (vctxt->nbAttrInfos != 0)
	xmlSchemaClearAttrInfos(vctxt);
    if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
	/*
	* This element was not expected;
	* we will not validate child elements of broken parents.
	* Skip validation of all content of the parent.
	*/
	vctxt->skipDepth = vctxt->depth -1;
	goto end_elem;
    }
    if ((inode->typeDef == NULL) ||
	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
	/*
	* 1. the type definition might be missing if the element was
	*    error prone
	* 2. it might be abstract.
	*/
	goto end_elem;
    }
    /*
    * Check the content model.
    */
    if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {

	/*
	* Workaround for "anyType".
	*/
	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
	    goto character_content;

	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
	    xmlChar *values[10];
	    int terminal, nbval = 10, nbneg;

	    if (inode->regexCtxt == NULL) {
		/*
		* Create the regex context.
		*/
		inode->regexCtxt =
		    xmlRegNewExecCtxt(inode->typeDef->contModel,
		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
		    vctxt);
		if (inode->regexCtxt == NULL) {
		    VERROR_INT("xmlSchemaValidatorPopElem",
			"failed to create a regex context");
		    goto internal_error;
		}
#ifdef DEBUG_AUTOMATA
		xmlGenericError(xmlGenericErrorContext,
		    "AUTOMATON create on '%s'\n", inode->localName);
#endif
	    }

	    /*
	     * Do not check further content if the node has been nilled
	     */
	    if (INODE_NILLED(inode)) {
		ret = 0;
#ifdef DEBUG_AUTOMATA
		xmlGenericError(xmlGenericErrorContext,
		    "AUTOMATON succeeded on nilled '%s'\n",
		    inode->localName);
#endif
                goto skip_nilled;
	    }

	    /*
	    * Get hold of the still expected content, since a further
	    * call to xmlRegExecPushString() will loose this information.
	    */
	    xmlRegExecNextValues(inode->regexCtxt,
		&nbval, &nbneg, &values[0], &terminal);
	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
		/*
		* Still missing something.
		*/
		ret = 1;
		inode->flags |=
		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
		    "Missing child element(s)",
		    nbval, nbneg, values);
#ifdef DEBUG_AUTOMATA
		xmlGenericError(xmlGenericErrorContext,
		    "AUTOMATON missing ERROR on '%s'\n",
		    inode->localName);
#endif
	    } else {
		/*
		* Content model is satisfied.
		*/
		ret = 0;
#ifdef DEBUG_AUTOMATA
		xmlGenericError(xmlGenericErrorContext,
		    "AUTOMATON succeeded on '%s'\n",
		    inode->localName);
#endif
	    }

	}
    }

skip_nilled:

    if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
	goto end_elem;

character_content:

    if (vctxt->value != NULL) {
	xmlSchemaFreeValue(vctxt->value);
	vctxt->value = NULL;
    }
    /*
    * Check character content.
    */
    if (inode->decl == NULL) {
	/*
	* Speedup if no declaration exists.
	*/
	if (WXS_IS_SIMPLE(inode->typeDef)) {
	    ret = xmlSchemaVCheckINodeDataType(vctxt,
		inode, inode->typeDef, inode->value);
	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
	    ret = xmlSchemaVCheckINodeDataType(vctxt,
		inode, inode->typeDef->contentTypeDef,
		inode->value);
	}
	if (ret < 0) {
	    VERROR_INT("xmlSchemaValidatorPopElem",
		"calling xmlSchemaVCheckCVCSimpleType()");
	    goto internal_error;
	}
	goto end_elem;
    }
    /*
    * cvc-elt (3.3.4) : 5
    * The appropriate case among the following must be true:
    */
    /*
    * cvc-elt (3.3.4) : 5.1
    * If the declaration has a {value constraint},
    * the item has neither element nor character [children] and
    * clause 3.2 has not applied, then all of the following must be true:
    */
    if ((inode->decl->value != NULL) &&
	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
	(! INODE_NILLED(inode))) {
	/*
	* cvc-elt (3.3.4) : 5.1.1
	* If the `actual type definition` is a `local type definition`
	* then the canonical lexical representation of the {value constraint}
	* value must be a valid default for the `actual type definition` as
	* defined in Element Default Valid (Immediate) ($3.3.6).
	*/
	/*
	* NOTE: 'local' above means types acquired by xsi:type.
	* NOTE: Although the *canonical* value is stated, it is not
	* relevant if canonical or not. Additionally XML Schema 1.1
	* will removed this requirement as well.
	*/
	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {

	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
		inode->decl->value, &(inode->val));
	    if (ret != 0) {
		if (ret < 0) {
		    VERROR_INT("xmlSchemaValidatorPopElem",
			"calling xmlSchemaCheckCOSValidDefault()");
		    goto internal_error;
		}
		goto end_elem;
	    }
	    /*
	    * Stop here, to avoid redundant validation of the value
	    * (see following).
	    */
	    goto default_psvi;
	}
	/*
	* cvc-elt (3.3.4) : 5.1.2
	* The element information item with the canonical lexical
	* representation of the {value constraint} value used as its
	* `normalized value` must be `valid` with respect to the
	* `actual type definition` as defined by Element Locally Valid (Type)
	* ($3.3.4).
	*/
	if (WXS_IS_SIMPLE(inode->typeDef)) {
	    ret = xmlSchemaVCheckINodeDataType(vctxt,
		inode, inode->typeDef, inode->decl->value);
	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
	    ret = xmlSchemaVCheckINodeDataType(vctxt,
		inode, inode->typeDef->contentTypeDef,
		inode->decl->value);
	}
	if (ret != 0) {
	    if (ret < 0) {
		VERROR_INT("xmlSchemaValidatorPopElem",
		    "calling xmlSchemaVCheckCVCSimpleType()");
		goto internal_error;
	    }
	    goto end_elem;
	}

default_psvi:
	/*
	* PSVI: Create a text node on the instance element.
	*/
	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
	    (inode->node != NULL)) {
	    xmlNodePtr textChild;
	    xmlChar *normValue;
	    /*
	    * VAL TODO: Normalize the value.
	    */
	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
		inode->decl->value);
	    if (normValue != NULL) {
		textChild = xmlNewText(BAD_CAST normValue);
		xmlFree(normValue);
	    } else
		textChild = xmlNewText(inode->decl->value);
	    if (textChild == NULL) {
		VERROR_INT("xmlSchemaValidatorPopElem",
		    "calling xmlNewText()");
		goto internal_error;
	    } else
		xmlAddChild(inode->node, textChild);
	}

    } else if (! INODE_NILLED(inode)) {
	/*
	* 5.2.1 The element information item must be `valid` with respect
	* to the `actual type definition` as defined by Element Locally
	* Valid (Type) ($3.3.4).
	*/
	if (WXS_IS_SIMPLE(inode->typeDef)) {
	     /*
	    * SPEC (cvc-type) (3.1)
	    * "If the type definition is a simple type definition, ..."
	    * (3.1.3) "If clause 3.2 of Element Locally Valid
	    * (Element) ($3.3.4) did not apply, then the `normalized value`
	    * must be `valid` with respect to the type definition as defined
	    * by String Valid ($3.14.4).
	    */
	    ret = xmlSchemaVCheckINodeDataType(vctxt,
		    inode, inode->typeDef, inode->value);
	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
	    /*
	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
	    * definition, then the element information item must be
	    * `valid` with respect to the type definition as per
	    * Element Locally Valid (Complex Type) ($3.4.4);"
	    *
	    * SPEC (cvc-complex-type) (2.2)
	    * "If the {content type} is a simple type definition, ...
	    * the `normalized value` of the element information item is
	    * `valid` with respect to that simple type definition as
	    * defined by String Valid ($3.14.4)."
	    */
	    ret = xmlSchemaVCheckINodeDataType(vctxt,
		inode, inode->typeDef->contentTypeDef, inode->value);
	}
	if (ret != 0) {
	    if (ret < 0) {
		VERROR_INT("xmlSchemaValidatorPopElem",
		    "calling xmlSchemaVCheckCVCSimpleType()");
		goto internal_error;
	    }
	    goto end_elem;
	}
	/*
	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
	* not applied, all of the following must be true:
	*/
	if ((inode->decl->value != NULL) &&
	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {

	    /*
	    * TODO: We will need a computed value, when comparison is
	    * done on computed values.
	    */
	    /*
	    * 5.2.2.1 The element information item must have no element
	    * information item [children].
	    */
	    if (inode->flags &
		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
		VERROR(ret, NULL,
		    "The content must not containt element nodes since "
		    "there is a fixed value constraint");
		goto end_elem;
	    } else {
		/*
		* 5.2.2.2 The appropriate case among the following must
		* be true:
		*/
		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
		    /*
		    * 5.2.2.2.1 If the {content type} of the `actual type
		    * definition` is mixed, then the *initial value* of the
		    * item must match the canonical lexical representation
		    * of the {value constraint} value.
		    *
		    * ... the *initial value* of an element information
		    * item is the string composed of, in order, the
		    * [character code] of each character information item in
		    * the [children] of that element information item.
		    */
		    if (! xmlStrEqual(inode->value, inode->decl->value)){
			/*
			* VAL TODO: Report invalid & expected values as well.
			* VAL TODO: Implement the canonical stuff.
			*/
			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
			xmlSchemaCustomErr(ACTXT_CAST vctxt,
			    ret, NULL, NULL,
			    "The initial value '%s' does not match the fixed "
			    "value constraint '%s'",
			    inode->value, inode->decl->value);
			goto end_elem;
		    }
		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
		    /*
		    * 5.2.2.2.2 If the {content type} of the `actual type
		    * definition` is a simple type definition, then the
		    * *actual value* of the item must match the canonical
		    * lexical representation of the {value constraint} value.
		    */
		    /*
		    * VAL TODO: *actual value* is the normalized value, impl.
		    *           this.
		    * VAL TODO: Report invalid & expected values as well.
		    * VAL TODO: Implement a comparison with the computed values.
		    */
		    if (! xmlStrEqual(inode->value,
			    inode->decl->value)) {
			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
			xmlSchemaCustomErr(ACTXT_CAST vctxt,
			    ret, NULL, NULL,
			    "The actual value '%s' does not match the fixed "
			    "value constraint '%s'",
			    inode->value,
			    inode->decl->value);
			goto end_elem;
		    }
		}
	    }
	}
    }

end_elem:
    if (vctxt->depth < 0) {
	/* TODO: raise error? */
	return (0);
    }
    if (vctxt->depth == vctxt->skipDepth)
	vctxt->skipDepth = -1;
    /*
    * Evaluate the history of XPath state objects.
    */
    if (inode->appliedXPath &&
	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
	goto internal_error;
    /*
    * MAYBE TODO:
    * SPEC (6) "The element information item must be `valid` with
    * respect to each of the {identity-constraint definitions} as per
    * Identity-constraint Satisfied ($3.11.4)."
    */
    /*
    * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
    *   need to be built in any case.
    *   We will currently build IDC node-tables and bubble them only if
    *   keyrefs do exist.
    */

    /*
    * Add the current IDC target-nodes to the IDC node-tables.
    */
    if ((inode->idcMatchers != NULL) &&
	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
    {
	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
	    goto internal_error;
    }
    /*
    * Validate IDC keyrefs.
    */
    if (vctxt->inode->hasKeyrefs)
	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
	    goto internal_error;
    /*
    * Merge/free the IDC table.
    */
    if (inode->idcTable != NULL) {
#ifdef DEBUG_IDC_NODE_TABLE
	xmlSchemaDebugDumpIDCTable(stdout,
	    inode->nsName,
	    inode->localName,
	    inode->idcTable);
#endif
	if ((vctxt->depth > 0) &&
	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
	{
	    /*
	    * Merge the IDC node table with the table of the parent node.
	    */
	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
		goto internal_error;
	}
    }
    /*
    * Clear the current ielem.
    * VAL TODO: Don't free the PSVI IDC tables if they are
    * requested for the PSVI.
    */
    xmlSchemaClearElemInfo(vctxt, inode);
    /*
    * Skip further processing if we are on the validation root.
    */
    if (vctxt->depth == 0) {
	vctxt->depth--;
	vctxt->inode = NULL;
	return (0);
    }
    /*
    * Reset the keyrefDepth if needed.
    */
    if (vctxt->aidcs != NULL) {
	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
	do {
	    if (aidc->keyrefDepth == vctxt->depth) {
		/*
		* A 'keyrefDepth' of a key/unique IDC matches the current
		* depth, this means that we are leaving the scope of the
		* top-most keyref IDC which refers to this IDC.
		*/
		aidc->keyrefDepth = -1;
	    }
	    aidc = aidc->next;
	} while (aidc != NULL);
    }
    vctxt->depth--;
    vctxt->inode = vctxt->elemInfos[vctxt->depth];
    /*
    * VAL TODO: 7 If the element information item is the `validation root`, it must be
    * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
    */
    return (ret);

internal_error:
    vctxt->err = -1;
    return (-1);
}