xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
                         xmlRelaxNGDefinePtr def)
{
    xmlRelaxNGDefinePtr ret, tmp;
    xmlChar *val;

    ret = def;
    if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||
        (IS_RELAXNG(node, "nsName"))) {
        if ((def->type != XML_RELAXNG_ELEMENT) &&
            (def->type != XML_RELAXNG_ATTRIBUTE)) {
            ret = xmlRelaxNGNewDefine(ctxt, node);
            if (ret == NULL)
                return (NULL);
            ret->parent = def;
            if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)
                ret->type = XML_RELAXNG_ATTRIBUTE;
            else
                ret->type = XML_RELAXNG_ELEMENT;
        }
    }
    if (IS_RELAXNG(node, "name")) {
        val = xmlNodeGetContent(node);
        xmlRelaxNGNormExtSpace(val);
        if (xmlValidateNCName(val, 0)) {
	    if (node->parent != NULL)
		xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
			   "Element %s name '%s' is not an NCName\n",
			   node->parent->name, val);
	    else
		xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
			   "name '%s' is not an NCName\n",
			   val, NULL);
        }
        ret->name = val;
        val = xmlGetProp(node, BAD_CAST "ns");
        ret->ns = val;
        if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
            (val != NULL) &&
            (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
	    xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
                        "Attribute with namespace '%s' is not allowed\n",
                        val, NULL);
        }
        if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
            (val != NULL) &&
            (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) {
	    xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,
                       "Attribute with QName 'xmlns' is not allowed\n",
                       val, NULL);
        }
    } else if (IS_RELAXNG(node, "anyName")) {
        ret->name = NULL;
        ret->ns = NULL;
        if (node->children != NULL) {
            ret->nameClass =
                xmlRelaxNGParseExceptNameClass(ctxt, node->children,
                                               (def->type ==
                                                XML_RELAXNG_ATTRIBUTE));
        }
    } else if (IS_RELAXNG(node, "nsName")) {
        ret->name = NULL;
        ret->ns = xmlGetProp(node, BAD_CAST "ns");
        if (ret->ns == NULL) {
            xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,
                       "nsName has no ns attribute\n", NULL, NULL);
        }
        if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
            (ret->ns != NULL) &&
            (xmlStrEqual
             (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
            xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
                       "Attribute with namespace '%s' is not allowed\n",
                       ret->ns, NULL);
        }
        if (node->children != NULL) {
            ret->nameClass =
                xmlRelaxNGParseExceptNameClass(ctxt, node->children,
                                               (def->type ==
                                                XML_RELAXNG_ATTRIBUTE));
        }
    } else if (IS_RELAXNG(node, "choice")) {
        xmlNodePtr child;
        xmlRelaxNGDefinePtr last = NULL;

        ret = xmlRelaxNGNewDefine(ctxt, node);
        if (ret == NULL)
            return (NULL);
        ret->parent = def;
        ret->type = XML_RELAXNG_CHOICE;

        if (node->children == NULL) {
            xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
                       "Element choice is empty\n", NULL, NULL);
        } else {

            child = node->children;
            while (child != NULL) {
                tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
                if (tmp != NULL) {
                    if (last == NULL) {
                        last = ret->nameClass = tmp;
                    } else {
                        last->next = tmp;
                        last = tmp;
                    }
                }
                child = child->next;
            }
        }
    } else {
        xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,
                   "expecting name, anyName, nsName or choice : got %s\n",
                   (node == NULL ? (const xmlChar *) "nothing" : node->name),
		   NULL);
        return (NULL);
    }
    if (ret != def) {
        if (def->nameClass == NULL) {
            def->nameClass = ret;
        } else {
            tmp = def->nameClass;
            while (tmp->next != NULL) {
                tmp = tmp->next;
            }
            tmp->next = ret;
        }
    }
    return (ret);
}