[Xml] Fix GetAttribute to handle null namespaces properly, add unit test.
[mono.git] / mcs / class / System.XML / System.Xml / DTDObjectModel.cs
index 313a5f33b414c70266cdb95930dd526cc9432f41..bbe073f6f13c6461611e3d586245fff56805aa98 100644 (file)
@@ -34,7 +34,14 @@ using System.IO;
 using System.Text;
 using System.Xml;
 using System.Xml.Schema;
+#if NET_2_0
+using System.Collections.Generic;
+#endif
+#if NET_2_1
+using XmlSchemaException = System.Xml.XmlException;
+#else
 using Mono.Xml.Schema;
+#endif
 
 #if NET_2_0
 using XmlTextReaderImpl = Mono.Xml2.XmlTextReader;
@@ -141,6 +148,7 @@ namespace Mono.Xml
                        set { linePosition = value; }
                }
 
+#if !NET_2_1
                internal XmlSchema CreateXsdSchema ()
                {
                        XmlSchema s = new XmlSchema ();
@@ -151,14 +159,19 @@ namespace Mono.Xml
                                s.Items.Add (el.CreateXsdElement ());
                        return s;
                }
+#endif
 
                public string ResolveEntity (string name)
                {
                        DTDEntityDeclaration decl = EntityDecls [name] 
                                as DTDEntityDeclaration;
                        if (decl == null) {
+#if NET_2_1
+                               AddError (new XmlSchemaException (String.Format ("Required entity was not found: {0}", name), null, this.LineNumber, this.LinePosition));
+#else
                                AddError (new XmlSchemaException ("Required entity was not found.",
                                        this.LineNumber, this.LinePosition, null, this.BaseURI, null));
+#endif
                                return " ";
                        }
                        else
@@ -270,6 +283,17 @@ namespace Mono.Xml
                }
        }
 
+#if NET_2_0
+       class DictionaryBase : List<KeyValuePair<string,DTDNode>>
+       {
+               public IEnumerable<DTDNode> Values {
+                       get {
+                               foreach (KeyValuePair<string,DTDNode> p in this)
+                                       yield return p.Value;
+                       }
+               }
+       }
+#endif
        internal class DTDCollectionBase : DictionaryBase
        {
                DTDObjectModel root;
@@ -283,6 +307,32 @@ namespace Mono.Xml
                        get { return root; }
                }
 
+#if NET_2_0
+               public DictionaryBase InnerHashtable {
+                       get { return this; }
+               }
+
+               protected void BaseAdd (string name, DTDNode value)
+               {
+                       base.Add (new KeyValuePair<string,DTDNode> (name, value));
+               }
+
+               public bool Contains (string key)
+               {
+                       foreach (KeyValuePair<string,DTDNode> p in this)
+                               if (p.Key == key)
+                                       return true;
+                       return false;
+               }
+
+               protected object BaseGet (string name)
+               {
+                       foreach (KeyValuePair<string,DTDNode> p in this)
+                               if (p.Key == name)
+                                       return p.Value;
+                       return null;
+               }
+#else
                public ICollection Keys {
                        get { return InnerHashtable.Keys; }
                }
@@ -290,6 +340,22 @@ namespace Mono.Xml
                public ICollection Values {
                        get { return InnerHashtable.Values; }
                }
+
+               protected void BaseAdd (string name, object value)
+               {
+                       InnerHashtable.Add (name, value);
+               }
+
+               public bool Contains (string key)
+               {
+                       return InnerHashtable.Contains (key);
+               }
+
+               protected object BaseGet (string name)
+               {
+                       return InnerHashtable [name];
+               }
+#endif
        }
 
        internal class DTDElementDeclarationCollection : DTDCollectionBase
@@ -303,19 +369,19 @@ namespace Mono.Xml
 
                public DTDElementDeclaration Get (string name)
                {
-                       return InnerHashtable [name] as DTDElementDeclaration;
+                       return BaseGet (name) as DTDElementDeclaration;
                }
 
                public void Add (string name, DTDElementDeclaration decl)
                {
-                       if (InnerHashtable.Contains (name)) {
+                       if (Contains (name)) {
                                Root.AddError (new XmlSchemaException (String.Format (
                                        "Element declaration for {0} was already added.",
                                        name), null));
                                return;
                        }
                        decl.SetRoot (Root);
-                       InnerHashtable.Add (name, decl);
+                       BaseAdd (name, decl);
                }
        }
 
@@ -324,7 +390,7 @@ namespace Mono.Xml
                public DTDAttListDeclarationCollection (DTDObjectModel root) : base (root) {}
 
                public DTDAttListDeclaration this [string name] {
-                       get { return InnerHashtable [name] as DTDAttListDeclaration; }
+                       get { return BaseGet (name) as DTDAttListDeclaration; }
                }
 
                public void Add (string name, DTDAttListDeclaration decl)
