private static bool ValidateNameInternal()

in src/Shared/Compat/ValidateNames.cs [477:592]


        private static bool ValidateNameInternal(string prefix, string localName, string ns, XPathNodeType nodeKind, Flags flags, bool throwOnError) {
            Debug.Assert(prefix != null && localName != null && ns != null);

            if ((flags & Flags.NCNames) != 0) {

                // 1. Verify that each non-empty prefix and localName is a valid NCName
                if (prefix.Length != 0)
                    if (!ParseNCNameInternal(prefix, throwOnError)) {
                        return false;
                    }

                if (localName.Length != 0)
                    if (!ParseNCNameInternal(localName, throwOnError)) {
                        return false;
                    }
            }

            if ((flags & Flags.CheckLocalName) != 0) {

                // 2. Determine whether the local name is valid
                switch (nodeKind) {
                    case XPathNodeType.Element:
                        // Elements and attributes must have a non-empty local name
                        if (localName.Length == 0) {
                            if (throwOnError) throw new XmlException(Res.Xdom_Empty_LocalName, string.Empty);
                            return false;
                        }
                        break;

                    case XPathNodeType.Attribute:
                        // Attribute local name cannot be "xmlns" if namespace is empty
                        if (ns.Length == 0 && localName.Equals("xmlns")) {
                            if (throwOnError) throw new XmlException(Res.XmlBadName, new string[] {nodeKind.ToString(), localName});
                            return false;
                        }
                        goto case XPathNodeType.Element;

                    case XPathNodeType.ProcessingInstruction:
                        // PI's local-name must be non-empty and cannot be 'xml' (case-insensitive)
                        if (localName.Length == 0 || (localName.Length == 3 && StartsWithXml(localName))) {
                            if (throwOnError) throw new XmlException(Res.Xml_InvalidPIName, localName);
                            return false;
                        }
                        break;

                    default:
                        // All other node types must have empty local-name
                        if (localName.Length != 0) {
                            if (throwOnError) throw new XmlException(Res.XmlNoNameAllowed, nodeKind.ToString());
                            return false;
                        }
                        break;
                }
            }

            if ((flags & Flags.CheckPrefixMapping) != 0) {

                // 3. Determine whether the prefix is valid
                switch (nodeKind) {
                    case XPathNodeType.Element:
                    case XPathNodeType.Attribute:
                    case XPathNodeType.Namespace:
                        if (ns.Length == 0) {
                            // If namespace is empty, then prefix must be empty
                            if (prefix.Length != 0) {
                                if (throwOnError) throw new XmlException(Res.Xml_PrefixForEmptyNs, string.Empty);
                                return false;
                            }
                        }
                        else {
                            // Don't allow empty attribute prefix since namespace is non-empty
                            if (prefix.Length == 0 && nodeKind == XPathNodeType.Attribute) {
                                if (throwOnError) throw new XmlException(Res.XmlBadName, new string[] {nodeKind.ToString(), localName});
                                return false;
                            }

                            if (prefix.Equals("xml")) {
                                // xml prefix must be mapped to the xml namespace
                                if (!ns.Equals(XmlReservedNs.NsXml)) {
                                    if (throwOnError) throw new XmlException(Res.Xml_XmlPrefix, string.Empty);
                                    return false;
                                }
                            }
                            else if (prefix.Equals("xmlns")) {
                                // Prefix may never be 'xmlns'
                                if (throwOnError) throw new XmlException(Res.Xml_XmlnsPrefix, string.Empty);
                                return false;
                            }
                            else if (IsReservedNamespace(ns)) {
                                // Don't allow non-reserved prefixes to map to xml or xmlns namespaces
                                if (throwOnError) throw new XmlException(Res.Xml_NamespaceDeclXmlXmlns, string.Empty);
                                return false;
                            }
                        }
                        break;

                    case XPathNodeType.ProcessingInstruction:
                        // PI's prefix and namespace must be empty
                        if (prefix.Length != 0 || ns.Length != 0) {
                            if (throwOnError) throw new XmlException(Res.Xml_InvalidPIName, CreateName(prefix, localName));
                            return false;
                        }
                        break;

                    default:
                        // All other node types must have empty prefix and namespace
                        if (prefix.Length != 0 || ns.Length != 0) {
                            if (throwOnError) throw new XmlException(Res.XmlNoNameAllowed, nodeKind.ToString());
                            return false;
                        }
                        break;
                }
            }

            return true;
        }