implementing XmlElement.SetAttributeNode(localName, namespaceURI) and
[mono.git] / mcs / class / System.XML / System.Xml / XmlNamespaceManager.cs
1 //
2 // XmlNamespaceManager.cs
3 //
4 // Author:
5 //   Jason Diamond (jason@injektilo.org)
6 //
7 // (C) 2001 Jason Diamond  http://injektilo.org/
8 //
9
10 using System.Collections;
11
12 namespace System.Xml
13 {
14         public class XmlNamespaceManager : IEnumerable
15         {
16                 #region Fields
17
18                 private XmlNameTable nameTable;
19                 private NamespaceScope currentScope;
20
21                 #endregion
22
23                 #region Constructor
24
25                 public XmlNamespaceManager (XmlNameTable nameTable)
26                 {
27                         this.nameTable = nameTable;
28
29                         nameTable.Add ("xmlns");
30                         nameTable.Add ("xml");
31                         nameTable.Add (String.Empty);
32                         nameTable.Add ("http://www.w3.org/2000/xmlns/");
33                         nameTable.Add ("http://www.w3.org/XML/1998/namespace");
34
35                         PushScope ();
36                 }
37
38                 #endregion
39
40                 #region Properties
41
42                 public virtual string DefaultNamespace {
43                         get { return LookupNamespace (String.Empty); }
44                 }
45
46                 public XmlNameTable NameTable {
47                         get { return nameTable; }
48                 }
49
50                 #endregion
51
52                 #region Methods
53
54                 public virtual void AddNamespace (string prefix, string uri)
55                 {
56                         if (prefix == null)
57                                 throw new ArgumentNullException ("prefix", "Value cannot be null.");
58
59                         if (uri == null)
60                                 throw new ArgumentNullException ("uri", "Value cannot be null.");
61
62                         if (prefix.Length > 2 && prefix.Substring (0, 3).ToLower () == "xml")
63                                 throw new ArgumentException ("Prefixes beginning with \"xml\" (regardless of whether the characters are uppercase, lowercase, or some combination thereof) are reserved for use by XML.", "prefix");
64
65                         if (currentScope.Namespaces == null)
66                                 currentScope.Namespaces = new Hashtable ();
67
68                         if (prefix == String.Empty)
69                                 currentScope.Namespaces [prefix] = nameTable.Add (uri);
70                         else
71                                 currentScope.Namespaces.Add (nameTable.Add (prefix), nameTable.Add (uri));
72                 }
73
74                 [MonoTODO]
75                 public virtual IEnumerator GetEnumerator ()
76                 {
77                         throw new NotImplementedException ();
78                 }
79
80                 public virtual bool HasNamespace (string prefix)
81                 {
82                         return currentScope != null && currentScope.Namespaces != null && currentScope.Namespaces.Contains (prefix);
83                 }
84
85                 public virtual string LookupNamespace (string prefix)
86                 {
87                         NamespaceScope scope = currentScope;
88
89                         while (scope != null) {
90                                 if (scope.Namespaces != null && scope.Namespaces.Contains (prefix))
91                                         return scope.Namespaces[prefix] as string;
92                                 scope = scope.Next;
93                         }
94
95                         switch (prefix) {
96                         case "xmlns":
97                                 return nameTable.Get ("http://www.w3.org/2000/xmlns/");
98                         case "xml":
99                                 return nameTable.Get ("http://www.w3.org/XML/1998/namespace");
100                         case "":
101                                 return nameTable.Get (String.Empty);
102                         }
103
104                         return null;
105                 }
106
107                 public virtual string LookupPrefix (string uri)
108                 {
109                         if (uri == null)
110                                 return null;
111
112                         NamespaceScope scope = currentScope;
113
114                         while (scope != null) 
115                         {
116                                 if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
117                                         foreach (DictionaryEntry entry in scope.Namespaces) {
118                                                 if (entry.Value.ToString() == uri)
119                                                         return nameTable.Get (entry.Key as string) as string;
120                                         }
121                                 }
122
123                                 scope = scope.Next;
124                         }
125
126                         return String.Empty;
127                 }
128
129                 public virtual bool PopScope ()
130                 {
131                         if (currentScope != null)
132                                 currentScope = currentScope.Next;
133
134                         return currentScope != null;
135                 }
136
137                 public virtual void PushScope ()
138                 {
139                         NamespaceScope newScope = new NamespaceScope ();
140                         newScope.Next = currentScope;
141                         currentScope = newScope;
142                 }
143
144                 [MonoTODO]
145                 public virtual void RemoveNamespace (string prefix, string uri)
146                 {
147                         throw new NotImplementedException ();
148                 }
149
150                 #endregion
151         }
152
153         internal class NamespaceScope
154         {
155                 internal NamespaceScope Next;
156                 internal Hashtable Namespaces;
157         }
158 }