2002-03-28 Duncan Mak <duncan@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlNamedNodeMap.cs
index e30aa7d4e42584a0258f0e892f24dad7eca2613a..d9cd04a6426c9658dc60d4d809d820b51e643e27 100644 (file)
-//\r
-// System.Xml.XmlNamedNodeMap.cs\r
-//\r
-// Author: Daniel Weber (daniel-weber@austin.rr.com)\r
-//\r
-// Implementation of abstract System.Xml.XmlNamedNodeMap class\r
-//\r
-// Credit for source code to Open XML 2.3.17\r
-\r
-using System;\r
-using System.Collections;\r
-\r
-namespace System.Xml\r
-{\r
-\r
-       public class XmlNamedNodeMap : IEnumerable\r
-       {\r
-               //=============== Class data structures ====================================\r
-               // Use weak references for owners to prevent circular linkage\r
-               protected XmlNode FOwner;\r
-               protected XmlNode FOwnerNode;\r
-\r
-               protected ArrayList FnodeList;\r
-               private bool FNamespaceAware;\r
-               private bool FIsReadonly;\r
-\r
-               // ============ Public Properties =====================================\r
-               //=====================================================================\r
-               /// <summary>\r
-               /// Get the count of nodes in the map\r
-               /// </summary>\r
-               public virtual int Count \r
-               {\r
-                       get\r
-                       {\r
-                               return FnodeList.Count;\r
-                       }\r
-               }\r
-               \r
-               // ============ Public Methods    =====================================\r
-               /// <summary>\r
-               /// Get the node at the given index.  Index is 0-based, top element is Count - 1\r
-               /// </summary>\r
-               /// <param name="index">index into array of XmlNode to get</param>\r
-               /// <returns>XmlNode at index, or null if index out of range</returns>\r
-               public virtual XmlNode Item(int index)\r
-               {\r
-                       try\r
-                       {\r
-                               return FnodeList[index] as XmlNode;   //FnodeList.Item(index);\r
-                       }\r
-                       catch (ArgumentOutOfRangeException)\r
-                       {\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// Get the node with the given name\r
-               /// If the nodes have an associated namespace, use (localName, namespaceURI) instead\r
-               /// </summary>\r
-               /// <param name="name">name of the node to return</param>\r
-               /// <returns>XmlNode, or null if node not found</returns>\r
-               public virtual XmlNode GetNamedItem(string name)\r
-               {\r
-                       // Can't return without a namespace to lookup\r
-                       // SDK doesn't specify an exception to throw, so just return null\r
-                       if (FNamespaceAware) \r
-                               return null;\r
-\r
-                       foreach (XmlNode cur in FnodeList)\r
-                       {\r
-                               if (cur.Name == name)\r
-                                       return cur;\r
-                       }\r
-\r
-                       return null;\r
-\r
-               }\r
-               \r
-               /// <summary>\r
-               /// Get the node with localName in given namespaceURI\r
-               /// </summary>\r
-               /// <param name="localName">localName of node</param>\r
-               /// <param name="namespaceURI">namespace of node</param>\r
-               /// <returns>XmlNode at location, or null</returns>\r
-               public virtual XmlNode GetNamedItem(string localName, string namespaceURI)\r
-               {\r
-                       // No namespace data in objects, can't lookup\r
-                       // SDK doesn't specify an exception to throw, so just return null\r
-                       if (! FNamespaceAware)\r
-                               return null;\r
-\r
-                       foreach (XmlNode cur in FnodeList)\r
-                       {\r
-                               if ((cur.Name == localName) & (cur.NamespaceURI == namespaceURI))\r
-                                       return cur;\r
-                       }\r
-                       return null;\r
-\r
-               }\r
-\r
-               /// <summary>\r
-               /// Get the enumerator for the node map\r
-               /// </summary>\r
-               /// <returns>Enumerator</returns>\r
-               public virtual IEnumerator GetEnumerator()\r
-               {\r
-                       return FnodeList.GetEnumerator();\r
-               }\r
-\r
-               \r
-               /// <summary>\r
-               /// Removes the node with given name from the Map and returns it.\r
-               /// If the node is namespace aware, use RemoveNamedItem(localName, namespaceURI) instead\r
-               /// </summary>\r
-               /// <param name="name">node name</param>\r
-               /// <returns>Removed node, or null if node not found</returns>\r
-               public virtual XmlNode RemoveNamedItem(string name)\r
-               {\r
-                       // Can't return without a namespace to lookup\r
-                       // SDK doesn't specify an exception to throw, so just return null\r
-                       if (FNamespaceAware) \r
-                               return null;\r
-\r
-                       for (int i = 0; i < FnodeList.Count; i++)\r
-                       {\r
-                               XmlNode cur = FnodeList[i] as XmlNode;\r
-                               if (cur.Name == name)\r
-                               {\r
-                                       FnodeList.RemoveAt(i);\r
-                                       return cur;\r
-                               }\r
-                       }\r
-                       return null;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Removes the node with given localName in namespaceURI\r
-               /// If this XmlNamedNodeMap is not namespace aware, use RemoveNamedItem(name) instead.\r
-               /// </summary>\r
-               /// <param name="localName">local node name</param>\r
-               /// <param name="namespaceURI">namespace node is in</param>\r
-               /// <returns>Node that was removed, or null if no node found</returns>\r
-               public virtual XmlNode RemoveNamedItem(string localName, string namespaceURI)\r
-               {\r
-                       // No namespace data in objects, can't lookup\r
-                       // SDK doesn't specify an exception to throw, so just return null\r
-                       if (! FNamespaceAware)  // NOT _namespaceAware\r
-                               return null;\r
-\r
-                       for (int i = 0; i < FnodeList.Count; i++)\r
-                       {\r
-                               XmlNode cur = FnodeList[i] as XmlNode;\r
-                               if ((cur.Name == localName) & (cur.NamespaceURI == namespaceURI))\r
-                               {\r
-                                       FnodeList.RemoveAt(i);\r
-                                       return cur;\r
-                               }\r
-                       }\r
-                       return null;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Adds the passed node using the name property\r
-               /// If a node with this name exists, it is returned, otherwise null is returned.\r
-               /// </summary>\r
-               /// <exception cref="ArgumentException">Raised if node was created from another docuement, or XmlNamedNodeMap is read-only</exception>\r
-               /// <exception cref="InvalidOperationException">Node is an XmlAttribute of another XmlElement</exception>\r
-               /// <param name="node"></param>\r
-               /// <returns></returns>\r
-               public virtual XmlNode SetNamedItem(XmlNode node)\r
-               {\r
-                       XmlNode retValue ;              // Return value of method\r
-\r
-                       // Can't add to read-only Map\r
-                       if (FIsReadonly)\r
-                               throw new ArgumentException("Attempt to add node to read-only Node Map");\r
-                       \r
-                       //if FOwner.OwnerDocument <> arg.OwnerDocument then raise EWrong_Document_Err\r
-                       if (! FOwner.OwnerDocument.Equals(node.OwnerDocument))\r
-                               throw new ArgumentException("Cannot add node from another document");\r
-               \r
-                       // if FNamespaceAware then raise ENamespace_Err.create('Namespace error.');\r
-                       if (FNamespaceAware)\r
-                               throw new InvalidOperationException("Invalid Operation: Can't add node by name to namespace aware node list");\r
-\r
-                       // Can't assign node that has a parent\r
-                       // TODO - is this check required/valid in the .NET API?\r
-                       //if assigned(arg.parentNode) then raise EInuse_Node_Err.create('In use node error.');\r
-                       if (node.ParentNode != null)\r
-                               throw new ArgumentException("In use node error");\r
-\r
-                       // XmlAttribute cannot be assigned to an element\r
-                       //if arg.NodeType = ntAttribute_Node\r
-                       //      then if assigned((arg as TdomAttr).OwnerElement)\r
-                       //                       then if (arg as TdomAttr).OwnerElement <> FOwnerNode then raise EInuse_Attribute_Err.create('Inuse attribute error.');\r
-\r
-                       if (node is XmlAttribute)\r
-                       {\r
-                               if ((node as XmlAttribute).OwnerElement != null)\r
-                               {\r
-                                       if (! FOwnerNode.Equals( (node as XmlAttribute).OwnerElement ))\r
-                                               throw new InvalidOperationException("XmlAttribute is assigned to another element");\r
-                               }\r
-                       }\r
-\r
-                       /* \r
-                       if not (arg.NodeType in FAllowedNodeTypes) then raise EHierarchy_Request_Err.create('Hierarchy request error.');\r
-                       */\r
-\r
-                       if ( GetNamedItem(node.Name) != null)\r
-                       { \r
-                               retValue = RemoveNamedItem(node.Name); \r
-                       }\r
-                       else\r
-                       { \r
-                               retValue = null;\r
-                       }\r
-\r
-                       FnodeList.Add(node);\r
-\r
-                       // TODO - check that owner is set properly on adding an attribute node\r
-\r
-                       return retValue;\r
-               }\r
-\r
-               // ============ Constructors  =========================================\r
-               internal XmlNamedNodeMap(XmlNode aOwner, XmlNode aOwnerNode, ArrayList nodeList)\r
-               {\r
-                       if (nodeList == null)\r
-                               nodeList = new ArrayList();\r
-                       else\r
-                               FnodeList = nodeList;\r
-                       FOwner = aOwner;\r
-                       FOwnerNode = aOwnerNode;\r
-                       FIsReadonly = false;\r
-                       FNamespaceAware = false;\r
-               }\r
-\r
-               // Add a default costructor to satisfy Visual Studio....\r
-               // TODO - figure out a way to get rid of default constructor on XmlNamedNodeMap()\r
-               internal XmlNamedNodeMap()\r
-               {\r
-                       FnodeList = new ArrayList();\r
-                       FOwner = null;\r
-                       FOwnerNode = null;\r
-                       FIsReadonly = false;\r
-                       FNamespaceAware = false;\r
-               }\r
-\r
-               // ============ Internal Properties ===================================\r
-               //=====================================================================\r
-               internal bool IsReadOnly\r
-               {\r
-                       get \r
-                       { \r
-                               return FIsReadonly;\r
-                       }\r
-                       set \r
-                       { \r
-                               FIsReadonly = value;\r
-                       }\r
-               }\r
-\r
-               internal bool NamespaceAware\r
-               {\r
-                       get \r
-                       { \r
-                               return FNamespaceAware; \r
-                       }\r
-                       set \r
-                       { \r
-                               FNamespaceAware = value;\r
-                       }\r
-               }\r
-\r
-       }\r
-}
\ No newline at end of file
+//
+// System.Xml.XmlNamedNodeMap
+//
+// Author:
+//   Jason Diamond (jason@injektilo.org)
+//   Duncan Mak  (duncan@ximian.com)
+//
+// (C) 2002 Jason Diamond  http://injektilo.org/
+//
+
+using System;
+using System.Collections;
+
+namespace System.Xml
+{
+       public class XmlNamedNodeMap : IEnumerable
+       {
+               XmlNode parent;
+               ArrayList nodeList;
+               bool readOnly = false;
+
+               internal XmlNamedNodeMap (XmlNode parent)
+               {
+                       this.parent = parent;
+                       nodeList = new ArrayList ();
+               }
+
+               public virtual int Count {
+                       get { return nodeList.Count; }
+               }
+
+               public virtual IEnumerator GetEnumerator () 
+               {
+                       return nodeList.GetEnumerator ();
+               }
+
+               public virtual XmlNode GetNamedItem (string name)
+               {
+                       foreach (XmlNode node in nodeList) {
+                               if (node.Name == name)
+                                       return node;
+                       }
+                       return null;
+               }
+
+               public virtual XmlNode GetNamedItem (string localName, string namespaceURI)
+               {
+                       foreach (XmlNode node in nodeList) {
+                               if ((node.Name == localName)
+                                   && (parent.NamespaceURI == namespaceURI))
+                                       return node;
+                       }
+
+                       return null;
+               }
+               
+               public virtual XmlNode Item (int index)
+               {
+                       if (index < 0 || index > nodeList.Count)
+                               return null;
+                       else
+                               return (XmlNode) nodeList [index];
+               }
+
+               public virtual XmlNode RemoveNamedItem (string name)
+               {                       
+                       foreach (XmlNode node in nodeList)
+                               if (node.Name == name) {
+                                       nodeList.Remove (node);
+                                       return node;
+                               }
+                       
+                       return null;
+               }
+
+               public virtual XmlNode RemoveNamedItem (string localName, string namespaceURI)
+               {
+                       foreach (XmlNode node in nodeList)
+                               if ((node.Name == localName)
+                                   && (parent.NamespaceURI == namespaceURI)) {
+                                       nodeList.Remove (node);
+                                       return node;
+                               }
+
+                       return null;
+               }
+
+               public virtual XmlNode SetNamedItem (XmlNode node)
+               {
+                       if (readOnly || (node.OwnerDocument != parent.OwnerDocument))
+                               throw new ArgumentException ("Cannot add to NodeMap.");
+                                               
+                       foreach (XmlNode x in nodeList)
+                               if (x.Name == node.Name) {
+                                       nodeList.Remove (x);
+                                       nodeList.Add (x);
+                                       return x;
+                               }
+                       
+                       nodeList.Add (node);
+                       return null;
+               }
+       }
+}