2003-02-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlAttributeCollection.cs
index 2b206cf6695bdc6597e82eeaf22b2ced0d57fc87..5c9694da5565fd1e5dd92f718e7b21c475db9d34 100644 (file)
-// System.Xml.XmlAttributeCollection.cs\r
-//\r
-// Author: Daniel Weber (daniel-weber@austin.rr.com)\r
-//\r
-// Implementation of abstract Xml.XmlAttributeCollection class\r
-//\r
-\r
-using System;\r
-using System.Collections;\r
-\r
-namespace System.Xml\r
-{\r
-       /// <summary>\r
-       /// A collection of Attributes that can be accessed by index or name(space)\r
-       /// Derived from XmlNamedNodeMap\r
-       /// <seealso cref="XmlNamedNodeMap"/>\r
-       /// </summary>\r
-       public class XmlAttributeCollection : XmlNamedNodeMap, ICollection\r
-       {\r
-\r
-               // =====  ICollection interface elements  ===================================\r
-               /// <summary>\r
-               /// Private class to provide Synchronzed Access to the attribute list.\r
-               /// </summary>\r
-               private class SyncAttributes : XmlAttributeCollection\r
-               {\r
-                       private XmlAttributeCollection _attributes;\r
-\r
-                       public SyncAttributes ( XmlAttributeCollection attributes )\r
-                       {\r
-                               _attributes = attributes;\r
-                       }\r
-\r
-                       public override bool IsSynchronized \r
-                       {\r
-                               get {return true; }\r
-                       }\r
-\r
-                       // Override all properties/methods that modify/read items\r
-                       //      and lock them so they are thread-safe\r
-                       public override void CopyTo(Array array, int index)\r
-                       {\r
-                               lock (_attributes )\r
-                               { _attributes.CopyTo(array, index); }\r
-                       }\r
-                       \r
-                       public override XmlAttribute this[string name] \r
-                       {\r
-                               get  {\r
-                                       lock (_attributes ) { return _attributes[name]; }\r
-                               }\r
-                       }\r
-\r
-                       public override XmlAttribute this[int i] \r
-                       {\r
-                               get {\r
-                                       lock (_attributes) { return _attributes[i]; }\r
-                               }\r
-                       }\r
-\r
-                       public override XmlAttribute Append( XmlAttribute node )\r
-                       {\r
-                               lock (_attributes)\r
-                               { return _attributes.Append( node ); }\r
-                       }\r
-                       \r
-                       public override void CopyTo(XmlAttribute[] array, int index)\r
-                       {\r
-                               lock (_attributes)\r
-                               { _attributes.CopyTo(array, index); }\r
-                       }\r
-\r
-                       public override XmlAttribute InsertAfter( \r
-                               XmlAttribute newNode, \r
-                               XmlAttribute refNode)\r
-                       {\r
-                               lock (_attributes)\r
-                               { return _attributes.InsertAfter( newNode, refNode ); }\r
-                       }\r
-\r
-                       public override XmlAttribute Prepend(XmlAttribute node)\r
-                       {\r
-                               lock (_attributes)\r
-                               { return _attributes.Prepend(node); }\r
-                       }\r
-\r
-                       public override XmlAttribute Remove(XmlAttribute node)\r
-                       {\r
-                               lock (_attributes)\r
-                               { return _attributes.Remove( node ); }\r
-                       }\r
-\r
-                       public override void RemoveAll()\r
-                       {\r
-                               lock (_attributes)\r
-                               { _attributes.RemoveAll(); }\r
-                       }\r
-\r
-                       public override XmlAttribute RemoveAt(int i)\r
-                       {\r
-                               lock (_attributes)\r
-                               { return _attributes.RemoveAt(i); }\r
-                       }\r
-\r
-                       public override XmlNode SetNamedItem(XmlNode node)\r
-                       {\r
-                               lock (_attributes)\r
-                               { return _attributes.SetNamedItem(node); }\r
-                       }\r
-\r
-                       // Even ToString, since someone could come along and blow away an\r
-                       //      attribute while we're iterating...\r
-                       public override string ToString()\r
-                       {\r
-                               lock (_attributes) \r
-                               { return _attributes.ToString(); }\r
-                       }\r
-\r
-               }  // SynchAttributes\r
-\r
-               /// <summary>\r
-               /// Return true if access is synchronized (thread-safe)\r
-               /// </summary>\r
-               public virtual bool IsSynchronized \r
-               {\r
-                       // This version of the class is not synchronized\r
-                       get\r
-                       {\r
-                               return false;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Return object used for synchronous access to class\r
-               /// </summary>\r
-               public object SyncRoot \r
-               {\r
-                       get\r
-                       {\r
-                               return this;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Returns a thread-safe version of the attribute collection.\r
-               /// </summary>\r
-               /// <param name="attributes">Attribute collection to make thread-safe.</param>\r
-               /// <returns>Thread-safe XmlAttributeCollection.</returns>\r
-               public static XmlAttributeCollection Synchronized(XmlAttributeCollection attributes) \r
-               {\r
-                       if (attributes == null) \r
-                       {\r
-                               throw new ArgumentNullException("Null XmlAttributeCollection passed to Synchronized()");\r
-                       }\r
-\r
-                       return new SyncAttributes(attributes);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Copy the XmlAttributeCollection into the passed array.  Index is zero-based.\r
-               /// </summary>\r
-               /// <param name="array">Array to copy into</param>\r
-               /// <param name="index">Index to start copying from</param>\r
-               public virtual void CopyTo(Array array, int index)\r
-               {\r
-                       // Let the Array handle all the errors, there's no risk to us\r
-\r
-                       // TODO - should we set OwnerElement to null in clone() in CopyTo(Array, int)? (yes, using setOwnerElement())\r
-                       int arrayIndex = 0;\r
-                       for (int i = index; i < FnodeList.Count; i++)\r
-                       {\r
-                               XmlAttribute e = FnodeList[i] as XmlAttribute;\r
-                               XmlAttribute theClone = e.Clone() as XmlAttribute;\r
-                               theClone.setOwnerElement(null);\r
-                               array.SetValue(theClone, arrayIndex);\r
-                               arrayIndex++;\r
-                       }\r
-               }\r
-               // XmlAttributeCollection Properties =================================\r
-               /// <summary>\r
-               /// Get the attribute with the specified name\r
-               /// </summary>\r
-               [System.Runtime.CompilerServices.IndexerName("ItemOf")]\r
-               public virtual XmlAttribute this[string name] \r
-               {\r
-                       get\r
-                       {\r
-                               return GetNamedItem(name) as XmlAttribute;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Get the attribute at the specified index.  The Collection is zero-based.\r
-               /// </summary>\r
-               [System.Runtime.CompilerServices.IndexerName("ItemOf")]\r
-               public virtual XmlAttribute this[int i] \r
-               {\r
-                       get\r
-                       {\r
-                               return base.Item(i) as XmlAttribute;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Get the attribute with the specifed (localName, URI)\r
-               /// </summary>\r
-               [System.Runtime.CompilerServices.IndexerName("ItemOf")]\r
-               public virtual XmlAttribute this[string localName, string namespaceURI] \r
-               {\r
-                       get\r
-                       {\r
-                               return GetNamedItem(localName, namespaceURI) as XmlAttribute;\r
-                       }\r
-               }\r
-\r
-               // ============= Public methods =====================================\r
-               /// <summary>\r
-               /// Appends the specified node to the attribute list\r
-               /// If the node is already in the list, it is moved to the end.\r
-               /// If a node is in the list with the same name, the node is removed and the new node is added.\r
-               /// </summary>\r
-               /// <param name="node">Attribute node to append to the collection</param>\r
-               /// <exception cref="ArgumentException">Node was created from a differant document or node is null</exception>\r
-               /// <returns></returns>\r
-               public virtual XmlAttribute Append( XmlAttribute node )\r
-               {\r
-                       // TODO - node validation? (no)\r
-                       \r
-                       XmlAttribute retval = null;\r
-\r
-                       System.Diagnostics.Debug.Assert(node != null, "Null node passed to Append()");\r
-\r
-                       if (! FOwner.OwnerDocument.Equals(node.OwnerDocument))\r
-                               throw new ArgumentException("Cannot append node from another document");\r
-\r
-                       if (node.OwnerElement != null) \r
-                               throw new ArgumentException("Cannot append node from another document");\r
-\r
-                       foreach (XmlAttribute cur in FnodeList)\r
-                       {\r
-                               // If node is already in the collection, it is moved to the last position. \r
-                               if (cur.Equals(node))\r
-                               {\r
-                                       retval = cur;\r
-                                       FnodeList.Remove(cur);\r
-                               }\r
-\r
-                               //If an attribute with the same name is already present in the collection, \r
-                               //   the original attribute is removed from the collection and \r
-                               //   node is added to the end of the collection.\r
-                               if (cur.Name == node.Name)\r
-                                       FnodeList.Remove(cur);\r
-                       }\r
-\r
-                       // add the new node to the end of the collection\r
-                       // set attribute owner element? (yes)\r
-                       node.setOwnerElement(FOwnerNode as XmlElement);\r
-                       FnodeList.Add(node);\r
-\r
-                       // return the removed item\r
-                       return retval;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Copies all attributes in collection into the array, starting at index.\r
-               /// attribute index is zero-based.\r
-               /// </summary>\r
-               /// <exception cref="OverflowException">Thrown if insufficient room to copy all elements</exception>\r
-               /// <param name="array">Array to copy XlmAttributes into</param>\r
-               /// <param name="index">index to start copy</param>\r
-               public virtual void CopyTo(XmlAttribute[] array, int index)\r
-               {\r
-                       // Let the array handle all the errors, there's no risk to us\r
-\r
-                       // TODO - should we set OwnerElement to null in clone() in CopyTo(XmlAttribute[], int)? (yes, using setOwnerElement())\r
-                       int arrayIndex = 0;\r
-                       for (int i = index; i < FnodeList.Count; i++)\r
-                       {\r
-                               XmlAttribute e = FnodeList[i] as XmlAttribute;\r
-                               XmlAttribute theClone = e.Clone() as XmlAttribute;\r
-                               theClone.setOwnerElement(null);\r
-                               array[arrayIndex] = theClone;\r
-                               arrayIndex++;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Helper function since InsertBefore/After use exact same algorithm\r
-               /// </summary>\r
-               /// <param name="refNode"></param>\r
-               /// <param name="newNode"></param>\r
-               /// <param name="offset">offset to add to Insert (0 or 1)</param>\r
-               /// <returns>Deleted attribute</returns>\r
-               private XmlAttribute InsertHelper(XmlAttribute newNode, XmlAttribute refNode, int offset)\r
-               {\r
-                       // TODO - validation? (no)\r
-                       // TODO - null refNode is valid (== prepend)\r
-                       if (refNode == null)\r
-                               throw new ArgumentNullException("Null refNode passed to InsertAfter()");\r
-                       if (newNode == null)\r
-                               throw new ArgumentNullException("Null newNode passed to InsertAfter()");\r
-\r
-                       if (! newNode.OwnerDocument.Equals(FOwner.OwnerDocument) )\r
-                               throw new ArgumentException("Node to insert does not have same owner document as reference");\r
-\r
-                       // Logically, it makes no sense to insert node "A" after node "A",\r
-                       //      since only one node "A" can be in the list - flag it as an error\r
-                       if (newNode.Name == refNode.Name)\r
-                               throw new ArgumentException("Node to insert has same name as reference node");\r
-\r
-                       // Other bizarre case is if refNode.Equals(newNode)\r
-                       //      We'll flag this error after we check that refNode is in the list\r
-               \r
-                       int refNodeIndex = -1;\r
-                       // Note that if newNode is in the list, then we'll get a name match\r
-                       int SameNameIndex = -1;\r
-\r
-                       for (int i = 0; i < FnodeList.Count; i++)\r
-                       {\r
-                               XmlAttribute curListNode = Item(i) as XmlAttribute;\r
-                               if (curListNode.Name == refNode.Name)\r
-                                       refNodeIndex = i;\r
-                               \r
-                               if (curListNode.Name == newNode.Name)\r
-                                       SameNameIndex = i;\r
-                       }\r
-\r
-                       if ( refNodeIndex == -1 )\r
-                               throw new ArgumentException("Attribute [" + refNode.Name + "] is not in Collection for InsertAfter()");\r
-\r
-                       // Check the obvious, InsertAfter( attr1, attr1);\r
-                       if (refNode.Equals( newNode ) )\r
-                               return newNode;\r
-\r
-                       XmlAttribute retval = null;\r
-\r
-                       if (SameNameIndex != -1)\r
-                       {\r
-                               // If this is newNode in the list, we'll insert it back in the right spot\r
-                               // If this is another node, just remove it\r
-                               retval = FnodeList[SameNameIndex] as XmlAttribute;\r
-                               FnodeList.RemoveAt(SameNameIndex);\r
-                               if ( SameNameIndex < refNodeIndex )\r
-                                       refNodeIndex--;\r
-                       }\r
-\r
-                       FnodeList.Insert(refNodeIndex + offset, newNode);\r
-\r
-                       // TODO - set OwnerElement? (no)\r
-                       //node.setOwnerElement(FOwnerNode as XmlElement);\r
-\r
-                       // TODO - determine which node to return (deleted node)\r
-                       return retval;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Insert the specifed attribute immediately after the reference node.\r
-               /// If an attribute with the same name is already in the collection, that attribute is removed and the new attribute inserted\r
-               /// </summary>\r
-               /// <exception cref="ArgumentException">Raised if newNode OwnerDocument differs from nodelist owner or refNode is not a member of the collection</exception>\r
-               /// <param name="newNode">New attribute to insert</param>\r
-               /// <param name="refNode">Reference node to insert new node after</param>\r
-               /// <returns>Inserted node</returns>\r
-               public virtual XmlAttribute InsertAfter( XmlAttribute newNode, XmlAttribute refNode)\r
-               {\r
-                       return InsertHelper(newNode, refNode, 1);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Inserts newNode into the collection just before refNode.\r
-               /// If a node with newNode.Name is already in the list, it is removed.\r
-               /// </summary>\r
-               /// <exception cref="ArgumentException">Thrown if inserted attribute created from different document, refNode not found in collection or\r
-               /// refNode.Name == newNode.Name.</exception>\r
-               /// <param name="newNode">Node to insert into list</param>\r
-               /// <param name="refNode">Node to insert before</param>\r
-               /// <returns>Deleted node, or null if no node was deleted.</returns>\r
-               public virtual XmlAttribute InsertBefore(\r
-                       XmlAttribute newNode,\r
-                       XmlAttribute refNode\r
-                       )\r
-               {\r
-                       return InsertHelper(newNode, refNode, 0);\r
-               }\r
-\r
-               /// <summary>\r
-               /// Inserts the specified node as the first node in the collection\r
-               /// </summary>\r
-               /// <param name="node">XmlAttribute to insert</param>\r
-               /// <exception cref="ArgumentException">If node is null, or owner document does not match collection.</exception>\r
-               /// <returns>Node that was removed, or null if no node deleted.</returns>\r
-               public virtual XmlAttribute Prepend(XmlAttribute node)\r
-               {\r
-                       //TODO - node validation? (no)\r
-                       // TODO - set attribute owner element? (no)\r
-                       //node.setOwnerElement(FOwnerNode as XmlElement);\r
-\r
-                       if (FnodeList.Count > 0)\r
-                       {\r
-                               return InsertBefore(node, Item(0) as XmlAttribute);\r
-                       }\r
-\r
-                       if (node == null)\r
-                               throw new ArgumentException("Cannot prepend null node");\r
-\r
-                       if (! node.OwnerDocument.Equals(FOwner.OwnerDocument) )\r
-                               throw new ArgumentException("Node to prepend does not have same owner document as reference");\r
-\r
-                       FnodeList.Add(node);                    \r
-                       return node;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Removes the requested node from the collection.\r
-               /// </summary>\r
-               /// <param name="node">Node to remove</param>\r
-               /// <returns>The node removed, or null if the node was not found in the collection.</returns>\r
-               public virtual XmlAttribute Remove(XmlAttribute node)\r
-               {\r
-                       for (int i = 0; i < FnodeList.Count; i++)\r
-                       {\r
-                               XmlAttribute e = FnodeList[i] as XmlAttribute;\r
-                       \r
-                               if (e.Equals(node))\r
-                               {\r
-                                       FnodeList.RemoveAt(i);\r
-                                       return node;\r
-                               }\r
-                       }\r
-                       // TODO - if node is a default, should we add it back with a default value? (no)\r
-                       return null;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Removes all attributes from the collection\r
-               /// </summary>\r
-               public virtual void RemoveAll()\r
-               {\r
-                       // Can this be this easy?\r
-                       for (int i = FnodeList.Count - 1; i > 0; i--)\r
-                       {\r
-                               XmlAttribute e = FnodeList[i] as XmlAttribute;\r
-                               e.setOwnerElement(null);\r
-                               FnodeList.RemoveAt(i);\r
-                       }\r
-\r
-                       // TODO - Add default attributes back in in RemoveAll()?  (no)\r
-               }\r
-\r
-               /// <summary>\r
-               /// Removes the attribute at the specified index\r
-               /// </summary>\r
-               /// <param name="i">index of attribute to remove.</param>\r
-               /// <returns>Removed node, or null if node not in collection</returns>\r
-               public virtual XmlAttribute RemoveAt(int i)\r
-               {\r
-                       if ((i < 0) | ( i >= FnodeList.Count))\r
-                               return null;\r
-\r
-                       // TODO - if default attribute removed in RemoveAt(), add it back? (no)\r
-                       XmlAttribute e = FnodeList[i] as XmlAttribute;\r
-                       FnodeList.RemoveAt(i);\r
-                       e.setOwnerElement(null);\r
-                       return e;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Adds a node to the collection using it's name.  If a node with the same name exists,\r
-               /// it is removed.\r
-               /// </summary>\r
-               /// <param name="node">XmlAttribute to add.</param>\r
-               /// <returns>If a node replaces a named node, the replaced node is deleted and returned. \r
-               /// Otherwise, null.</returns>\r
-               public override XmlNode SetNamedItem(XmlNode node)\r
-               {\r
-                       return base.SetNamedItem(node);\r
-               }\r
-\r
-               public override string ToString()\r
-               {\r
-                       string retval = "System.Xml.XmlAttributeCollection ";\r
-                       if (FOwnerNode != null)\r
-                               retval += "OwnerElement: " + FOwnerNode.Name;\r
-\r
-                       foreach (XmlAttribute o in FnodeList)\r
-                       {\r
-                               retval += o.Name + "=" + o.Value;\r
-                       }\r
-                       return retval;\r
-\r
-               }\r
-               // ============= Constructors ========================================\r
-               // TODO - change constructor to pass in IEnumerator?\r
-               internal XmlAttributeCollection(XmlNode aOwner, XmlNode aOwnerNode, ArrayList nodeList) :\r
-                       base(aOwner, aOwnerNode, nodeList)\r
-               {\r
-                       // Makes no sense to have namespace aware on attributes\r
-                       NamespaceAware = false;\r
-               }\r
-\r
-               internal XmlAttributeCollection ()\r
-               {\r
-               }\r
-\r
-       }\r
-}
\ No newline at end of file
+//
+// System.Xml.XmlAttributeCollection
+//
+// Author:
+//   Jason Diamond (jason@injektilo.org)
+//   Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
+//
+// (C) 2002 Jason Diamond  http://injektilo.org/
+// (C) 2002 Atsushi Enomoto
+//
+
+using System;
+using System.Collections;
+
+namespace System.Xml
+{
+       public class XmlAttributeCollection : XmlNamedNodeMap, ICollection
+       {
+               XmlElement ownerElement;
+
+               internal XmlAttributeCollection (XmlNode parent) : base (parent)
+               {
+                       ownerElement = parent as XmlElement;
+                       if(ownerElement == null)
+                               throw new XmlException ("invalid construction for XmlAttributeCollection.");
+               }
+
+               bool ICollection.IsSynchronized {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               bool IsReadOnly {
+                       get {
+                               return ownerElement.IsReadOnly;
+                       }
+               }
+
+               [MonoTODO]
+               [System.Runtime.CompilerServices.IndexerName ("ItemOf")]
+               public virtual XmlAttribute this [string name] {
+                       get {
+                               return (XmlAttribute) GetNamedItem (name);
+                       }
+               }
+
+               [MonoTODO]
+               [System.Runtime.CompilerServices.IndexerName ("ItemOf")]
+               public virtual XmlAttribute this [int i] {
+                       get {
+                               return (XmlAttribute) Nodes [i];
+                       }
+               }
+
+               [MonoTODO]
+               [System.Runtime.CompilerServices.IndexerName ("ItemOf")]
+               public virtual XmlAttribute this [string localName, string namespaceURI] {
+                       get {
+                               return (XmlAttribute) GetNamedItem (localName, namespaceURI);
+                       }
+               }
+
+               object ICollection.SyncRoot {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               
+               public virtual XmlAttribute Append (XmlAttribute node) 
+               {
+                       XmlNode xmlNode = this.SetNamedItem (node);
+                       return node;
+               }       
+
+               public void CopyTo (XmlAttribute[] array, int index)
+               {
+                       // assuming that Nodes is a correct collection.
+                       for(int i=0; i<Nodes.Count; i++)
+                               array [index + i] = Nodes [i] as XmlAttribute;
+               }
+
+               [MonoTODO] // I don't know why this method is required...
+               void ICollection.CopyTo (Array array, int index)
+               {
+                       // assuming that Nodes is a correct collection.
+                       array.CopyTo (Nodes.ToArray (typeof(XmlAttribute)), index);
+               }
+
+               public virtual XmlAttribute InsertAfter (XmlAttribute newNode, XmlAttribute refNode)
+               {
+                       if(newNode.OwnerDocument != this.ownerElement.OwnerDocument)
+                               throw new ArgumentException ("different document created this newNode.");
+
+                       ownerElement.OwnerDocument.onNodeInserting (newNode, null);
+
+                       int pos = Nodes.Count + 1;
+                       if(refNode != null)
+                       {
+                               for(int i=0; i<Nodes.Count; i++)
+                               {
+                                       XmlNode n = Nodes [i] as XmlNode;
+                                       if(n == refNode)
+                                       {
+                                               pos = i + 1;
+                                               break;
+                                       }
+                               }
+                               if(pos > Nodes.Count)
+                                       throw new XmlException ("refNode not found in this collection.");
+                       }
+                       else
+                               pos = 0;
+                       SetNamedItem (newNode, pos);
+
+                       ownerElement.OwnerDocument.onNodeInserted (newNode, null);
+
+                       return newNode;
+               }
+
+               public virtual XmlAttribute InsertBefore (XmlAttribute newNode, XmlAttribute refNode)
+               {
+                       if(newNode.OwnerDocument != this.ownerElement.OwnerDocument)
+                               throw new ArgumentException ("different document created this newNode.");
+
+                       ownerElement.OwnerDocument.onNodeInserting (newNode, null);
+
+                       int pos = Nodes.Count;
+                       if(refNode != null)
+                       {
+                               for(int i=0; i<Nodes.Count; i++)
+                               {
+                                       XmlNode n = Nodes [i] as XmlNode;
+                                       if(n == refNode)
+                                       {
+                                               pos = i;
+                                               break;
+                                       }
+                               }
+                               if(pos == Nodes.Count)
+                                       throw new XmlException ("refNode not found in this collection.");
+                       }
+                       SetNamedItem (newNode, pos);
+
+                       ownerElement.OwnerDocument.onNodeInserted (newNode, null);
+
+                       return newNode;
+               }
+
+               public virtual XmlAttribute Prepend (XmlAttribute node) 
+               {
+                       return this.InsertAfter (node, null);
+               }
+
+               public virtual XmlAttribute Remove (XmlAttribute node) 
+               {
+                       if(node == null || node.OwnerDocument != this.ownerElement.OwnerDocument)
+                               throw new ArgumentException ("node is null or different document created this node.");
+
+                       XmlAttribute retAttr = null;
+                       foreach(XmlAttribute attr in Nodes)
+                       {
+                               if(attr == node)
+                               {
+                                       retAttr = attr;
+                                       break;
+                               }
+                       }
+
+                       if(retAttr != null)
+                       {
+                               ownerElement.OwnerDocument.onNodeRemoving (node, null);
+                               base.RemoveNamedItem (retAttr.LocalName, retAttr.NamespaceURI);
+                               ownerElement.OwnerDocument.onNodeRemoved (node, null);
+                       }
+                       return retAttr;
+               }
+
+               public virtual void RemoveAll () 
+               {
+                       while(Count > 0)
+                               Remove ((XmlAttribute)Nodes [0]);
+               }
+
+               public virtual XmlAttribute RemoveAt (int i) 
+               {
+                       if(Nodes.Count <= i)
+                               return null;
+                       return Remove ((XmlAttribute)Nodes [i]);
+               }
+
+               public override XmlNode SetNamedItem (XmlNode node)
+               {
+                       return SetNamedItem(node, -1);
+               }
+
+               [MonoTODO("event handling")]
+               internal new XmlNode SetNamedItem (XmlNode node, int pos)
+               {
+                       if(IsReadOnly)
+                               throw new XmlException ("this AttributeCollection is read only.");
+
+                       return base.SetNamedItem (node, pos);
+               }
+       }
+}