private bool CheckNamespaceInScope(QilBinary nd) {
QilName ndName;
string prefix, ns, prefixExisting, nsExisting;
XPathNodeType nodeType;
switch (nd.NodeType) {
case QilNodeType.ElementCtor:
case QilNodeType.AttributeCtor:
ndName = nd.Left as QilName;
if (ndName != null) {
prefix = ndName.Prefix;
ns = ndName.NamespaceUri;
nodeType = (nd.NodeType == QilNodeType.ElementCtor) ? XPathNodeType.Element : XPathNodeType.Attribute;
break;
}
// Not a literal name, so return false
return false;
default:
Debug.Assert(nd.NodeType == QilNodeType.NamespaceDecl);
prefix = (string) (QilLiteral) nd.Left;
ns = (string) (QilLiteral) nd.Right;
nodeType = XPathNodeType.Namespace;
break;
}
// Attribute with null namespace and xmlns:xml are always in-scope
if (nd.NodeType == QilNodeType.AttributeCtor && ns.Length == 0 ||
prefix == "xml" && ns == XmlReservedNs.NsXml) {
XmlILConstructInfo.Write(nd).IsNamespaceInScope = true;
return true;
}
// Don't process names that are invalid
if (!ValidateNames.ValidateName(prefix, string.Empty, ns, nodeType, ValidateNames.Flags.CheckPrefixMapping))
return false;
// Atomize names
prefix = this.nsmgr.NameTable.Add(prefix);
ns = this.nsmgr.NameTable.Add(ns);
// Determine whether namespace is already in-scope
for (int iNmsp = 0; iNmsp < this.cntNmsp; iNmsp++) {
this.nsmgr.GetNamespaceDeclaration(iNmsp, out prefixExisting, out nsExisting);
// If prefix is already declared,
if ((object) prefix == (object) prefixExisting) {
// Then if the namespace is the same, this namespace is redundant
if ((object) ns == (object) nsExisting)
XmlILConstructInfo.Write(nd).IsNamespaceInScope = true;
// Else quit searching, because any further matching prefixes will be hidden (not in-scope)
Debug.Assert(nd.NodeType != QilNodeType.NamespaceDecl || !this.nsmgr.HasNamespace(prefix) || this.nsmgr.LookupNamespace(prefix) == ns,
"Compilers must ensure that namespace declarations do not conflict with the namespace used by the element constructor.");
break;
}
}
// If not in-scope, then add if it's allowed
if (this.addInScopeNmsp) {
this.nsmgr.AddNamespace(prefix, ns);
this.cntNmsp++;
}
return true;
}
}