[Xml] Fix GetAttribute to handle null namespaces properly, add unit test.
[mono.git] / mcs / class / System.XML / System.Xml / DTDObjectModel.cs
index 715f4596651789fa0183b87ad2b1dac63ae221bd..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
@@ -246,7 +259,6 @@ namespace Mono.Xml
                        validationErrors.Add (ex);
                }
 
-#if NET_2_0
                internal string GenerateEntityAttributeText (string entityName)
                {
                        DTDEntityDeclaration entity = EntityDecls [entityName] as DTDEntityDeclaration;
@@ -269,9 +281,19 @@ namespace Mono.Xml
                        else
                                return new XmlTextReaderImpl (entity.EntityValue, XmlNodeType.Element, context);
                }
-#endif
        }
 
+#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;
@@ -285,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; }
                }
@@ -292,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
@@ -305,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);
                }
        }
 
@@ -326,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)
@@ -339,7 +403,7 @@ namespace Mono.Xml
                                                existing.Add (def);
                        } else {
                                decl.SetRoot (Root);
-                               InnerHashtable.Add (name, decl);
+                               BaseAdd (name, decl);
                        }
                }
        }
@@ -349,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);
                }
        }
 
@@ -368,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);
                }
        }
 
@@ -437,7 +501,29 @@ namespace Mono.Xml
                        return compiledAutomata;
                }
 
+#if !NET_2_1
                internal XmlSchemaParticle CreateXsdParticle ()
+               {
+                       XmlSchemaParticle p = CreateXsdParticleCore ();
+                       if (p == null)
+                               return null;
+
+                       switch (Occurence) {
+                       case DTDOccurence.Optional:
+                               p.MinOccurs = 0;
+                               break;
+                       case DTDOccurence.OneOrMore:
+                               p.MaxOccursString = "unbounded";
+                               break;
+                       case DTDOccurence.ZeroOrMore:
+                               p.MinOccurs = 0;
+                               p.MaxOccursString = "unbounded";
+                               break;
+                       }
+                       return p;
+               }
+
+               XmlSchemaParticle CreateXsdParticleCore ()
                {
                        XmlSchemaParticle p = null;
                        if (ElementName != null) {
@@ -462,20 +548,9 @@ namespace Mono.Xml
                                }
                                p = gb;
                        }
-                       switch (Occurence) {
-                       case DTDOccurence.Optional:
-                               p.MinOccurs = 0;
-                               break;
-                       case DTDOccurence.OneOrMore:
-                               p.MaxOccursString = "unbounded";
-                               break;
-                       case DTDOccurence.ZeroOrMore:
-                               p.MinOccurs = 0;
-                               p.MaxOccursString = "unbounded";
-                               break;
-                       }
                        return p;
                }
+#endif
 
                private DTDAutomata CompileInternal ()
                {
@@ -619,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
@@ -674,6 +751,7 @@ namespace Mono.Xml
                        }
                }
 
+#if !NET_2_1
                internal XmlSchemaElement CreateXsdElement ()
                {
                        XmlSchemaElement el = new XmlSchemaElement ();
@@ -725,6 +803,7 @@ namespace Mono.Xml
                        */
                        return el;
                }
+#endif
        }
 
        internal class DTDAttributeDefinition : DTDNode
@@ -818,12 +897,15 @@ namespace Mono.Xml
                        }
                }
 
+#if !NET_2_1
                internal XmlSchemaAttribute CreateXsdAttribute ()
                {
                        XmlSchemaAttribute a = new XmlSchemaAttribute ();
                        SetLineInfo (a);
                        a.Name = Name;
                        a.DefaultValue = resolvedNormalizedDefaultValue;
+                       if (OccurenceType != DTDAttributeOccurenceType.Required)
+                               a.Use = XmlSchemaUse.Optional;
 
                        XmlQualifiedName qname = XmlQualifiedName.Empty;
                        ArrayList enumeration = null;
@@ -876,6 +958,7 @@ namespace Mono.Xml
                                a.SchemaTypeName = qname;
                        return a;
                }
+#endif
 
                internal string ComputeDefaultValue ()
                {
@@ -1078,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;
@@ -1203,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;
                }