XmlNamedNodeMap.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //
  2. // System.Xml.XmlNamedNodeMap.cs
  3. //
  4. // Author: Daniel Weber ([email protected])
  5. //
  6. // Implementation of abstract System.Xml.XmlNamedNodeMap class
  7. //
  8. // Credit for source code to Open XML 2.3.17
  9. using System;
  10. using System.Collections;
  11. namespace System.Xml
  12. {
  13. public class XmlNamedNodeMap : IEnumerable
  14. {
  15. //=============== Class data structures ====================================
  16. // Use weak references for owners to prevent circular linkage
  17. protected XmlNode FOwner;
  18. protected XmlNode FOwnerNode;
  19. protected ArrayList FnodeList;
  20. private bool FNamespaceAware;
  21. private bool FIsReadonly;
  22. // ============ Public Properties =====================================
  23. //=====================================================================
  24. /// <summary>
  25. /// Get the count of nodes in the map
  26. /// </summary>
  27. public virtual int Count
  28. {
  29. get
  30. {
  31. return FnodeList.Count;
  32. }
  33. }
  34. // ============ Public Methods =====================================
  35. /// <summary>
  36. /// Get the node at the given index. Index is 0-based, top element is Count - 1
  37. /// </summary>
  38. /// <param name="index">index into array of XmlNode to get</param>
  39. /// <returns>XmlNode at index, or null if index out of range</returns>
  40. public virtual XmlNode Item(int index)
  41. {
  42. try
  43. {
  44. return FnodeList[index] as XmlNode; //FnodeList.Item(index);
  45. }
  46. catch (ArgumentOutOfRangeException)
  47. {
  48. return null;
  49. }
  50. }
  51. /// <summary>
  52. /// Get the node with the given name
  53. /// If the nodes have an associated namespace, use (localName, namespaceURI) instead
  54. /// </summary>
  55. /// <param name="name">name of the node to return</param>
  56. /// <returns>XmlNode, or null if node not found</returns>
  57. public virtual XmlNode GetNamedItem(string name)
  58. {
  59. // Can't return without a namespace to lookup
  60. // SDK doesn't specify an exception to throw, so just return null
  61. if (FNamespaceAware)
  62. return null;
  63. foreach (XmlNode cur in FnodeList)
  64. {
  65. if (cur.Name == name)
  66. return cur;
  67. }
  68. return null;
  69. }
  70. /// <summary>
  71. /// Get the node with localName in given namespaceURI
  72. /// </summary>
  73. /// <param name="localName">localName of node</param>
  74. /// <param name="namespaceURI">namespace of node</param>
  75. /// <returns>XmlNode at location, or null</returns>
  76. public virtual XmlNode GetNamedItem(string localName, string namespaceURI)
  77. {
  78. // No namespace data in objects, can't lookup
  79. // SDK doesn't specify an exception to throw, so just return null
  80. if (! FNamespaceAware)
  81. return null;
  82. foreach (XmlNode cur in FnodeList)
  83. {
  84. if ((cur.Name == localName) & (cur.NamespaceURI == namespaceURI))
  85. return cur;
  86. }
  87. return null;
  88. }
  89. /// <summary>
  90. /// Get the enumerator for the node map
  91. /// </summary>
  92. /// <returns>Enumerator</returns>
  93. public virtual IEnumerator GetEnumerator()
  94. {
  95. return FnodeList.GetEnumerator();
  96. }
  97. /// <summary>
  98. /// Removes the node with given name from the Map and returns it.
  99. /// If the node is namespace aware, use RemoveNamedItem(localName, namespaceURI) instead
  100. /// </summary>
  101. /// <param name="name">node name</param>
  102. /// <returns>Removed node, or null if node not found</returns>
  103. public virtual XmlNode RemoveNamedItem(string name)
  104. {
  105. // Can't return without a namespace to lookup
  106. // SDK doesn't specify an exception to throw, so just return null
  107. if (FNamespaceAware)
  108. return null;
  109. for (int i = 0; i < FnodeList.Count; i++)
  110. {
  111. XmlNode cur = FnodeList[i] as XmlNode;
  112. if (cur.Name == name)
  113. {
  114. FnodeList.RemoveAt(i);
  115. return cur;
  116. }
  117. }
  118. return null;
  119. }
  120. /// <summary>
  121. /// Removes the node with given localName in namespaceURI
  122. /// If this XmlNamedNodeMap is not namespace aware, use RemoveNamedItem(name) instead.
  123. /// </summary>
  124. /// <param name="localName">local node name</param>
  125. /// <param name="namespaceURI">namespace node is in</param>
  126. /// <returns>Node that was removed, or null if no node found</returns>
  127. public virtual XmlNode RemoveNamedItem(string localName, string namespaceURI)
  128. {
  129. // No namespace data in objects, can't lookup
  130. // SDK doesn't specify an exception to throw, so just return null
  131. if (! FNamespaceAware) // NOT _namespaceAware
  132. return null;
  133. for (int i = 0; i < FnodeList.Count; i++)
  134. {
  135. XmlNode cur = FnodeList[i] as XmlNode;
  136. if ((cur.Name == localName) & (cur.NamespaceURI == namespaceURI))
  137. {
  138. FnodeList.RemoveAt(i);
  139. return cur;
  140. }
  141. }
  142. return null;
  143. }
  144. /// <summary>
  145. /// Adds the passed node using the name property
  146. /// If a node with this name exists, it is returned, otherwise null is returned.
  147. /// </summary>
  148. /// <exception cref="ArgumentException">Raised if node was created from another docuement, or XmlNamedNodeMap is read-only</exception>
  149. /// <exception cref="InvalidOperationException">Node is an XmlAttribute of another XmlElement</exception>
  150. /// <param name="node"></param>
  151. /// <returns></returns>
  152. public virtual XmlNode SetNamedItem(XmlNode node)
  153. {
  154. XmlNode retValue ; // Return value of method
  155. // Can't add to read-only Map
  156. if (FIsReadonly)
  157. throw new ArgumentException("Attempt to add node to read-only Node Map");
  158. //if FOwner.OwnerDocument <> arg.OwnerDocument then raise EWrong_Document_Err
  159. if (! FOwner.OwnerDocument.Equals(node.OwnerDocument))
  160. throw new ArgumentException("Cannot add node from another document");
  161. // if FNamespaceAware then raise ENamespace_Err.create('Namespace error.');
  162. if (FNamespaceAware)
  163. throw new InvalidOperationException("Invalid Operation: Can't add node by name to namespace aware node list");
  164. // Can't assign node that has a parent
  165. // TODO - is this check required/valid in the .NET API?
  166. //if assigned(arg.parentNode) then raise EInuse_Node_Err.create('In use node error.');
  167. if (node.ParentNode != null)
  168. throw new ArgumentException("In use node error");
  169. // XmlAttribute cannot be assigned to an element
  170. //if arg.NodeType = ntAttribute_Node
  171. // then if assigned((arg as TdomAttr).OwnerElement)
  172. // then if (arg as TdomAttr).OwnerElement <> FOwnerNode then raise EInuse_Attribute_Err.create('Inuse attribute error.');
  173. if (node is XmlAttribute)
  174. {
  175. if ((node as XmlAttribute).OwnerElement != null)
  176. {
  177. if (! FOwnerNode.Equals( (node as XmlAttribute).OwnerElement ))
  178. throw new InvalidOperationException("XmlAttribute is assigned to another element");
  179. }
  180. }
  181. /*
  182. if not (arg.NodeType in FAllowedNodeTypes) then raise EHierarchy_Request_Err.create('Hierarchy request error.');
  183. */
  184. if ( GetNamedItem(node.Name) != null)
  185. {
  186. retValue = RemoveNamedItem(node.Name);
  187. }
  188. else
  189. {
  190. retValue = null;
  191. }
  192. FnodeList.Add(node);
  193. // TODO - check that owner is set properly on adding an attribute node
  194. return retValue;
  195. }
  196. // ============ Constructors =========================================
  197. internal XmlNamedNodeMap(XmlNode aOwner, XmlNode aOwnerNode, ArrayList nodeList)
  198. {
  199. if (nodeList == null)
  200. nodeList = new ArrayList();
  201. else
  202. FnodeList = nodeList;
  203. FOwner = aOwner;
  204. FOwnerNode = aOwnerNode;
  205. FIsReadonly = false;
  206. FNamespaceAware = false;
  207. }
  208. // Add a default costructor to satisfy Visual Studio....
  209. // TODO - figure out a way to get rid of default constructor on XmlNamedNodeMap()
  210. internal XmlNamedNodeMap()
  211. {
  212. FnodeList = new ArrayList();
  213. FOwner = null;
  214. FOwnerNode = null;
  215. FIsReadonly = false;
  216. FNamespaceAware = false;
  217. }
  218. // ============ Internal Properties ===================================
  219. //=====================================================================
  220. internal bool IsReadOnly
  221. {
  222. get
  223. {
  224. return FIsReadonly;
  225. }
  226. set
  227. {
  228. FIsReadonly = value;
  229. }
  230. }
  231. internal bool NamespaceAware
  232. {
  233. get
  234. {
  235. return FNamespaceAware;
  236. }
  237. set
  238. {
  239. FNamespaceAware = value;
  240. }
  241. }
  242. }
  243. }