2 // XmlNamespaceManager.cs
5 // Jason Diamond (jason@injektilo.org)
7 // (C) 2001 Jason Diamond http://injektilo.org/
10 using System.Collections;
14 public class XmlNamespaceManager : IEnumerable
18 private XmlNameTable nameTable;
19 private NamespaceScope currentScope;
20 internal const string XmlnsXml = "http://www.w3.org/XML/1998/namespace";
21 internal const string XmlnsXmlns = "http://www.w3.org/2000/xmlns/";
27 internal XmlNamespaceManager () {}
28 public XmlNamespaceManager (XmlNameTable nameTable)
30 this.nameTable = nameTable;
32 nameTable.Add ("xmlns");
33 nameTable.Add ("xml");
34 nameTable.Add (String.Empty);
35 nameTable.Add (XmlnsXmlns);
36 nameTable.Add (XmlnsXml);
39 currentScope.Namespaces = new Hashtable ();
40 currentScope.Namespaces.Add ("", "");
41 currentScope.Namespaces.Add ("xml", XmlnsXml);
42 currentScope.Namespaces.Add ("xmlns", XmlnsXmlns);
49 public virtual string DefaultNamespace {
50 get { return LookupNamespace (String.Empty); }
53 public XmlNameTable NameTable {
54 get { return nameTable; }
61 public virtual void AddNamespace (string prefix, string uri)
64 throw new ArgumentNullException ("prefix", "Value cannot be null.");
67 throw new ArgumentNullException ("uri", "Value cannot be null.");
69 IsValidDeclaration (prefix, uri, true);
71 if (currentScope.Namespaces == null)
72 currentScope.Namespaces = new Hashtable ();
74 if (prefix != String.Empty)
75 nameTable.Add (prefix);
76 currentScope.Namespaces [prefix] = nameTable.Add (uri);
79 internal static string IsValidDeclaration (string prefix, string uri, bool throwException)
81 string message = null;
82 if (prefix == "xml" && uri != XmlnsXml)
83 message = String.Format ("Prefix \"xml\" is only allowed to the fixed uri \"{0}\"", XmlnsXml);
84 else if (uri == XmlnsXml)
85 message = String.Format ("Namespace URI \"{0}\" can only be declared with the fixed prefix \"xml\"", XmlnsXml);
86 if (message == null && prefix == "xmlns")
87 message = "Declaring prefix named \"xmlns\" is not allowed to any namespace.";
88 if (message == null && uri == XmlnsXmlns)
89 message = String.Format ("Namespace URI \"{0}\" cannot be declared with any namespace.", XmlnsXmlns);
90 if (message != null && throwException)
91 throw new ArgumentException (message);
96 public virtual IEnumerator GetEnumerator ()
99 if (currentScope.Namespaces == null)
100 currentScope.Namespaces = new Hashtable ();
102 return currentScope.Namespaces.Keys.GetEnumerator ();
105 // In fact it returns such table's enumerator that contains all the namespaces.
106 // while HasNamespace() ignores pushed namespaces.
107 Hashtable ht = new Hashtable ();
108 NamespaceScope scope = currentScope;
110 while (scope != null) {
111 if (scope.Namespaces != null) {
112 IEnumerator e = scope.Namespaces.Keys.GetEnumerator ();
113 while (e.MoveNext ()) {
114 if (!ht.ContainsKey (e.Current))
115 ht.Add (e.Current, scope.Namespaces [e.Current]);
120 return ht.Keys.GetEnumerator ();
123 public virtual bool HasNamespace (string prefix)
125 return currentScope != null && currentScope.Namespaces != null && currentScope.Namespaces.Contains (prefix);
128 public virtual string LookupNamespace (string prefix)
130 NamespaceScope scope = currentScope;
132 while (scope != null) {
133 if (scope.Namespaces != null && scope.Namespaces.Contains (prefix))
134 return scope.Namespaces[prefix] as string;
140 return nameTable.Get (XmlnsXmlns);
142 return nameTable.Get (XmlnsXml);
144 return nameTable.Get (String.Empty);
150 public virtual string LookupPrefix (string uri)
155 NamespaceScope scope = currentScope;
157 while (scope != null)
159 if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
160 foreach (DictionaryEntry entry in scope.Namespaces) {
161 if (entry.Value.ToString() == uri)
162 return nameTable.Get (entry.Key as string) as string;
169 // ECMA specifies that this method returns String.Empty
170 // in case of no match. But actually MS.NET returns null.
171 // For more information,see
172 // http://lists.ximian.com/archives/public/mono-list/2003-January/005071.html
173 //return String.Empty;
177 public virtual bool PopScope ()
179 if (currentScope != null)
180 currentScope = currentScope.Next;
182 return currentScope != null;
185 public virtual void PushScope ()
187 NamespaceScope newScope = new NamespaceScope ();
188 newScope.Next = currentScope;
189 currentScope = newScope;
192 public virtual void RemoveNamespace (string prefix, string uri)
195 throw new ArgumentNullException ("prefix");
198 throw new ArgumentNullException ("uri");
200 if (currentScope == null || currentScope.Namespaces == null)
203 string p = nameTable.Get (prefix);
204 string u = nameTable.Get (uri);
205 if (p == null || u == null)
208 string storedUri = currentScope.Namespaces [p] as string;
209 if (storedUri == null || storedUri != u)
212 currentScope.Namespaces.Remove (p);
218 internal class NamespaceScope
220 internal NamespaceScope Next;
221 internal Hashtable Namespaces;