예제 #1
0
        /// <summary>
        /// Determine whether an ElementCtor, AttributeCtor, or NamespaceDecl's namespace is already declared.  If it is,
        /// set the IsNamespaceInScope property to True.  Otherwise, add the namespace to the set of in-scope namespaces if
        /// addInScopeNmsp is True.  Return false if the name is computed or is invalid.
        /// </summary>
        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 = _nsmgr.NameTable.Add(prefix);
            ns     = _nsmgr.NameTable.Add(ns);

            // Determine whether namespace is already in-scope
            for (int iNmsp = 0; iNmsp < _cntNmsp; iNmsp++)
            {
                _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 || !_nsmgr.HasNamespace(prefix) || _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 (_addInScopeNmsp)
            {
                _nsmgr.AddNamespace(prefix, ns);
                _cntNmsp++;
            }

            return(true);
        }