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(SR.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(SR.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(SR.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(SR.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(SR.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(SR.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(SR.Xml_XmlPrefix, string.Empty);
return false;
}
}
else if (prefix.Equals("xmlns"))
{
// Prefix may never be 'xmlns'
if (throwOnError) throw new XmlException(SR.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(SR.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(SR.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(SR.XmlNoNameAllowed, nodeKind.ToString());
return false;
}
break;
}
}
return true;
}