File: System\Windows\Data\XmlNamespaceMappingCollection.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
//
// Description: Implementation of XmlNamespaceMappingCollection object.
//
// Specs:       XmlDataSource.mht
//              WCP DataSources.mht
//
 
using System.Collections; // IEnumerator
using System.Xml;
using System.Windows.Markup;
 
namespace System.Windows.Data
{
    /// <summary>
    /// XmlNamespaceMappingCollection Class
    /// Used to declare namespaces to be used in Xml data binding XPath queries
    /// </summary>
    [Localizability(LocalizationCategory.NeverLocalize)]
    public class XmlNamespaceMappingCollection : XmlNamespaceManager, ICollection<XmlNamespaceMapping>, IAddChildInternal
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public XmlNamespaceMappingCollection() : base(new NameTable())
        {}
 
#region IAddChild
 
        /// <summary>
        /// IAddChild implementation
        /// <see cref="IAddChild"/>
        /// </summary>
        /// <param name="value"></param>
        void IAddChild.AddChild(object value)
        {
            AddChild(value);
        }
 
        /// <summary>
        /// IAddChild implementation
        /// </summary>
        /// <param name="value"></param>
        protected virtual void AddChild(object value)
        {
            XmlNamespaceMapping mapping = value as XmlNamespaceMapping;
            if (mapping == null)
                throw new ArgumentException(SR.Format(SR.RequiresXmlNamespaceMapping, value.GetType().FullName), "value");
 
            Add(mapping);
        }
 
        /// <summary>
        /// IAddChild implementation
        /// </summary>
        /// <param name="text"></param>
        void IAddChild.AddText(string text)
        {
            AddText(text);
        }
 
        /// <summary>
        /// IAddChild implementation
        /// </summary>
        /// <param name="text"></param>
        protected virtual void AddText(string text)
        {
            ArgumentNullException.ThrowIfNull(text);
 
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        }
 
#endregion
 
#region ICollection<XmlNamespaceMapping>
 
        /// <summary>
        /// Add XmlNamespaceMapping
        /// </summary>
        /// <exception cref="ArgumentNullException">mapping is null</exception>
        public void Add(XmlNamespaceMapping mapping)
        {
            ArgumentNullException.ThrowIfNull(mapping);
 
            if (mapping.Uri == null)
                throw new ArgumentException(SR.RequiresXmlNamespaceMappingUri, nameof(mapping));
 
            // BUG 983685: change this to take Uri when AddNamespace is fixed to use Uri instead of String.
            // SECURITY: this workaround (passing the original string) defeats the security benefits of using Uri.
            this.AddNamespace(mapping.Prefix, mapping.Uri.OriginalString);
        }
 
        /// <summary>
        /// Remove all XmlNamespaceMappings
        /// </summary>
        /// <remarks>
        /// This is potentially an expensive operation.
        /// It may be cheaper to simply create a new XmlNamespaceMappingCollection.
        /// </remarks>
        public void Clear()
        {
            int count = Count;
            XmlNamespaceMapping[] array = new XmlNamespaceMapping[count];
            CopyTo(array, 0);
            for (int i = 0; i < count; ++i)
            {
                Remove(array[i]);
            }
        }
 
        /// <summary>
        /// Add XmlNamespaceMapping
        /// </summary>
        /// <exception cref="ArgumentNullException">mapping is null</exception>
        public bool Contains(XmlNamespaceMapping mapping)
        {
            ArgumentNullException.ThrowIfNull(mapping);
 
            if (mapping.Uri == null)
                throw new ArgumentException(SR.RequiresXmlNamespaceMappingUri, nameof(mapping));
 
            return (this.LookupNamespace(mapping.Prefix) == mapping.Uri.OriginalString);
        }
 
        /// <summary>
        /// Copy XmlNamespaceMappings to array
        /// </summary>
        public void CopyTo(XmlNamespaceMapping[] array, int arrayIndex)
        {
            ArgumentNullException.ThrowIfNull(array);
 
            int i = arrayIndex;
            int maxLength = array.Length;
            foreach (XmlNamespaceMapping mapping in this)
            {
                if (i >= maxLength)
                    throw new ArgumentException(SR.Format(SR.Collection_CopyTo_NumberOfElementsExceedsArrayLength, nameof(arrayIndex), nameof(array)));
                array[i] = mapping;
                ++ i;
            }
        }
 
        /// <summary>
        /// Remove XmlNamespaceMapping
        /// </summary>
        /// <returns>
        /// true if the mapping was removed
        /// </returns>
        /// <exception cref="ArgumentNullException">mapping is null</exception>
        public bool Remove(XmlNamespaceMapping mapping)
        {
            ArgumentNullException.ThrowIfNull(mapping);
 
            if (mapping.Uri == null)
                throw new ArgumentException(SR.RequiresXmlNamespaceMappingUri, nameof(mapping));
 
            if (Contains(mapping))
            {
                this.RemoveNamespace(mapping.Prefix, mapping.Uri.OriginalString);
                return true;
            }
            return false;
        }
 
        /// <summary>
        /// Count of the number of XmlNamespaceMappings
        /// </summary>
        public int Count
        {
            get
            {
                int count = 0;
                foreach (XmlNamespaceMapping mapping in this)
                {
                    ++ count;
                }
                return count;
            }
        }
 
        /// <summary>
        /// Value to indicate if this collection is read only
        /// </summary>
        public bool IsReadOnly
        {
            get { return false; }
        }
 
        /// <summary>
        /// IEnumerable implementation.
        /// </summary>
        /// <remarks>
        /// This enables the serializer to serialize the contents of the XmlNamespaceMappingCollection.
        /// The default namespaces (xnm, xml, and string.Empty) are not included in this enumeration.
        /// </remarks>
        public override IEnumerator GetEnumerator()
        {
            return ProtectedGetEnumerator();
        }
 
        /// <summary>
        /// IEnumerable (generic) implementation.
        /// </summary>
        IEnumerator<XmlNamespaceMapping> IEnumerable<XmlNamespaceMapping>.GetEnumerator()
        {
            return ProtectedGetEnumerator();
        }
 
        /// <summary>
        /// Protected member for use by IEnumerable implementations.
        /// </summary>
        protected IEnumerator<XmlNamespaceMapping> ProtectedGetEnumerator()
        {
            IEnumerator enumerator = BaseEnumerator;
 
            while (enumerator.MoveNext())
            {
                string prefix = (string) enumerator.Current;
                // ignore the default namespaces added automatically in the XmlNamespaceManager
                if (prefix == "xmlns" || prefix == "xml")
                    continue;
                string ns = this.LookupNamespace(prefix);
                // ignore the empty prefix if the namespace has not been reassigned
                if ((prefix == string.Empty) && (ns == string.Empty))
                    continue;
 
                Uri uri = new Uri(ns, UriKind.RelativeOrAbsolute);
                XmlNamespaceMapping xnm = new XmlNamespaceMapping(prefix, uri);
 
                yield return xnm;
            }
        }
 
        // The iterator above cannot access base.GetEnumerator directly - this
        // causes build warning 1911, and makes MoveNext throw a security
        // exception under partial trust (bug 1785518).  Accessing it indirectly
        // through this property fixes the problem.
        private IEnumerator BaseEnumerator
        {
            get { return base.GetEnumerator(); }
        }
 
#endregion ICollection<XmlNamespaceMapping>
    }
}