@@ -337,7 +403,7 @@ namespace Mono.Xml
                                                existing.Add (def);
                        } else {
                                decl.SetRoot (Root);
-                               InnerHashtable.Add (name, decl);
+                               BaseAdd (name, decl);
                        }
                }
        }
@@ -347,17 +413,17 @@ namespace Mono.Xml
                public DTDEntityDeclarationCollection (DTDObjectModel root) : base (root) {}
 
                public DTDEntityDeclaration this [string name] {
-                       get { return InnerHashtable [name] as DTDEntityDeclaration; }
+                       get { return BaseGet (name) as DTDEntityDeclaration; }
                }
 
                public void Add (string name, DTDEntityDeclaration decl)
                {
-                       if (InnerHashtable [name] != null)
+                       if (Contains (name))
                                throw new InvalidOperationException (String.Format (
                                        "Entity declaration for {0} was already added.",
                                        name));
                        decl.SetRoot (Root);
-                       InnerHashtable.Add (name, decl);
+                       BaseAdd (name, decl);
                }
        }
 
@@ -366,17 +432,17 @@ namespace Mono.Xml
                public DTDNotationDeclarationCollection (DTDObjectModel root) : base (root) {}
 
                public DTDNotationDeclaration this [string name] {
-                       get { return InnerHashtable [name] as DTDNotationDeclaration; }
+                       get { return BaseGet (name) as DTDNotationDeclaration; }
                }
 
                public void Add (string name, DTDNotationDeclaration decl)
                {
-                       if (InnerHashtable [name] != null)
+                       if (Contains (name))
                                throw new InvalidOperationException (String.Format (
                                        "Notation declaration for {0} was already added.",
                                        name));
                        decl.SetRoot (Root);
-                       InnerHashtable.Add (name, decl);
+                       BaseAdd (name, decl);
                }
        }
 
@@ -435,6 +501,7 @@ namespace Mono.Xml
                        return compiledAutomata;
                }
 
+#if !NET_2_1
                internal XmlSchemaParticle CreateXsdParticle ()
                {
                        XmlSchemaParticle p = CreateXsdParticleCore ();
@@ -483,6 +550,7 @@ namespace Mono.Xml
                        }
                        return p;
                }
+#endif
 
                private DTDAutomata CompileInternal ()
                {
@@ -626,12 +694,14 @@ namespace Mono.Xml
                        return new XmlException (this as IXmlLineInfo, BaseURI, message);
                }
 
+#if !NET_2_1
                public void SetLineInfo (XmlSchemaObject obj)
                {
                        obj.SourceUri = BaseURI;
                        obj.LineNumber = LineNumber;
                        obj.LinePosition = LinePosition;
                }
+#endif
        }
 
        internal class DTDElementDeclaration : DTDNode
@@ -681,6 +751,7 @@ namespace Mono.Xml
                        }
                }
 
+#if !NET_2_1
                internal XmlSchemaElement CreateXsdElement ()
                {
                        XmlSchemaElement el = new XmlSchemaElement ();
@@ -732,6 +803,7 @@ namespace Mono.Xml
                        */
                        return el;
                }
+#endif
        }
 
        internal class DTDAttributeDefinition : DTDNode
@@ -825,6 +897,7 @@ namespace Mono.Xml
                        }
                }
 
+#if !NET_2_1
                internal XmlSchemaAttribute CreateXsdAttribute ()
                {
                        XmlSchemaAttribute a = new XmlSchemaAttribute ();
@@ -885,6 +958,7 @@ namespace Mono.Xml
                                a.SchemaTypeName = qname;
                        return a;
                }
+#endif
 
                internal string ComputeDefaultValue ()
                {
@@ -1087,7 +1161,7 @@ namespace Mono.Xml
                                if (Root.ExternalResources.Count > DTDObjectModel.AllowedExternalEntitiesMax)
                                        throw new InvalidOperationException ("The total amount of external entities exceeded the allowed number.");
 
-                       } catch (Exception ex) {
+                       } catch (Exception) {
 //                             loadException = ex;
                                LiteralEntityValue = String.Empty;
                                LoadFailed = true;
@@ -1212,8 +1286,12 @@ namespace Mono.Xml
                                }
                        }
                        if (start != 0)
+#if NET_2_1
+                               Root.AddError (new XmlSchemaException (this, this.BaseURI, "Invalid reference character '&' is specified."));
+#else
                                Root.AddError (new XmlSchemaException ("Invalid reference character '&' is specified.",
                                        this.LineNumber, this.LinePosition, null, this.BaseURI, null));
+#endif
                        scanned = true;
                        recursed = false;
                }