2004-04-05 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlNamedNodeMap.cs
index 408bf988efc58debc344916a0283edf1fbc7d234..d2ff996b61708960f03cf70638afe7f493d83918 100644 (file)
@@ -10,6 +10,7 @@
 
 using System;
 using System.Collections;
+using Mono.Xml;
 
 namespace System.Xml
 {
@@ -17,6 +18,7 @@ namespace System.Xml
        {
                XmlNode parent;
                ArrayList nodeList;
+               bool readOnly = false;
 
                internal XmlNamedNodeMap (XmlNode parent)
                {
@@ -35,7 +37,8 @@ namespace System.Xml
 
                public virtual XmlNode GetNamedItem (string name)
                {
-                       foreach (XmlNode node in nodeList) {
+                       for (int i = 0; i < nodeList.Count; i++) {
+                               XmlNode node = (XmlNode) nodeList [i];
                                if (node.Name == name)
                                        return node;
                        }
@@ -44,9 +47,10 @@ namespace System.Xml
 
                public virtual XmlNode GetNamedItem (string localName, string namespaceURI)
                {
-                       foreach (XmlNode node in nodeList) {
-                               if ((node.Name == localName)
-                                   && (parent.NamespaceURI == namespaceURI))
+                       for (int i = 0; i < nodeList.Count; i++) {
+                               XmlNode node = (XmlNode) nodeList [i];
+                               if ((node.LocalName == localName)
+                                   && (node.NamespaceURI == namespaceURI))
                                        return node;
                        }
 
@@ -55,7 +59,7 @@ namespace System.Xml
                
                public virtual XmlNode Item (int index)
                {
-                       if (index < 0 || index > nodeList.Count)
+                       if (index < 0 || index >= nodeList.Count)
                                return null;
                        else
                                return (XmlNode) nodeList [index];
@@ -63,41 +67,88 @@ namespace System.Xml
 
                public virtual XmlNode RemoveNamedItem (string name)
                {
-                       XmlNode removed = null;
-
-                       foreach (XmlNode node in nodeList)
+                       for (int i = 0; i < nodeList.Count; i++) {
+                               XmlNode node = (XmlNode) nodeList [i];
                                if (node.Name == name) {
-                                       removed = node;
+                                       if (node.IsReadOnly)
+                                               throw new InvalidOperationException ("Cannot remove. This node is read only: " + name);
                                        nodeList.Remove (node);
+                                       // Since XmlAttributeCollection does not override
+                                       // it while attribute have to keep it in the
+                                       // collection, it adds to the collection immediately.
+                                       XmlAttribute attr = node as XmlAttribute;
+                                       if (attr != null) {
+                                               DTDAttributeDefinition def = attr.GetAttributeDefinition ();
+                                               if (def != null && def.DefaultValue != null) {
+                                                       XmlAttribute newAttr = attr.OwnerDocument.CreateAttribute (attr.Prefix, attr.LocalName, attr.NamespaceURI, true, false);
+                                                       newAttr.Value = def.DefaultValue;
+                                                       newAttr.SetDefault ();
+                                                       attr.OwnerElement.SetAttributeNode (newAttr);
+                                               }
+                                       }
+                                       return node;
                                }
-                       
-                       return removed;
+                       }
+                       return null;
                }
 
                public virtual XmlNode RemoveNamedItem (string localName, string namespaceURI)
                {
-                       XmlNode removed = null;
-
-                       foreach (XmlNode node in nodeList)
-                               if ((node.Name == localName)
-                                   && (parent.NamespaceURI == namespaceURI)) {
-                                       removed = node;
+                       for (int i = 0; i < nodeList.Count; i++) {
+                               XmlNode node = (XmlNode) nodeList [i];
+                               if ((node.LocalName == localName)
+                                   && (node.NamespaceURI == namespaceURI)) {
                                        nodeList.Remove (node);
+                                       return node;
                                }
-
-                       return removed;
+                       }
+                       return null;
                }
 
                public virtual XmlNode SetNamedItem (XmlNode node)
                {
-                       XmlNode replaced = null;
+                       return SetNamedItem (node, -1, true);
+               }
+
+               internal XmlNode SetNamedItem (XmlNode node, bool raiseEvent)
+               {
+                       return SetNamedItem (node, -1, raiseEvent);
+               }
+
+               internal XmlNode SetNamedItem (XmlNode node, int pos, bool raiseEvent)
+               {
+                       if (readOnly || (node.OwnerDocument != parent.OwnerDocument))
+                               throw new ArgumentException ("Cannot add to NodeMap.");
+
+                       if (raiseEvent)
+                               parent.OwnerDocument.onNodeInserting (node, parent);
+
+                       try {
+                               for (int i = 0; i < nodeList.Count; i++) {
+                                       XmlNode x = (XmlNode) nodeList [i];
+                                       if(x.LocalName == node.LocalName && x.NamespaceURI == node.NamespaceURI) {
+                                               nodeList.Remove (x);
+                                               if (pos < 0)
+                                                       nodeList.Add (node);
+                                               else
+                                                       nodeList.Insert (pos, node);
+                                               return x;
+                                       }
+                               }
                        
-                       foreach (XmlNode x in nodeList)
-                               if (x == node)
-                                       replaced = x;
-                                       
-                       nodeList.Add (node);
-                       return replaced;
+                               if(pos < 0)
+                                       nodeList.Add (node);
+                               else
+                                       nodeList.Insert (pos, node);
+
+                               return node;
+                       } finally {
+                               if (raiseEvent)
+                                       parent.OwnerDocument.onNodeInserted (node, parent);
+                       }
+
                }
+
+               internal ArrayList Nodes { get { return nodeList; } }
        }
 }