xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
{
    xmlRelaxNGDefinePtr ret, cur, last;
    xmlNodePtr child;
    const xmlChar *olddefine;

    ret = xmlRelaxNGNewDefine(ctxt, node);
    if (ret == NULL)
        return (NULL);
    ret->type = XML_RELAXNG_ELEMENT;
    ret->parent = ctxt->def;
    child = node->children;
    if (child == NULL) {
        xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,
                   "xmlRelaxNGParseElement: element has no children\n",
                   NULL, NULL);
        return (ret);
    }
    cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
    if (cur != NULL)
        child = child->next;

    if (child == NULL) {
        xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,
                   "xmlRelaxNGParseElement: element has no content\n",
                   NULL, NULL);
        return (ret);
    }
    olddefine = ctxt->define;
    ctxt->define = NULL;
    last = NULL;
    while (child != NULL) {
        cur = xmlRelaxNGParsePattern(ctxt, child);
        if (cur != NULL) {
            cur->parent = ret;
            switch (cur->type) {
                case XML_RELAXNG_EMPTY:
                case XML_RELAXNG_NOT_ALLOWED:
                case XML_RELAXNG_TEXT:
                case XML_RELAXNG_ELEMENT:
                case XML_RELAXNG_DATATYPE:
                case XML_RELAXNG_VALUE:
                case XML_RELAXNG_LIST:
                case XML_RELAXNG_REF:
                case XML_RELAXNG_PARENTREF:
                case XML_RELAXNG_EXTERNALREF:
                case XML_RELAXNG_DEF:
                case XML_RELAXNG_ZEROORMORE:
                case XML_RELAXNG_ONEORMORE:
                case XML_RELAXNG_OPTIONAL:
                case XML_RELAXNG_CHOICE:
                case XML_RELAXNG_GROUP:
                case XML_RELAXNG_INTERLEAVE:
                    if (last == NULL) {
                        ret->content = last = cur;
                    } else {
                        if ((last->type == XML_RELAXNG_ELEMENT) &&
                            (ret->content == last)) {
                            ret->content = xmlRelaxNGNewDefine(ctxt, node);
                            if (ret->content != NULL) {
                                ret->content->type = XML_RELAXNG_GROUP;
                                ret->content->content = last;
                            } else {
                                ret->content = last;
                            }
                        }
                        last->next = cur;
                        last = cur;
                    }
                    break;
                case XML_RELAXNG_ATTRIBUTE:
                    cur->next = ret->attrs;
                    ret->attrs = cur;
                    break;
                case XML_RELAXNG_START:
                    xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
                               "RNG Internal error, start found in element\n",
                               NULL, NULL);
                    break;
                case XML_RELAXNG_PARAM:
                    xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
                               "RNG Internal error, param found in element\n",
                               NULL, NULL);
                    break;
                case XML_RELAXNG_EXCEPT:
                    xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
                               "RNG Internal error, except found in element\n",
                               NULL, NULL);
                    break;
                case XML_RELAXNG_NOOP:
                    xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
                               "RNG Internal error, noop found in element\n",
                               NULL, NULL);
                    break;
            }
        }
        child = child->next;
    }
    ctxt->define = olddefine;
    return (ret);
}