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) {
134 string s = scope.Namespaces [prefix] as string;
135 if (s != null) return s;
142 return nameTable.Get (XmlnsXmlns);
144 return nameTable.Get (XmlnsXml);
146 return nameTable.Get (String.Empty);
152 public virtual string LookupPrefix (string uri)
157 NamespaceScope scope = currentScope;
159 while (scope != null)
161 if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
162 foreach (DictionaryEntry entry in scope.Namespaces) {
163 if (entry.Value.ToString() == uri)
164 return nameTable.Get (entry.Key as string) as string;
171 // ECMA specifies that this method returns String.Empty
172 // in case of no match. But actually MS.NET returns null.
173 // For more information,see
174 // http://lists.ximian.com/archives/public/mono-list/2003-January/005071.html
175 //return String.Empty;
179 public virtual bool PopScope ()
181 if (currentScope != null)
182 currentScope = currentScope.Next;
184 return currentScope != null;
187 public virtual void PushScope ()
189 NamespaceScope newScope = new NamespaceScope ();
190 newScope.Next = currentScope;
191 currentScope = newScope;
194 public virtual void RemoveNamespace (string prefix, string uri)
197 throw new ArgumentNullException ("prefix");
200 throw new ArgumentNullException ("uri");
202 if (currentScope == null || currentScope.Namespaces == null)
205 string p = nameTable.Get (prefix);
206 string u = nameTable.Get (uri);
207 if (p == null || u == null)
210 string storedUri = currentScope.Namespaces [p] as string;
211 if (storedUri == null || storedUri != u)
214 currentScope.Namespaces.Remove (p);
220 internal class NamespaceScope
222 internal NamespaceScope Next;
223 internal Hashtable Namespaces;