xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
{
    xmlAttrPtr cur, next;

    cur = node->properties;
    while (cur != NULL) {
        next = cur->next;
        if ((cur->ns == NULL) ||
            (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
            if (xmlStrEqual(cur->name, BAD_CAST "name")) {
                if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "ref")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "param")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "define"))) {
                    xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
                               "Attribute %s is not allowed on %s\n",
                               cur->name, node->name);
                }
            } else if (xmlStrEqual(cur->name, BAD_CAST "type")) {
                if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "data"))) {
                    xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
                               "Attribute %s is not allowed on %s\n",
                               cur->name, node->name);
                }
            } else if (xmlStrEqual(cur->name, BAD_CAST "href")) {
                if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "include"))) {
                    xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
                               "Attribute %s is not allowed on %s\n",
                               cur->name, node->name);
                }
            } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) {
                if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&
                    (!xmlStrEqual(node->name, BAD_CAST "define"))) {
                    xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
                               "Attribute %s is not allowed on %s\n",
                               cur->name, node->name);
                }
            } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) {
                xmlChar *val;
                xmlURIPtr uri;

                val = xmlNodeListGetString(node->doc, cur->children, 1);
                if (val != NULL) {
                    if (val[0] != 0) {
                        uri = xmlParseURI((const char *) val);
                        if (uri == NULL) {
                            xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,
                                       "Attribute %s contains invalid URI %s\n",
                                       cur->name, val);
                        } else {
                            if (uri->scheme == NULL) {
                                xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,
                                           "Attribute %s URI %s is not absolute\n",
                                           cur->name, val);
                            }
                            if (uri->fragment != NULL) {
                                xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,
                                           "Attribute %s URI %s has a fragment ID\n",
                                           cur->name, val);
                            }
                            xmlFreeURI(uri);
                        }
                    }
                    xmlFree(val);
                }
            } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) {
                xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,
                           "Unknown attribute %s on %s\n", cur->name,
                           node->name);
            }
        }
        cur = next;
    }
}