xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
{
    xmlAttrPtr attr;
    int ret = 0;
    xmlSchemaNodeInfoPtr ielem = NULL;
    xmlNodePtr node, valRoot;
    const xmlChar *nsName;

    /* DOC VAL TODO: Move this to the start function. */
    if (vctxt->validationRoot != NULL)
        valRoot = vctxt->validationRoot;
    else
	valRoot = xmlDocGetRootElement(vctxt->doc);
    if (valRoot == NULL) {
	/* VAL TODO: Error code? */
	VERROR(1, NULL, "The document has no document element");
	return (1);
    }
    vctxt->depth = -1;
    vctxt->validationRoot = valRoot;
    node = valRoot;
    while (node != NULL) {
	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
	    goto next_sibling;
	if (node->type == XML_ELEMENT_NODE) {

	    /*
	    * Init the node-info.
	    */
	    vctxt->depth++;
	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
		goto internal_error;
	    ielem = vctxt->inode;
	    ielem->node = node;
	    ielem->nodeLine = node->line;
	    ielem->localName = node->name;
	    if (node->ns != NULL)
		ielem->nsName = node->ns->href;
	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
	    /*
	    * Register attributes.
	    * DOC VAL TODO: We do not register namespace declaration
	    * attributes yet.
	    */
	    vctxt->nbAttrInfos = 0;
	    if (node->properties != NULL) {
		attr = node->properties;
		do {
		    if (attr->ns != NULL)
			nsName = attr->ns->href;
		    else
			nsName = NULL;
		    ret = xmlSchemaValidatorPushAttribute(vctxt,
			(xmlNodePtr) attr,
			/*
			* Note that we give it the line number of the
			* parent element.
			*/
			ielem->nodeLine,
			attr->name, nsName, 0,
			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
		    if (ret == -1) {
			VERROR_INT("xmlSchemaDocWalk",
			    "calling xmlSchemaValidatorPushAttribute()");
			goto internal_error;
		    }
		    attr = attr->next;
		} while (attr);
	    }
	    /*
	    * Validate the element.
	    */
	    ret = xmlSchemaValidateElem(vctxt);
	    if (ret != 0) {
		if (ret == -1) {
		    VERROR_INT("xmlSchemaDocWalk",
			"calling xmlSchemaValidateElem()");
		    goto internal_error;
		}
		/*
		* Don't stop validation; just skip the content
		* of this element.
		*/
		goto leave_node;
	    }
	    if ((vctxt->skipDepth != -1) &&
		(vctxt->depth >= vctxt->skipDepth))
		goto leave_node;
	} else if ((node->type == XML_TEXT_NODE) ||
	    (node->type == XML_CDATA_SECTION_NODE)) {
	    /*
	    * Process character content.
	    */
	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
	    if (ret < 0) {
		VERROR_INT("xmlSchemaVDocWalk",
		    "calling xmlSchemaVPushText()");
		goto internal_error;
	    }
	    /*
	    * DOC VAL TODO: Should we skip further validation of the
	    * element content here?
	    */
	} else if ((node->type == XML_ENTITY_NODE) ||
	    (node->type == XML_ENTITY_REF_NODE)) {
	    /*
	    * DOC VAL TODO: What to do with entities?
	    */
	    VERROR_INT("xmlSchemaVDocWalk",
		"there is at least one entity reference in the node-tree "
		"currently being validated. Processing of entities with "
		"this XML Schema processor is not supported (yet). Please "
		"substitute entities before validation.");
	    goto internal_error;
	} else {
	    goto leave_node;
	    /*
	    * DOC VAL TODO: XInclude nodes, etc.
	    */
	}
	/*
	* Walk the doc.
	*/
	if (node->children != NULL) {
	    node = node->children;
	    continue;
	}
leave_node:
	if (node->type == XML_ELEMENT_NODE) {
	    /*
	    * Leaving the scope of an element.
	    */
	    if (node != vctxt->inode->node) {
		VERROR_INT("xmlSchemaVDocWalk",
		    "element position mismatch");
		goto internal_error;
	    }
	    ret = xmlSchemaValidatorPopElem(vctxt);
	    if (ret != 0) {
		if (ret < 0) {
		    VERROR_INT("xmlSchemaVDocWalk",
			"calling xmlSchemaValidatorPopElem()");
		    goto internal_error;
		}
	    }
	    if (node == valRoot)
		goto exit;
	}
next_sibling:
	if (node->next != NULL)
	    node = node->next;
	else {
	    node = node->parent;
	    goto leave_node;
	}
    }

exit:
    return (ret);
internal_error:
    return (-1);
}