2002-11-24 Duncan Mak <duncan@ximian.com>
[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                 public virtual IEnumerator GetEnumerator ()
75                 {
76                         if (currentScope.Namespaces == null)
77                                 currentScope.Namespaces = new Hashtable ();
78
79                         return currentScope.Namespaces.Keys.GetEnumerator ();
80                 }
81
82                 public virtual bool HasNamespace (string prefix)
83                 {
84                         return currentScope != null && currentScope.Namespaces != null && currentScope.Namespaces.Contains (prefix);
85                 }
86
87                 public virtual string LookupNamespace (string prefix)
88                 {
89                         NamespaceScope scope = currentScope;
90
91                         while (scope != null) {
92                                 if (scope.Namespaces != null && scope.Namespaces.Contains (prefix))
93                                         return scope.Namespaces[prefix] as string;
94                                 scope = scope.Next;
95                         }
96
97                         switch (prefix) {
98                         case "xmlns":
99                                 return nameTable.Get ("http://www.w3.org/2000/xmlns/");
100                         case "xml":
101                                 return nameTable.Get ("http://www.w3.org/XML/1998/namespace");
102                         case "":
103                                 return nameTable.Get (String.Empty);
104                         }
105
106                         return null;
107                 }
108
109                 public virtual string LookupPrefix (string uri)
110                 {
111                         if (uri == null)
112                                 return null;
113
114                         NamespaceScope scope = currentScope;
115
116                         while (scope != null) 
117                         {
118                                 if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
119                                         foreach (DictionaryEntry entry in scope.Namespaces) {
120                                                 if (entry.Value.ToString() == uri)
121                                                         return nameTable.Get (entry.Key as string) as string;
122                                         }
123                                 }
124
125                                 scope = scope.Next;
126                         }
127
128                         return String.Empty;
129                 }
130
131                 public virtual bool PopScope ()
132                 {
133                         if (currentScope != null)
134                                 currentScope = currentScope.Next;
135
136                         return currentScope != null;
137                 }
138
139                 public virtual void PushScope ()
140                 {
141                         NamespaceScope newScope = new NamespaceScope ();
142                         newScope.Next = currentScope;
143                         currentScope = newScope;
144                 }
145
146                 public virtual void RemoveNamespace (string prefix, string uri)
147                 {
148                         if (prefix == null)
149                                 throw new ArgumentNullException ("prefix");
150
151                         if (uri == null)
152                                 throw new ArgumentNullException ("uri");
153
154                         if (currentScope == null || currentScope.Namespaces == null)
155                                 return;
156
157                         string p = nameTable.Get (prefix);
158                         string u = nameTable.Get (uri);
159                         if (p == null || u == null)
160                                 return;
161                                 
162                         string storedUri = currentScope.Namespaces [p] as string;
163                         if (storedUri == null || storedUri != u)
164                                 return;
165
166                         currentScope.Namespaces.Remove (p);
167                 }
168
169                 #endregion
170         }
171
172         internal class NamespaceScope
173         {
174                 internal NamespaceScope Next;
175                 internal Hashtable Namespaces;
176         }
177 }