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;
25 public XmlNamespaceManager (XmlNameTable nameTable)
27 this.nameTable = nameTable;
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");
36 currentScope.Namespaces = new Hashtable ();
37 currentScope.Namespaces.Add ("xml", "http://www.w3.org/XML/1998/namespace");
38 currentScope.Namespaces.Add ("xmlns", "http://www.w3.org/2000/xmlns/");
45 public virtual string DefaultNamespace {
46 get { return LookupNamespace (String.Empty); }
49 public XmlNameTable NameTable {
50 get { return nameTable; }
57 public virtual void AddNamespace (string prefix, string uri)
60 throw new ArgumentNullException ("prefix", "Value cannot be null.");
63 throw new ArgumentNullException ("uri", "Value cannot be null.");
65 if (prefix.Length > 2 && prefix.Substring (0, 3).ToLower () == "xml")
66 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");
68 if (currentScope.Namespaces == null)
69 currentScope.Namespaces = new Hashtable ();
71 if (prefix != String.Empty)
72 nameTable.Add (prefix);
73 currentScope.Namespaces [prefix] = nameTable.Add (uri);
76 public virtual IEnumerator GetEnumerator ()
78 if (currentScope.Namespaces == null)
79 currentScope.Namespaces = new Hashtable ();
81 return currentScope.Namespaces.Keys.GetEnumerator ();
84 public virtual bool HasNamespace (string prefix)
86 return currentScope != null && currentScope.Namespaces != null && currentScope.Namespaces.Contains (prefix);
89 public virtual string LookupNamespace (string prefix)
91 NamespaceScope scope = currentScope;
93 while (scope != null) {
94 if (scope.Namespaces != null && scope.Namespaces.Contains (prefix))
95 return scope.Namespaces[prefix] as string;
101 return nameTable.Get ("http://www.w3.org/2000/xmlns/");
103 return nameTable.Get ("http://www.w3.org/XML/1998/namespace");
105 return nameTable.Get (String.Empty);
111 public virtual string LookupPrefix (string uri)
116 NamespaceScope scope = currentScope;
118 while (scope != null)
120 if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
121 foreach (DictionaryEntry entry in scope.Namespaces) {
122 if (entry.Value.ToString() == uri)
123 return nameTable.Get (entry.Key as string) as string;
130 // ECMA specifies that this method returns String.Empty
131 // in case of no match. But actually MS.NET returns null.
132 // For more information,see
133 // http://lists.ximian.com/archives/public/mono-list/2003-January/005071.html
134 //return String.Empty;
138 public virtual bool PopScope ()
140 if (currentScope != null)
141 currentScope = currentScope.Next;
143 return currentScope != null;
146 public virtual void PushScope ()
148 NamespaceScope newScope = new NamespaceScope ();
149 newScope.Next = currentScope;
150 currentScope = newScope;
153 public virtual void RemoveNamespace (string prefix, string uri)
156 throw new ArgumentNullException ("prefix");
159 throw new ArgumentNullException ("uri");
161 if (currentScope == null || currentScope.Namespaces == null)
164 string p = nameTable.Get (prefix);
165 string u = nameTable.Get (uri);
166 if (p == null || u == null)
169 string storedUri = currentScope.Namespaces [p] as string;
170 if (storedUri == null || storedUri != u)
173 currentScope.Namespaces.Remove (p);
179 internal class NamespaceScope
181 internal NamespaceScope Next;
182 internal Hashtable Namespaces;