File: System\Xml\Dom\XmlNamedNodemap.cs
Web Access
Project: src\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections;
 
namespace System.Xml
{
    // Represents a collection of nodes that can be accessed by name or index.
    public partial class XmlNamedNodeMap : IEnumerable
    {
        internal XmlNode parent;
        internal SmallXmlNodeList nodes;
 
        internal XmlNamedNodeMap(XmlNode parent)
        {
            this.parent = parent;
        }
 
        // Retrieves a XmlNode specified by name.
        public virtual XmlNode? GetNamedItem(string name)
        {
            int offset = FindNodeOffset(name);
            if (offset >= 0)
                return (XmlNode)nodes[offset];
 
            return null;
        }
 
        // Adds a XmlNode using its Name property
        public virtual XmlNode? SetNamedItem(XmlNode? node)
        {
            if (node == null)
                return null;
 
            int offset = FindNodeOffset(node.LocalName, node.NamespaceURI);
            if (offset == -1)
            {
                AddNode(node);
                return null;
            }
            else
            {
                return ReplaceNodeAt(offset, node);
            }
        }
 
        // Removes the node specified by name.
        public virtual XmlNode? RemoveNamedItem(string name)
        {
            int offset = FindNodeOffset(name);
            if (offset >= 0)
            {
                return RemoveNodeAt(offset);
            }
 
            return null;
        }
 
        // Gets the number of nodes in this XmlNamedNodeMap.
        public virtual int Count
        {
            get
            {
                return nodes.Count;
            }
        }
 
        // Retrieves the node at the specified index in this XmlNamedNodeMap.
        public virtual XmlNode? Item(int index)
        {
            if (index < 0 || index >= nodes.Count)
                return null;
            try
            {
                return (XmlNode)nodes[index];
            }
            catch (ArgumentOutOfRangeException)
            {
                throw new IndexOutOfRangeException(SR.Xdom_IndexOutOfRange);
            }
        }
 
        //
        // DOM Level 2
        //
 
        // Retrieves a node specified by LocalName and NamespaceURI.
        public virtual XmlNode? GetNamedItem(string localName, string? namespaceURI)
        {
            int offset = FindNodeOffset(localName, namespaceURI);
            if (offset >= 0)
                return (XmlNode)nodes[offset];
 
            return null;
        }
 
        // Removes a node specified by local name and namespace URI.
        public virtual XmlNode? RemoveNamedItem(string localName, string? namespaceURI)
        {
            int offset = FindNodeOffset(localName, namespaceURI);
            if (offset >= 0)
            {
                return RemoveNodeAt(offset);
            }
 
            return null;
        }
 
        public virtual IEnumerator GetEnumerator()
        {
            return nodes.GetEnumerator();
        }
 
        internal int FindNodeOffset(string name)
        {
            int c = this.Count;
            for (int i = 0; i < c; i++)
            {
                XmlNode node = (XmlNode)nodes[i];
 
                if (name == node.Name)
                    return i;
            }
 
            return -1;
        }
 
        internal int FindNodeOffset(string localName, string? namespaceURI)
        {
            int c = this.Count;
            for (int i = 0; i < c; i++)
            {
                XmlNode node = (XmlNode)nodes[i];
 
                if (node.LocalName == localName && node.NamespaceURI == namespaceURI)
                    return i;
            }
 
            return -1;
        }
 
        internal virtual XmlNode AddNode(XmlNode node)
        {
            XmlNode? oldParent;
            if (node.NodeType == XmlNodeType.Attribute)
                oldParent = ((XmlAttribute)node).OwnerElement;
            else
                oldParent = node.ParentNode;
 
            string? nodeValue = node.Value;
            XmlNodeChangedEventArgs? args = parent.GetEventArgs(node, oldParent, parent, nodeValue, nodeValue, XmlNodeChangedAction.Insert);
 
            if (args != null)
                parent.BeforeEvent(args);
 
            nodes.Add(node);
            node.SetParent(parent);
 
            if (args != null)
                parent.AfterEvent(args);
 
            return node;
        }
 
        internal virtual XmlNode AddNodeForLoad(XmlNode node, XmlDocument doc)
        {
            XmlNodeChangedEventArgs? args = doc.GetInsertEventArgsForLoad(node, parent);
            if (args != null)
            {
                doc.BeforeEvent(args);
            }
 
            nodes.Add(node);
            node.SetParent(parent);
            if (args != null)
            {
                doc.AfterEvent(args);
            }
 
            return node;
        }
 
        internal virtual XmlNode RemoveNodeAt(int i)
        {
            XmlNode oldNode = (XmlNode)nodes[i];
 
            string? oldNodeValue = oldNode.Value;
            XmlNodeChangedEventArgs? args = parent.GetEventArgs(oldNode, parent, null, oldNodeValue, oldNodeValue, XmlNodeChangedAction.Remove);
 
            if (args != null)
                parent.BeforeEvent(args);
 
            nodes.RemoveAt(i);
            oldNode.SetParent(null);
 
            if (args != null)
                parent.AfterEvent(args);
 
            return oldNode;
        }
 
        internal XmlNode ReplaceNodeAt(int i, XmlNode node)
        {
            XmlNode oldNode = RemoveNodeAt(i);
            InsertNodeAt(i, node);
            return oldNode;
        }
 
        internal virtual XmlNode InsertNodeAt(int i, XmlNode node)
        {
            XmlNode? oldParent;
            if (node.NodeType == XmlNodeType.Attribute)
                oldParent = ((XmlAttribute)node).OwnerElement;
            else
                oldParent = node.ParentNode;
 
            string? nodeValue = node.Value;
            XmlNodeChangedEventArgs? args = parent.GetEventArgs(node, oldParent, parent, nodeValue, nodeValue, XmlNodeChangedAction.Insert);
 
            if (args != null)
                parent.BeforeEvent(args);
 
            nodes.Insert(i, node);
            node.SetParent(parent);
 
            if (args != null)
                parent.AfterEvent(args);
 
            return node;
        }
    }
}