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 ("xml", XmlnsXml);
41 currentScope.Namespaces.Add ("xmlns", XmlnsXmlns);
48 public virtual string DefaultNamespace {
49 get { return LookupNamespace (String.Empty); }
52 public XmlNameTable NameTable {
53 get { return nameTable; }
60 public virtual void AddNamespace (string prefix, string uri)
63 throw new ArgumentNullException ("prefix", "Value cannot be null.");
66 throw new ArgumentNullException ("uri", "Value cannot be null.");
68 IsValidDeclaration (prefix, uri, true);
70 if (currentScope.Namespaces == null)
71 currentScope.Namespaces = new Hashtable ();
73 if (prefix != String.Empty)
74 nameTable.Add (prefix);
75 currentScope.Namespaces [prefix] = nameTable.Add (uri);
78 internal static string IsValidDeclaration (string prefix, string uri, bool throwException)
80 string message = null;
81 if (prefix == "xml" && uri != XmlnsXml)
82 message = String.Format ("Prefix \"xml\" is only allowed to the fixed uri \"{0}\"", XmlnsXml);
83 else if (uri == XmlnsXml)
84 message = String.Format ("Namespace URI \"{0}\" can only be declared with the fixed prefix \"xml\"", XmlnsXml);
85 if (message == null && prefix == "xmlns")
86 message = "Declaring prefix named \"xmlns\" is not allowed to any namespace.";
87 if (message == null && uri == XmlnsXmlns)
88 message = String.Format ("Namespace URI \"{0}\" cannot be declared with any namespace.", XmlnsXmlns);
89 if (message != null && throwException)
90 throw new ArgumentException (message);
95 public virtual IEnumerator GetEnumerator ()
97 if (currentScope.Namespaces == null)
98 currentScope.Namespaces = new Hashtable ();
100 return currentScope.Namespaces.Keys.GetEnumerator ();
103 public virtual bool HasNamespace (string prefix)
105 return currentScope != null && currentScope.Namespaces != null && currentScope.Namespaces.Contains (prefix);
108 public virtual string LookupNamespace (string prefix)
110 NamespaceScope scope = currentScope;
112 while (scope != null) {
113 if (scope.Namespaces != null && scope.Namespaces.Contains (prefix))
114 return scope.Namespaces[prefix] as string;
120 return nameTable.Get (XmlnsXmlns);
122 return nameTable.Get (XmlnsXml);
124 return nameTable.Get (String.Empty);
130 public virtual string LookupPrefix (string uri)
135 NamespaceScope scope = currentScope;
137 while (scope != null)
139 if (scope.Namespaces != null && scope.Namespaces.ContainsValue (uri)) {
140 foreach (DictionaryEntry entry in scope.Namespaces) {
141 if (entry.Value.ToString() == uri)
142 return nameTable.Get (entry.Key as string) as string;
149 // ECMA specifies that this method returns String.Empty
150 // in case of no match. But actually MS.NET returns null.
151 // For more information,see
152 // http://lists.ximian.com/archives/public/mono-list/2003-January/005071.html
153 //return String.Empty;
157 public virtual bool PopScope ()
159 if (currentScope != null)
160 currentScope = currentScope.Next;
162 return currentScope != null;
165 public virtual void PushScope ()
167 NamespaceScope newScope = new NamespaceScope ();
168 newScope.Next = currentScope;
169 currentScope = newScope;
172 public virtual void RemoveNamespace (string prefix, string uri)
175 throw new ArgumentNullException ("prefix");
178 throw new ArgumentNullException ("uri");
180 if (currentScope == null || currentScope.Namespaces == null)
183 string p = nameTable.Get (prefix);
184 string u = nameTable.Get (uri);
185 if (p == null || u == null)
188 string storedUri = currentScope.Namespaces [p] as string;
189 if (storedUri == null || storedUri != u)
192 currentScope.Namespaces.Remove (p);
198 internal class NamespaceScope
200 internal NamespaceScope Next;
201 internal Hashtable Namespaces;