XmlnsDictionary.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / XmlnsDictionary.cs / 1305600 / XmlnsDictionary.cs

                            //---------------------------------------------------------------------------- 
//
// File: XmlnsDictionary.cs
//
// Description: 
//   A dictionary to control XML namespace mappings
// 
// 
// History:
//    6/06/01:    rogerg        Created 
//    5/23/03:    peterost     Ported to wcp
//    3/12/04:    chandras    Changed to add NamespaceDeclation List
//
// Copyright (C) 2001 by Microsoft Corporation.  All rights reserved. 
//
//--------------------------------------------------------------------------- 
 
using System;
using System.Xml; 
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Reflection;
using MS.Utility; 
 
#if PBTCOMPILER
namespace MS.Internal.Markup 
#else

using System.Windows;
using System.Windows.Threading; 

 
namespace System.Windows.Markup 
#endif
{ 
    /// 
    /// A dictionary to control XML prefix-Namespaceuri mappings
    /// 
#if PBTCOMPILER 
    internal class XmlnsDictionary : IDictionary
#else 
    public class XmlnsDictionary : IDictionary, System.Xaml.IXamlNamespaceResolver 
#endif
    { 
#region Public Methods
        /// 
        /// NamespaceDeclaration class which is similar to NamespaceDeclaration class in
        /// XmlNamespaceManager code in BCL. ScopeCount gets incremented and decremented 
        /// at PushScope/PopScope, and acts like a marker between Scoped Declarations.
        ///  
        struct NamespaceDeclaration 
        {
            ///  
            /// namespace prefix
            /// 
            public string Prefix;
 
            /// 
            /// xml namespace uri. 
            ///  
            public string Uri;
 
            /// 
            /// ScopeCount.  Incremented for nested scopes.
            /// 
            public int    ScopeCount; 
        }
 
        ///  
        /// Namespace Scope
        /// to retrieve all the declarations at current level or from the root node 
        /// 
        enum NamespaceScope
        {
            ///  
            /// All Namespaces from root to this Node
            ///  
            All, 

            ///  
            /// Only Namespaces at this Node
            /// 
            Local
        } 

        ///  
        /// Default constructor 
        /// 
        public XmlnsDictionary() 
        {
            // Initializes the XmlnsDictionary NamespaceDeclarations array with default 8 items
            // and initializes the last Declaration marker to zero for first insertion.
            Initialize(); 
        }
 
#if !PBTCOMPILER 
        /// 
        /// Construct an XmlnsDictionary based on an already existing one. The Sealed property is not 
        /// propagated between dictionaries.
        /// 
        /// The dictionary on which to base the new one
        public XmlnsDictionary(XmlnsDictionary xmlnsDictionary) 
        {
            if(null == xmlnsDictionary) 
            { 
                throw new ArgumentNullException( "xmlnsDictionary" );
            } 

            // Copy the Declarations if they exists
            if (xmlnsDictionary != null && xmlnsDictionary.Count > 0)
            { 
                _lastDecl = xmlnsDictionary._lastDecl;
                if (_nsDeclarations == null) 
                { 
                    _nsDeclarations = new NamespaceDeclaration[_lastDecl+1];
                } 

                // Initialize the count to Zero and start counting.
                _countDecl = 0;
 
                for (int i = 0; i <= _lastDecl; i++)
                { 
                    // We copy the entire Dictionary, but update the count only for non-null uri/ 
                    // The reason is, Count, doesn't make sense when we are implementing the
                    // storage in our own way. We don't remove the namespace declarations when 
                    // asked to remove, instead we set their uri values to null.
                    if (xmlnsDictionary._nsDeclarations[i].Uri != null)
                    {    _countDecl++;  }
 
                    _nsDeclarations[i].Prefix     = xmlnsDictionary._nsDeclarations[i].Prefix;
                    _nsDeclarations[i].Uri        = xmlnsDictionary._nsDeclarations[i].Uri; 
                    _nsDeclarations[i].ScopeCount = xmlnsDictionary._nsDeclarations[i].ScopeCount; 
                }
            } 
            else // create an empty array of Declarations. Default Size is 8.
            {
                Initialize();
            } 
        }
#endif 
 
        /// 
        /// Add a namespace to the dictionary (accepts objects for the purpose of implementing IDictionary) 
        /// 
        /// The XML prefix of this namespace (should be a string)
        /// The namespace the prefix maps to (should be a string)
        public void Add(object prefix, object xmlNamespace) 
        {
            // Check for the parameters to be strings as this is IDictionary implementation with object type params. 
            if (!(prefix is string) || !(xmlNamespace is string)) 
            {
                throw new ArgumentException(SR.Get(SRID.ParserKeysAreStrings)); 
            }
            // Add calls gets delegated to AddNamespace which adds a NamespaceDeclaration to the list of Declarations
            AddNamespace((string)prefix, (string)xmlNamespace);
         } 

#if !PBTCOMPILER 
        ///  
        /// Add a namespace to the dictionary
        ///  
        /// The XML prefix of this namespace
        /// The namespace the prefix maps to
        public void Add(string prefix,string xmlNamespace)
        { 
            // Add calls gets delegated to AddNamespace which adds a NamespaceDeclaration to the list of Declarations
            AddNamespace(prefix, xmlNamespace); 
        } 
#endif
 
        /// 
        /// Remove all entries from the dictionary
        /// 
        public void Clear() 
        {
            CheckSealed(); 
            _lastDecl = 0; 
            _countDecl = 0;
        } 

        /// 
        /// Whether the dictionary contains the specified keys
        ///  
        /// prefix to search for
        /// true if the key exists in the dictionary, false otherwise 
        public bool Contains(object key) 
        {
            return (HasNamespace((string)key)); 
        }

        /// 
        /// Removes an XML prefix from the dictionary 
        /// 
        /// The prefix to be removed 
        public void Remove(string prefix) 
        {
            string xmlNamespace = LookupNamespace(prefix); 
            RemoveNamespace(prefix, xmlNamespace);
        }

        ///  
        /// Removes an XML prefix from the dictionary
        ///  
        /// The prefix to be removed 
        public void Remove(object prefix)
        { 
            this.Remove((string)prefix);
        }

#if !PBTCOMPILER 
        /// 
        /// Copy the dictionary to an array 
        ///  
        /// The array into which to copy the table data
        /// The zero-based index in array at which copying begins 
        public void CopyTo(DictionaryEntry[] array, int index)
        {
            CopyTo((Array)array, index);
        } 
#endif
 
#region IDictionaryMethods 

        ///  
        /// IDictionary interface that returns an enumerator on the dictionary contents
        /// 
        /// Returns an enumerator on the dictionary contents
        IDictionaryEnumerator IDictionary.GetEnumerator() 
        {
            HybridDictionary namespaceTable = new HybridDictionary(_lastDecl); 
 
            for (int thisDecl = 0; thisDecl < _lastDecl;  thisDecl++)
            { 
                if (_nsDeclarations[thisDecl].Uri != null)
                {
                    namespaceTable[_nsDeclarations[thisDecl].Prefix] = _nsDeclarations[thisDecl].Uri;
                } 
            }
 
            return namespaceTable.GetEnumerator(); 
        }
 
#endregion IDictionaryMethods

#region IEnumerableMethods
 
        /// 
        /// IEnumerator interface that returns an enumerator on the dictionary contents 
        ///  
        /// Returns an enumerator on the dictionary contents
        IEnumerator IEnumerable.GetEnumerator() 
        {
            return this.GetEnumerator();
        }
 
#endregion IEnumerableMethods
 
#region ICollectionMethods 

        ///  
        /// ICollection method to copy the dictionary to an array
        /// 
        /// The array into which to copy the table data
        /// The zero-based index in array at which copying begins 
        public void CopyTo(Array array, int index)
        { 
            IDictionary dict = GetNamespacesInScope(NamespaceScope.All) as IDictionary; 
            if (dict != null)
                dict.CopyTo(array,index); 
        }

#endregion ICollectionMethods
 
#region IXamlNamespaceResolver Members
 
#if !PBTCOMPILER 
        public string GetNamespace(string prefix)
        { 
            return LookupNamespace(prefix);
        }

        public System.Collections.Generic.IEnumerable GetNamespacePrefixes() 
        {
            if (_lastDecl > 0) 
            { 
                for (int i = _lastDecl - 1; i >= 0; i--)
                { 
                    yield return new System.Xaml.NamespaceDeclaration(_nsDeclarations[i].Uri, _nsDeclarations[i].Prefix);
                }
            }
        } 
#endif
 
#endregion 

 
#if !PBTCOMPILER
        /// 
        /// IDictionary interface that returns an enumerator on the dictionary contents
        ///  
        /// Returns an enumerator on the dictionary contents
        protected IDictionaryEnumerator GetDictionaryEnumerator() 
        { 
            HybridDictionary namespaceTable = new HybridDictionary(_lastDecl);
 
            for (int thisDecl = 0; thisDecl < _lastDecl; thisDecl++)
            {
                if (_nsDeclarations[thisDecl].Uri != null)
                { 
                    namespaceTable[_nsDeclarations[thisDecl].Prefix] = _nsDeclarations[thisDecl].Uri;
                } 
            } 

            return namespaceTable.GetEnumerator(); 
        }
#endif

        ///  
        /// IEnumerator interface that returns an enumerator on the dictionary contents
        ///  
        /// Returns an enumerator on the dictionary contents 
        protected IEnumerator GetEnumerator()
        { 
            return Keys.GetEnumerator();
        }

#if !PBTCOMPILER 
        /// 
        /// Seal the dictionary so it can't be changed (this must be done before the setting the dictionary as a 
        /// dynamic property). Any attempt to modify the dictionary after this function is called will result in 
        /// a InvalidOperationException being thrown.
        ///  
        public void Seal()
        {
            _sealed = true;
        } 
#endif
 
        ///  
        /// Looks up the namespace corresponding to an XML namespace prefix
        ///  
        /// The XML namespace prefix to look up
        /// The namespace corresponding to the given prefix if it exists, null otherwise
        public string LookupNamespace(string prefix)
        { 
            if (prefix == null)
            { 
                throw new ArgumentNullException( "prefix" ); 
            }
 
            if (_lastDecl >0)
            {
                for (int thisDecl = _lastDecl-1; thisDecl >= 0; thisDecl--)
                { 
                    if ((_nsDeclarations[thisDecl].Prefix == prefix) &&
                        _nsDeclarations[thisDecl].Uri != null && 
                        _nsDeclarations[thisDecl].Uri != String.Empty) 
                    {
                        return _nsDeclarations[thisDecl].Uri; 
                    }
                }
            }
            return null; 
        }
 
#if !PBTCOMPILER 
        /// 
        /// Looks up the XML prefix corresponding to a namespaceuri 
        /// 
        /// The namespaceuri to look up
        /// 
        /// string.Empty if the given namespace corresponds to the default namespace; 
        /// otherwise, the XML prefix corresponding to the given namespace, or null
        /// if none exists. 
        ///  
        public string LookupPrefix(string xmlNamespace)
        { 
            if (xmlNamespace == null)
            {
                throw new ArgumentNullException( "xmlNamespace" );
            } 

            if (_lastDecl > 0) 
            { 
                for (int thisDecl = _lastDecl-1; thisDecl >= 0; thisDecl--)
                { 
                    if (_nsDeclarations[thisDecl].Uri == xmlNamespace)
                        return _nsDeclarations[thisDecl].Prefix;
                }
            } 
            return null;
       } 
 
        /// 
        /// DefaultNamespace for easy Access. 
        /// 
        public string DefaultNamespace()
        {
             string defaultNs = LookupNamespace(string.Empty); 
             return (defaultNs == null) ? string.Empty : defaultNs;
         } 
#endif 

        ///  
        /// Pushes the scope of the Xmlns dictionary.
        ///    when the ParserContext is entering into next level,
        ///    PushScope will get called from ParserContext.PushScope
        ///  
        public void PushScope()
        { 
            CheckSealed(); 
            _nsDeclarations[_lastDecl].ScopeCount++;
        } 

        /// 
        /// Pops the scope of the Xmlns dictionary
        ///    when the ParserContext is leaving the current level, 
        ///    PopScope will get called from ParserContext.PopScope
        ///  
        public void PopScope() 
        {
            CheckSealed(); 

            int lastScopeCount = _nsDeclarations[_lastDecl].ScopeCount;
            int decl = _lastDecl;
 
            while (decl > 0 && _nsDeclarations[decl-1].ScopeCount == lastScopeCount)
            { 
                decl--; 
            }
 
            // If we are not the first entry, we reduce the ScopeCount of
            // entry which we incremented in pushscope
            if (_nsDeclarations[decl].ScopeCount > 0)
            { 
                _nsDeclarations[decl].ScopeCount--;
                _nsDeclarations[decl].Prefix = String.Empty; 
                _nsDeclarations[decl].Uri = null; 
            }
 
            _lastDecl = decl;
        }

#endregion Public Methods 

#region Properties 
 
        /// 
        /// IDictionary property specifying whether the dictionary is fixed size (always false) 
        /// 
        public bool IsFixedSize
        {
            get { return false; } 
        }
 
        ///  
        /// IDictionary property specifying whether the dictionary is read-only
        ///  
        public bool IsReadOnly
        {
            get { return _sealed; }
        } 

        ///  
        /// A property indexing into the dictionary by XML prefix 
        /// 
        public string this[string prefix] 
        {
            get {   return LookupNamespace(prefix); }
            set {   AddNamespace(prefix, value as string);}
        } 

        ///  
        /// A property indexing into the dictionary by XML prefix (supports objects to satisfy IDictionary spec) 
        /// 
        public object this[object prefix] 
        {
            get
            {
                if (!(prefix is string)) 
                {
                    throw new ArgumentException(SR.Get(SRID.ParserKeysAreStrings)); 
                } 
                return LookupNamespace((string)prefix);
            } 
            set
            {
                if (!(prefix is string) || !(value is string))
                { 
                    throw new ArgumentException(SR.Get(SRID.ParserKeysAreStrings));
                } 
                AddNamespace((string)prefix, (string)value); 
            }
        } 

        /// 
        /// An ICollection of all keys in the dictionary
        ///  
        public ICollection Keys
        { 
            get 
            {
                // Dynamically create the keys table and return it. 
                // should be used mainly in foreach cases thru IEnumerator.
                // Indexer is provided, so this is seldom useful.
                ArrayList prefixes = new ArrayList(_lastDecl+1);
                for (int thisDecl =0; thisDecl < _lastDecl; thisDecl++) 
                {
                    // add all the Namespace Declarations whose Namespaces are not null 
                    if (_nsDeclarations[thisDecl].Uri != null) 
                    {
                        if (!prefixes.Contains(_nsDeclarations[thisDecl].Prefix)) 
                            prefixes.Add(_nsDeclarations[thisDecl].Prefix);
                    }
                }
                return prefixes; 
            }
        } 
 
        /// 
        /// An ICollection of all values in the dictionary (order of ICollection corresponds 
        /// to order of Keys)
        /// 
        public ICollection Values
        { 
            get
            { 
                HybridDictionary namespaceTable = new HybridDictionary(_lastDecl+1); 
                for (int thisDecl = 0; thisDecl < _lastDecl; thisDecl++)
                { 
                    if (_nsDeclarations[thisDecl].Uri != null)
                    {
                        namespaceTable[_nsDeclarations[thisDecl].Prefix] = _nsDeclarations[thisDecl].Uri;
                    } 
                }
                return namespaceTable.Values; 
            } 
        }
 
        /// 
        /// The number of elements in the dictionaries
        /// 
        public int Count 
        {
            get 
            { 
                return _countDecl;
            } 
        }

        /// 
        /// Whether or not access to this dictionary is thread-safe 
        /// 
        public bool IsSynchronized 
        { 
            get  {return _nsDeclarations.IsSynchronized; }
        } 

        /// 
        /// An object that can be used to synchronize access to the dictionary
        ///  
        public object SyncRoot
        { 
            get {return _nsDeclarations.SyncRoot; } 
        }
 
#if !PBTCOMPILER
        /// 
        /// Whether or not the dictionary is sealed
        ///  
        public bool Sealed
        { 
            get { return _sealed; } 
        }
#endif 

#endregion Properties

#if !PBTCOMPILER 
#region Internal
        // Unseal the dictionary internally 
        internal void Unseal() 
        {
            _sealed = false; 
        }
 #endregion Internal
 #endif
 
#region Private
        private void Initialize() 
        { 
            // We set the initial array to 8 and double from there when we run of the space.
            // For the start case, we set the DefaultNamespaceuri to null. 
            _nsDeclarations = new NamespaceDeclaration[8];
            _nsDeclarations[0].Prefix = string.Empty;
            _nsDeclarations[0].Uri = null;
            _nsDeclarations[0].ScopeCount = 0; 
            _lastDecl = 0;
            _countDecl = 0; 
       } 

       private void CheckSealed() 
        {
            if (IsReadOnly)
            {
                throw new InvalidOperationException(SR.Get(SRID.ParserDictionarySealed)); 
            }
        } 
 
        /// 
        /// Helper to Add Namespace - Checks for prefix from rear. 
        ///  If exists : override it locally, if not Adds an entry.
        /// 
        /// prefix to add
        /// namespace uri string to add 
        private void AddNamespace(string prefix, string xmlNamespace)
        { 
            CheckSealed(); 

            if (xmlNamespace == null) 
                throw new ArgumentNullException("xmlNamespace");

            if (prefix == null)
                throw new ArgumentNullException("prefix"); 

            int lastScopeCount = _nsDeclarations[_lastDecl].ScopeCount; 
 
            if (_lastDecl > 0)
            { 
                // Check the local scope for the given prefix
                for (int thisDecl = _lastDecl-1;
                     thisDecl >= 0 && _nsDeclarations[thisDecl].ScopeCount == lastScopeCount;
                     thisDecl--) 
                {
                    if (String.Equals(_nsDeclarations[thisDecl].Prefix, prefix)) 
                    { 
                        // Redefine an existing namespace
                        _nsDeclarations[thisDecl].Uri = xmlNamespace; 
                        return;
                    }
                }
 
                // Running out of Array Capacity, allocate more and copy the contents.
                if (_lastDecl == _nsDeclarations.Length - 1) 
                { 
                    NamespaceDeclaration[] new_nsDeclarations = new NamespaceDeclaration[_nsDeclarations.Length * 2];
 
                    Array.Copy(_nsDeclarations, 0, new_nsDeclarations, 0, _nsDeclarations.Length);
                    _nsDeclarations = new_nsDeclarations;
                }
            } 

             _countDecl++; 
            _nsDeclarations[_lastDecl].Prefix = prefix; 
            _nsDeclarations[_lastDecl].Uri = xmlNamespace;
            _lastDecl++; 
            _nsDeclarations[_lastDecl].ScopeCount = lastScopeCount;
        }

        // Removing the namespace given prefix and xmlNamespace. 
        // We need prefix and xmlNamespace, inorder to remove the correct entry.
        // Walking from the LastDecl to first entry in the list to zero 
        // and removing the right entry which matches both. 
        private void RemoveNamespace(string prefix, string xmlNamespace)
        { 
            CheckSealed();
            if (_lastDecl > 0)
            {
                if (xmlNamespace == null) 
                {
                    throw new ArgumentNullException("xmlNamespace"); 
                } 

                if (prefix == null) 
                {
                    throw new ArgumentNullException("prefix");
                }
 
               int lastScopeCount = _nsDeclarations[_lastDecl-1].ScopeCount;
               for (int thisDecl = _lastDecl-1; 
                     thisDecl >= 0 && _nsDeclarations[thisDecl].ScopeCount == lastScopeCount; 
                     thisDecl--)
                { 
                    if ((_nsDeclarations[thisDecl].Prefix == prefix) && (_nsDeclarations[thisDecl].Uri == xmlNamespace))
                    {
                        _nsDeclarations[thisDecl].Uri = null;
                        _countDecl--; 
                    }
                } 
            } 
        }
 
        // Get all namespaces in the local or scope from the last parent
        private  IDictionary GetNamespacesInScope(NamespaceScope scope)
        {
            int i = 0; 

            switch (scope) 
            { 
                case NamespaceScope.All:
                    i = 0; 
                    break;

                case NamespaceScope.Local:
                    i = _lastDecl; 
                    int lastScopeCount = _nsDeclarations[i].ScopeCount;
                    while (_nsDeclarations[i].ScopeCount == lastScopeCount) 
                        i--; 
                    i++;
                    break; 
            }

            HybridDictionary dict = new HybridDictionary(_lastDecl -i + 1);
 
            for (; i < _lastDecl; i++)
            { 
                string prefix = _nsDeclarations[i].Prefix; 
                string xmlNamespace    = _nsDeclarations[i].Uri;
 
                Debug.Assert(prefix != null);
                if (xmlNamespace.Length > 0 || prefix.Length > 0)
                {
                    dict[prefix] = xmlNamespace; 
                }
                else 
                { 
                    // default namespace redeclared to "" -> remove from list
                    dict.Remove(prefix); 
                }
            }

            return dict; 
        }
 
        // Utility method to find whether a prefix has namespace associated. 
        private bool HasNamespace(string prefix)
        { 
            if (_lastDecl > 0)
            {
                for (int thisDecl = _lastDecl-1;
                     thisDecl >= 0; 
                     thisDecl--)
                { 
                    if ( (_nsDeclarations[thisDecl].Prefix == prefix) && _nsDeclarations[thisDecl].Uri != null) 
                    {
                        if (prefix.Length > 0 || _nsDeclarations[thisDecl].Uri.Length > 0) 
                        {
                            return true;
                        }
                        return false; 
                    }
                } 
            } 

            return false; 
        }

#endregion Private
 
#region Private Data
        ///  
        /// Namespace Declarations Array. Used to Index Namespaces within Context. 
        /// 
        private NamespaceDeclaration[] _nsDeclarations; 

        /// 
        /// Namespace Declarations Rear Index, where we do additions and deletions, also
        /// this is the index from which we start lookup for namespaces. 
        /// 
        private int   _lastDecl = 0; 
 
        /// 
        /// Namespace Declarations Rear Index, where we do additions and deletions, also 
        /// this is the index from which we start lookup for namespaces.
        /// 
        private int _countDecl = 0;
 
        /// 
        /// Seals the Current Dictionary from further updating it. 
        ///  
        private bool _sealed = false;       // True if dictionary is immutable.
#endregion Private Data 

    } //XmlNamespaceManager
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// File: XmlnsDictionary.cs
//
// Description: 
//   A dictionary to control XML namespace mappings
// 
// 
// History:
//    6/06/01:    rogerg        Created 
//    5/23/03:    peterost     Ported to wcp
//    3/12/04:    chandras    Changed to add NamespaceDeclation List
//
// Copyright (C) 2001 by Microsoft Corporation.  All rights reserved. 
//
//--------------------------------------------------------------------------- 
 
using System;
using System.Xml; 
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Reflection;
using MS.Utility; 
 
#if PBTCOMPILER
namespace MS.Internal.Markup 
#else

using System.Windows;
using System.Windows.Threading; 

 
namespace System.Windows.Markup 
#endif
{ 
    /// 
    /// A dictionary to control XML prefix-Namespaceuri mappings
    /// 
#if PBTCOMPILER 
    internal class XmlnsDictionary : IDictionary
#else 
    public class XmlnsDictionary : IDictionary, System.Xaml.IXamlNamespaceResolver 
#endif
    { 
#region Public Methods
        /// 
        /// NamespaceDeclaration class which is similar to NamespaceDeclaration class in
        /// XmlNamespaceManager code in BCL. ScopeCount gets incremented and decremented 
        /// at PushScope/PopScope, and acts like a marker between Scoped Declarations.
        ///  
        struct NamespaceDeclaration 
        {
            ///  
            /// namespace prefix
            /// 
            public string Prefix;
 
            /// 
            /// xml namespace uri. 
            ///  
            public string Uri;
 
            /// 
            /// ScopeCount.  Incremented for nested scopes.
            /// 
            public int    ScopeCount; 
        }
 
        ///  
        /// Namespace Scope
        /// to retrieve all the declarations at current level or from the root node 
        /// 
        enum NamespaceScope
        {
            ///  
            /// All Namespaces from root to this Node
            ///  
            All, 

            ///  
            /// Only Namespaces at this Node
            /// 
            Local
        } 

        ///  
        /// Default constructor 
        /// 
        public XmlnsDictionary() 
        {
            // Initializes the XmlnsDictionary NamespaceDeclarations array with default 8 items
            // and initializes the last Declaration marker to zero for first insertion.
            Initialize(); 
        }
 
#if !PBTCOMPILER 
        /// 
        /// Construct an XmlnsDictionary based on an already existing one. The Sealed property is not 
        /// propagated between dictionaries.
        /// 
        /// The dictionary on which to base the new one
        public XmlnsDictionary(XmlnsDictionary xmlnsDictionary) 
        {
            if(null == xmlnsDictionary) 
            { 
                throw new ArgumentNullException( "xmlnsDictionary" );
            } 

            // Copy the Declarations if they exists
            if (xmlnsDictionary != null && xmlnsDictionary.Count > 0)
            { 
                _lastDecl = xmlnsDictionary._lastDecl;
                if (_nsDeclarations == null) 
                { 
                    _nsDeclarations = new NamespaceDeclaration[_lastDecl+1];
                } 

                // Initialize the count to Zero and start counting.
                _countDecl = 0;
 
                for (int i = 0; i <= _lastDecl; i++)
                { 
                    // We copy the entire Dictionary, but update the count only for non-null uri/ 
                    // The reason is, Count, doesn't make sense when we are implementing the
                    // storage in our own way. We don't remove the namespace declarations when 
                    // asked to remove, instead we set their uri values to null.
                    if (xmlnsDictionary._nsDeclarations[i].Uri != null)
                    {    _countDecl++;  }
 
                    _nsDeclarations[i].Prefix     = xmlnsDictionary._nsDeclarations[i].Prefix;
                    _nsDeclarations[i].Uri        = xmlnsDictionary._nsDeclarations[i].Uri; 
                    _nsDeclarations[i].ScopeCount = xmlnsDictionary._nsDeclarations[i].ScopeCount; 
                }
            } 
            else // create an empty array of Declarations. Default Size is 8.
            {
                Initialize();
            } 
        }
#endif 
 
        /// 
        /// Add a namespace to the dictionary (accepts objects for the purpose of implementing IDictionary) 
        /// 
        /// The XML prefix of this namespace (should be a string)
        /// The namespace the prefix maps to (should be a string)
        public void Add(object prefix, object xmlNamespace) 
        {
            // Check for the parameters to be strings as this is IDictionary implementation with object type params. 
            if (!(prefix is string) || !(xmlNamespace is string)) 
            {
                throw new ArgumentException(SR.Get(SRID.ParserKeysAreStrings)); 
            }
            // Add calls gets delegated to AddNamespace which adds a NamespaceDeclaration to the list of Declarations
            AddNamespace((string)prefix, (string)xmlNamespace);
         } 

#if !PBTCOMPILER 
        ///  
        /// Add a namespace to the dictionary
        ///  
        /// The XML prefix of this namespace
        /// The namespace the prefix maps to
        public void Add(string prefix,string xmlNamespace)
        { 
            // Add calls gets delegated to AddNamespace which adds a NamespaceDeclaration to the list of Declarations
            AddNamespace(prefix, xmlNamespace); 
        } 
#endif
 
        /// 
        /// Remove all entries from the dictionary
        /// 
        public void Clear() 
        {
            CheckSealed(); 
            _lastDecl = 0; 
            _countDecl = 0;
        } 

        /// 
        /// Whether the dictionary contains the specified keys
        ///  
        /// prefix to search for
        /// true if the key exists in the dictionary, false otherwise 
        public bool Contains(object key) 
        {
            return (HasNamespace((string)key)); 
        }

        /// 
        /// Removes an XML prefix from the dictionary 
        /// 
        /// The prefix to be removed 
        public void Remove(string prefix) 
        {
            string xmlNamespace = LookupNamespace(prefix); 
            RemoveNamespace(prefix, xmlNamespace);
        }

        ///  
        /// Removes an XML prefix from the dictionary
        ///  
        /// The prefix to be removed 
        public void Remove(object prefix)
        { 
            this.Remove((string)prefix);
        }

#if !PBTCOMPILER 
        /// 
        /// Copy the dictionary to an array 
        ///  
        /// The array into which to copy the table data
        /// The zero-based index in array at which copying begins 
        public void CopyTo(DictionaryEntry[] array, int index)
        {
            CopyTo((Array)array, index);
        } 
#endif
 
#region IDictionaryMethods 

        ///  
        /// IDictionary interface that returns an enumerator on the dictionary contents
        /// 
        /// Returns an enumerator on the dictionary contents
        IDictionaryEnumerator IDictionary.GetEnumerator() 
        {
            HybridDictionary namespaceTable = new HybridDictionary(_lastDecl); 
 
            for (int thisDecl = 0; thisDecl < _lastDecl;  thisDecl++)
            { 
                if (_nsDeclarations[thisDecl].Uri != null)
                {
                    namespaceTable[_nsDeclarations[thisDecl].Prefix] = _nsDeclarations[thisDecl].Uri;
                } 
            }
 
            return namespaceTable.GetEnumerator(); 
        }
 
#endregion IDictionaryMethods

#region IEnumerableMethods
 
        /// 
        /// IEnumerator interface that returns an enumerator on the dictionary contents 
        ///  
        /// Returns an enumerator on the dictionary contents
        IEnumerator IEnumerable.GetEnumerator() 
        {
            return this.GetEnumerator();
        }
 
#endregion IEnumerableMethods
 
#region ICollectionMethods 

        ///  
        /// ICollection method to copy the dictionary to an array
        /// 
        /// The array into which to copy the table data
        /// The zero-based index in array at which copying begins 
        public void CopyTo(Array array, int index)
        { 
            IDictionary dict = GetNamespacesInScope(NamespaceScope.All) as IDictionary; 
            if (dict != null)
                dict.CopyTo(array,index); 
        }

#endregion ICollectionMethods
 
#region IXamlNamespaceResolver Members
 
#if !PBTCOMPILER 
        public string GetNamespace(string prefix)
        { 
            return LookupNamespace(prefix);
        }

        public System.Collections.Generic.IEnumerable GetNamespacePrefixes() 
        {
            if (_lastDecl > 0) 
            { 
                for (int i = _lastDecl - 1; i >= 0; i--)
                { 
                    yield return new System.Xaml.NamespaceDeclaration(_nsDeclarations[i].Uri, _nsDeclarations[i].Prefix);
                }
            }
        } 
#endif
 
#endregion 

 
#if !PBTCOMPILER
        /// 
        /// IDictionary interface that returns an enumerator on the dictionary contents
        ///  
        /// Returns an enumerator on the dictionary contents
        protected IDictionaryEnumerator GetDictionaryEnumerator() 
        { 
            HybridDictionary namespaceTable = new HybridDictionary(_lastDecl);
 
            for (int thisDecl = 0; thisDecl < _lastDecl; thisDecl++)
            {
                if (_nsDeclarations[thisDecl].Uri != null)
                { 
                    namespaceTable[_nsDeclarations[thisDecl].Prefix] = _nsDeclarations[thisDecl].Uri;
                } 
            } 

            return namespaceTable.GetEnumerator(); 
        }
#endif

        ///  
        /// IEnumerator interface that returns an enumerator on the dictionary contents
        ///  
        /// Returns an enumerator on the dictionary contents 
        protected IEnumerator GetEnumerator()
        { 
            return Keys.GetEnumerator();
        }

#if !PBTCOMPILER 
        /// 
        /// Seal the dictionary so it can't be changed (this must be done before the setting the dictionary as a 
        /// dynamic property). Any attempt to modify the dictionary after this function is called will result in 
        /// a InvalidOperationException being thrown.
        ///  
        public void Seal()
        {
            _sealed = true;
        } 
#endif
 
        ///  
        /// Looks up the namespace corresponding to an XML namespace prefix
        ///  
        /// The XML namespace prefix to look up
        /// The namespace corresponding to the given prefix if it exists, null otherwise
        public string LookupNamespace(string prefix)
        { 
            if (prefix == null)
            { 
                throw new ArgumentNullException( "prefix" ); 
            }
 
            if (_lastDecl >0)
            {
                for (int thisDecl = _lastDecl-1; thisDecl >= 0; thisDecl--)
                { 
                    if ((_nsDeclarations[thisDecl].Prefix == prefix) &&
                        _nsDeclarations[thisDecl].Uri != null && 
                        _nsDeclarations[thisDecl].Uri != String.Empty) 
                    {
                        return _nsDeclarations[thisDecl].Uri; 
                    }
                }
            }
            return null; 
        }
 
#if !PBTCOMPILER 
        /// 
        /// Looks up the XML prefix corresponding to a namespaceuri 
        /// 
        /// The namespaceuri to look up
        /// 
        /// string.Empty if the given namespace corresponds to the default namespace; 
        /// otherwise, the XML prefix corresponding to the given namespace, or null
        /// if none exists. 
        ///  
        public string LookupPrefix(string xmlNamespace)
        { 
            if (xmlNamespace == null)
            {
                throw new ArgumentNullException( "xmlNamespace" );
            } 

            if (_lastDecl > 0) 
            { 
                for (int thisDecl = _lastDecl-1; thisDecl >= 0; thisDecl--)
                { 
                    if (_nsDeclarations[thisDecl].Uri == xmlNamespace)
                        return _nsDeclarations[thisDecl].Prefix;
                }
            } 
            return null;
       } 
 
        /// 
        /// DefaultNamespace for easy Access. 
        /// 
        public string DefaultNamespace()
        {
             string defaultNs = LookupNamespace(string.Empty); 
             return (defaultNs == null) ? string.Empty : defaultNs;
         } 
#endif 

        ///  
        /// Pushes the scope of the Xmlns dictionary.
        ///    when the ParserContext is entering into next level,
        ///    PushScope will get called from ParserContext.PushScope
        ///  
        public void PushScope()
        { 
            CheckSealed(); 
            _nsDeclarations[_lastDecl].ScopeCount++;
        } 

        /// 
        /// Pops the scope of the Xmlns dictionary
        ///    when the ParserContext is leaving the current level, 
        ///    PopScope will get called from ParserContext.PopScope
        ///  
        public void PopScope() 
        {
            CheckSealed(); 

            int lastScopeCount = _nsDeclarations[_lastDecl].ScopeCount;
            int decl = _lastDecl;
 
            while (decl > 0 && _nsDeclarations[decl-1].ScopeCount == lastScopeCount)
            { 
                decl--; 
            }
 
            // If we are not the first entry, we reduce the ScopeCount of
            // entry which we incremented in pushscope
            if (_nsDeclarations[decl].ScopeCount > 0)
            { 
                _nsDeclarations[decl].ScopeCount--;
                _nsDeclarations[decl].Prefix = String.Empty; 
                _nsDeclarations[decl].Uri = null; 
            }
 
            _lastDecl = decl;
        }

#endregion Public Methods 

#region Properties 
 
        /// 
        /// IDictionary property specifying whether the dictionary is fixed size (always false) 
        /// 
        public bool IsFixedSize
        {
            get { return false; } 
        }
 
        ///  
        /// IDictionary property specifying whether the dictionary is read-only
        ///  
        public bool IsReadOnly
        {
            get { return _sealed; }
        } 

        ///  
        /// A property indexing into the dictionary by XML prefix 
        /// 
        public string this[string prefix] 
        {
            get {   return LookupNamespace(prefix); }
            set {   AddNamespace(prefix, value as string);}
        } 

        ///  
        /// A property indexing into the dictionary by XML prefix (supports objects to satisfy IDictionary spec) 
        /// 
        public object this[object prefix] 
        {
            get
            {
                if (!(prefix is string)) 
                {
                    throw new ArgumentException(SR.Get(SRID.ParserKeysAreStrings)); 
                } 
                return LookupNamespace((string)prefix);
            } 
            set
            {
                if (!(prefix is string) || !(value is string))
                { 
                    throw new ArgumentException(SR.Get(SRID.ParserKeysAreStrings));
                } 
                AddNamespace((string)prefix, (string)value); 
            }
        } 

        /// 
        /// An ICollection of all keys in the dictionary
        ///  
        public ICollection Keys
        { 
            get 
            {
                // Dynamically create the keys table and return it. 
                // should be used mainly in foreach cases thru IEnumerator.
                // Indexer is provided, so this is seldom useful.
                ArrayList prefixes = new ArrayList(_lastDecl+1);
                for (int thisDecl =0; thisDecl < _lastDecl; thisDecl++) 
                {
                    // add all the Namespace Declarations whose Namespaces are not null 
                    if (_nsDeclarations[thisDecl].Uri != null) 
                    {
                        if (!prefixes.Contains(_nsDeclarations[thisDecl].Prefix)) 
                            prefixes.Add(_nsDeclarations[thisDecl].Prefix);
                    }
                }
                return prefixes; 
            }
        } 
 
        /// 
        /// An ICollection of all values in the dictionary (order of ICollection corresponds 
        /// to order of Keys)
        /// 
        public ICollection Values
        { 
            get
            { 
                HybridDictionary namespaceTable = new HybridDictionary(_lastDecl+1); 
                for (int thisDecl = 0; thisDecl < _lastDecl; thisDecl++)
                { 
                    if (_nsDeclarations[thisDecl].Uri != null)
                    {
                        namespaceTable[_nsDeclarations[thisDecl].Prefix] = _nsDeclarations[thisDecl].Uri;
                    } 
                }
                return namespaceTable.Values; 
            } 
        }
 
        /// 
        /// The number of elements in the dictionaries
        /// 
        public int Count 
        {
            get 
            { 
                return _countDecl;
            } 
        }

        /// 
        /// Whether or not access to this dictionary is thread-safe 
        /// 
        public bool IsSynchronized 
        { 
            get  {return _nsDeclarations.IsSynchronized; }
        } 

        /// 
        /// An object that can be used to synchronize access to the dictionary
        ///  
        public object SyncRoot
        { 
            get {return _nsDeclarations.SyncRoot; } 
        }
 
#if !PBTCOMPILER
        /// 
        /// Whether or not the dictionary is sealed
        ///  
        public bool Sealed
        { 
            get { return _sealed; } 
        }
#endif 

#endregion Properties

#if !PBTCOMPILER 
#region Internal
        // Unseal the dictionary internally 
        internal void Unseal() 
        {
            _sealed = false; 
        }
 #endregion Internal
 #endif
 
#region Private
        private void Initialize() 
        { 
            // We set the initial array to 8 and double from there when we run of the space.
            // For the start case, we set the DefaultNamespaceuri to null. 
            _nsDeclarations = new NamespaceDeclaration[8];
            _nsDeclarations[0].Prefix = string.Empty;
            _nsDeclarations[0].Uri = null;
            _nsDeclarations[0].ScopeCount = 0; 
            _lastDecl = 0;
            _countDecl = 0; 
       } 

       private void CheckSealed() 
        {
            if (IsReadOnly)
            {
                throw new InvalidOperationException(SR.Get(SRID.ParserDictionarySealed)); 
            }
        } 
 
        /// 
        /// Helper to Add Namespace - Checks for prefix from rear. 
        ///  If exists : override it locally, if not Adds an entry.
        /// 
        /// prefix to add
        /// namespace uri string to add 
        private void AddNamespace(string prefix, string xmlNamespace)
        { 
            CheckSealed(); 

            if (xmlNamespace == null) 
                throw new ArgumentNullException("xmlNamespace");

            if (prefix == null)
                throw new ArgumentNullException("prefix"); 

            int lastScopeCount = _nsDeclarations[_lastDecl].ScopeCount; 
 
            if (_lastDecl > 0)
            { 
                // Check the local scope for the given prefix
                for (int thisDecl = _lastDecl-1;
                     thisDecl >= 0 && _nsDeclarations[thisDecl].ScopeCount == lastScopeCount;
                     thisDecl--) 
                {
                    if (String.Equals(_nsDeclarations[thisDecl].Prefix, prefix)) 
                    { 
                        // Redefine an existing namespace
                        _nsDeclarations[thisDecl].Uri = xmlNamespace; 
                        return;
                    }
                }
 
                // Running out of Array Capacity, allocate more and copy the contents.
                if (_lastDecl == _nsDeclarations.Length - 1) 
                { 
                    NamespaceDeclaration[] new_nsDeclarations = new NamespaceDeclaration[_nsDeclarations.Length * 2];
 
                    Array.Copy(_nsDeclarations, 0, new_nsDeclarations, 0, _nsDeclarations.Length);
                    _nsDeclarations = new_nsDeclarations;
                }
            } 

             _countDecl++; 
            _nsDeclarations[_lastDecl].Prefix = prefix; 
            _nsDeclarations[_lastDecl].Uri = xmlNamespace;
            _lastDecl++; 
            _nsDeclarations[_lastDecl].ScopeCount = lastScopeCount;
        }

        // Removing the namespace given prefix and xmlNamespace. 
        // We need prefix and xmlNamespace, inorder to remove the correct entry.
        // Walking from the LastDecl to first entry in the list to zero 
        // and removing the right entry which matches both. 
        private void RemoveNamespace(string prefix, string xmlNamespace)
        { 
            CheckSealed();
            if (_lastDecl > 0)
            {
                if (xmlNamespace == null) 
                {
                    throw new ArgumentNullException("xmlNamespace"); 
                } 

                if (prefix == null) 
                {
                    throw new ArgumentNullException("prefix");
                }
 
               int lastScopeCount = _nsDeclarations[_lastDecl-1].ScopeCount;
               for (int thisDecl = _lastDecl-1; 
                     thisDecl >= 0 && _nsDeclarations[thisDecl].ScopeCount == lastScopeCount; 
                     thisDecl--)
                { 
                    if ((_nsDeclarations[thisDecl].Prefix == prefix) && (_nsDeclarations[thisDecl].Uri == xmlNamespace))
                    {
                        _nsDeclarations[thisDecl].Uri = null;
                        _countDecl--; 
                    }
                } 
            } 
        }
 
        // Get all namespaces in the local or scope from the last parent
        private  IDictionary GetNamespacesInScope(NamespaceScope scope)
        {
            int i = 0; 

            switch (scope) 
            { 
                case NamespaceScope.All:
                    i = 0; 
                    break;

                case NamespaceScope.Local:
                    i = _lastDecl; 
                    int lastScopeCount = _nsDeclarations[i].ScopeCount;
                    while (_nsDeclarations[i].ScopeCount == lastScopeCount) 
                        i--; 
                    i++;
                    break; 
            }

            HybridDictionary dict = new HybridDictionary(_lastDecl -i + 1);
 
            for (; i < _lastDecl; i++)
            { 
                string prefix = _nsDeclarations[i].Prefix; 
                string xmlNamespace    = _nsDeclarations[i].Uri;
 
                Debug.Assert(prefix != null);
                if (xmlNamespace.Length > 0 || prefix.Length > 0)
                {
                    dict[prefix] = xmlNamespace; 
                }
                else 
                { 
                    // default namespace redeclared to "" -> remove from list
                    dict.Remove(prefix); 
                }
            }

            return dict; 
        }
 
        // Utility method to find whether a prefix has namespace associated. 
        private bool HasNamespace(string prefix)
        { 
            if (_lastDecl > 0)
            {
                for (int thisDecl = _lastDecl-1;
                     thisDecl >= 0; 
                     thisDecl--)
                { 
                    if ( (_nsDeclarations[thisDecl].Prefix == prefix) && _nsDeclarations[thisDecl].Uri != null) 
                    {
                        if (prefix.Length > 0 || _nsDeclarations[thisDecl].Uri.Length > 0) 
                        {
                            return true;
                        }
                        return false; 
                    }
                } 
            } 

            return false; 
        }

#endregion Private
 
#region Private Data
        ///  
        /// Namespace Declarations Array. Used to Index Namespaces within Context. 
        /// 
        private NamespaceDeclaration[] _nsDeclarations; 

        /// 
        /// Namespace Declarations Rear Index, where we do additions and deletions, also
        /// this is the index from which we start lookup for namespaces. 
        /// 
        private int   _lastDecl = 0; 
 
        /// 
        /// Namespace Declarations Rear Index, where we do additions and deletions, also 
        /// this is the index from which we start lookup for namespaces.
        /// 
        private int _countDecl = 0;
 
        /// 
        /// Seals the Current Dictionary from further updating it. 
        ///  
        private bool _sealed = false;       // True if dictionary is immutable.
#endregion Private Data 

    } //XmlNamespaceManager
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK