xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
{
    xmlRelaxNGPtr ret = NULL;
    xmlDocPtr doc;
    xmlNodePtr root;

    xmlRelaxNGInitTypes();

    if (ctxt == NULL)
        return (NULL);

    /*
     * First step is to parse the input document into an DOM/Infoset
     */
    if (ctxt->URL != NULL) {
        doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
        if (doc == NULL) {
            xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
                       "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
                       NULL);
            return (NULL);
        }
    } else if (ctxt->buffer != NULL) {
        doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
        if (doc == NULL) {
            xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
                       "xmlRelaxNGParse: could not parse schemas\n", NULL,
                       NULL);
            return (NULL);
        }
        doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
        ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
    } else if (ctxt->document != NULL) {
        doc = ctxt->document;
    } else {
        xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,
                   "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);
        return (NULL);
    }
    ctxt->document = doc;

    /*
     * Some preprocessing of the document content
     */
    doc = xmlRelaxNGCleanupDoc(ctxt, doc);
    if (doc == NULL) {
        xmlFreeDoc(ctxt->document);
        ctxt->document = NULL;
        return (NULL);
    }

    /*
     * Then do the parsing for good
     */
    root = xmlDocGetRootElement(doc);
    if (root == NULL) {
        xmlRngPErr(ctxt, (xmlNodePtr) doc,
	           XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
                   (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);

        xmlFreeDoc(ctxt->document);
        ctxt->document = NULL;
        return (NULL);
    }
    ret = xmlRelaxNGParseDocument(ctxt, root);
    if (ret == NULL) {
        xmlFreeDoc(ctxt->document);
        ctxt->document = NULL;
        return (NULL);
    }

    /*
     * Check the ref/defines links
     */
    /*
     * try to preprocess interleaves
     */
    if (ctxt->interleaves != NULL) {
        xmlHashScan(ctxt->interleaves,
                    (xmlHashScanner) xmlRelaxNGComputeInterleaves, ctxt);
    }

    /*
     * if there was a parsing error return NULL
     */
    if (ctxt->nbErrors > 0) {
        xmlRelaxNGFree(ret);
        ctxt->document = NULL;
        xmlFreeDoc(doc);
        return (NULL);
    }

    /*
     * try to compile (parts of) the schemas
     */
    if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) {
        if (ret->topgrammar->start->type != XML_RELAXNG_START) {
            xmlRelaxNGDefinePtr def;

            def = xmlRelaxNGNewDefine(ctxt, NULL);
            if (def != NULL) {
                def->type = XML_RELAXNG_START;
                def->content = ret->topgrammar->start;
                ret->topgrammar->start = def;
            }
        }
        xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);
    }

    /*
     * Transfer the pointer for cleanup at the schema level.
     */
    ret->doc = doc;
    ctxt->document = NULL;
    ret->documents = ctxt->documents;
    ctxt->documents = NULL;

    ret->includes = ctxt->includes;
    ctxt->includes = NULL;
    ret->defNr = ctxt->defNr;
    ret->defTab = ctxt->defTab;
    ctxt->defTab = NULL;
    if (ctxt->idref == 1)
        ret->idref = 1;

    return (ret);
}