2003-08-07 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
authorAtsushi Eno <atsushieno@gmail.com>
Thu, 7 Aug 2003 22:08:17 +0000 (22:08 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Thu, 7 Aug 2003 22:08:17 +0000 (22:08 -0000)
* DTDObjectModel.cs :
  - Added validation error check (and AddError(), Errors).
  - Fixed ComputeDefaultValue() to handle various references correctly.
  - DTDEntityDeclaration.EntityValue became property, and added
    LiteralEntityValue. The new one holds resolved value.
    Added ResolveExternalEntity(). It now required root in .ctor().
* DTDValidatingReader.cs :
  - Now it handles namespaced attributes (as input to xsd validator).
  - Added XmlResolver property as usual XmlReader.
  - Added currentEntityHandling field so that it can stand changing
    XmlValidatingReader's EntityHandling dynamically.
  - FilterNormalization() now requires name for getting datatypes and
    can stand for non-current attribute normalization.
  - Splitted ReadContent() from Read() that can be called recursively
    when expanding entities.
  - Now handles Entity not found error *after* resolution of entities,
    as MS.NET does.
  - Read()ing DTD checks its Errors and raises validation error events.
    In some situations, DTD parsing may detect VC error, not WFC error.
    It also strictly checks NData existence.
  - Handling of entity-resolved text is a bit changed and Read()ing
    element, endElement, cdata now changed to switch collecting text
    and collected text.
  - content type ANY should allow texts.
  - Added enumerated attribute validity check.
  - Added Name/Names creation rule check for ID/IDREF/IDREFS.
  - Added entity existence check for ENTITY/ENTITIES attributes.
  - Added NMTOKEN creation rule check for NMTOKEN/NMTOKENS.
  - Fixed to remove extraneous #REQUIRED check.
  - Contributing default attribute is now only applied to the case
    ValidationType is DTD or None.
  - ResolveEntity() now handles external entities.
    Added Mono.Xml.IXmlParserContext interface support.
* XmlDocumentType.cs : Fixed to use BaseURI to build DTD model.
* XmlTextReader.cs :
  - Fixed ReadAttributeValue() to reset returnEntityReference.
  - Added bool MaybeTextDecl only for ResolveEntity().
  - Fixed ReadWhitespace(). In fact its value is considered even if it
    is in the end of the XML.
  - Fixed ReadXmlDeclaration(). Now skips text declaration.
  - CompileDTDSubset() now checks IGNORE/INCLUDE section end balances.
  - ReadContentSpec() should set OrderType = OR for mixed model.
    Fixed to set content element name correctly.
  - ImportAsPERef() now skips Text declaration.
  - Type of enumerated default attributes shold be string.
  - Undeclared PE error is now handled as DTD's VC error, not
    XmlTextReader's WFC error.
* XmlValidatingReader.cs : BaseURI should provide that of
  original XmlReader's when read was not started yet.
  Fixed XmlResolver to delegate to DTDValidatingReader.

* XmlAttributeCollection.cs : Acquiring attList declaration is
  insufficient especially in case of lack of elementdecl.
* XmlChar.cs : (Maybe this is compact than XmlConstructs.)
  added IsWhitespace(),IsNCNameChar(),IsName(),IsNCName(),IsNmToken(),
  IsPubid(). Copies IsValidIANAEncoding() from XmlConstructs.

* XmlInputStream.cs : Removed "version" declaration check. It should
  be done by XmlTextReader.

* XmlNodeReader.cs : added internal GetInternalParserContext() and now
  it can be used in XmlValidatingReader.ResolveEntity().
  ResolveEntity() sets XmlTextReader.MaybeTextDecl.

svn path=/trunk/mcs/; revision=17167

mcs/class/System.XML/System.Xml/ChangeLog
mcs/class/System.XML/System.Xml/DTDObjectModel.cs
mcs/class/System.XML/System.Xml/DTDValidatingReader.cs
mcs/class/System.XML/System.Xml/XmlAttributeCollection.cs
mcs/class/System.XML/System.Xml/XmlChar.cs
mcs/class/System.XML/System.Xml/XmlDocumentType.cs
mcs/class/System.XML/System.Xml/XmlInputStream.cs
mcs/class/System.XML/System.Xml/XmlNodeReader.cs
mcs/class/System.XML/System.Xml/XmlTextReader.cs
mcs/class/System.XML/System.Xml/XmlValidatingReader.cs

index 71d28ebd949dda1b2885f81a409e0207e55c9d77..a22a4a8c8f01a829c306fc0f64fad71639ab3a9c 100644 (file)
@@ -1,3 +1,69 @@
+2003-08-07  Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+
+       * DTDObjectModel.cs :
+         - Added validation error check (and AddError(), Errors).
+         - Fixed ComputeDefaultValue() to handle various references correctly.
+         - DTDEntityDeclaration.EntityValue became property, and added
+           LiteralEntityValue. The new one holds resolved value.
+           Added ResolveExternalEntity(). It now required root in .ctor().
+       * DTDValidatingReader.cs :
+         - Now it handles namespaced attributes (as input to xsd validator).
+         - Added XmlResolver property as usual XmlReader.
+         - Added currentEntityHandling field so that it can stand changing
+           XmlValidatingReader's EntityHandling dynamically.
+         - FilterNormalization() now requires name for getting datatypes and
+           can stand for non-current attribute normalization.
+         - Splitted ReadContent() from Read() that can be called recursively
+           when expanding entities.
+         - Now handles Entity not found error *after* resolution of entities,
+           as MS.NET does.
+         - Read()ing DTD checks its Errors and raises validation error events.
+           In some situations, DTD parsing may detect VC error, not WFC error.
+           It also strictly checks NData existence.
+         - Handling of entity-resolved text is a bit changed and Read()ing
+           element, endElement, cdata now changed to switch collecting text
+           and collected text.
+         - content type ANY should allow texts.
+         - Added enumerated attribute validity check.
+         - Added Name/Names creation rule check for ID/IDREF/IDREFS.
+         - Added entity existence check for ENTITY/ENTITIES attributes.
+         - Added NMTOKEN creation rule check for NMTOKEN/NMTOKENS.
+         - Fixed to remove extraneous #REQUIRED check.
+         - Contributing default attribute is now only applied to the case
+           ValidationType is DTD or None.
+         - ResolveEntity() now handles external entities.
+           Added Mono.Xml.IXmlParserContext interface support.
+       * XmlDocumentType.cs : Fixed to use BaseURI to build DTD model.
+       * XmlTextReader.cs :
+         - Fixed ReadAttributeValue() to reset returnEntityReference.
+         - Added bool MaybeTextDecl only for ResolveEntity().
+         - Fixed ReadWhitespace(). In fact its value is considered even if it
+           is in the end of the XML.
+         - Fixed ReadXmlDeclaration(). Now skips text declaration.
+         - CompileDTDSubset() now checks IGNORE/INCLUDE section end balances.
+         - ReadContentSpec() should set OrderType = OR for mixed model.
+           Fixed to set content element name correctly.
+         - ImportAsPERef() now skips Text declaration.
+         - Type of enumerated default attributes shold be string.
+         - Undeclared PE error is now handled as DTD's VC error, not
+           XmlTextReader's WFC error.
+       * XmlValidatingReader.cs : BaseURI should provide that of 
+         original XmlReader's when read was not started yet.
+         Fixed XmlResolver to delegate to DTDValidatingReader.
+
+       * XmlAttributeCollection.cs : Acquiring attList declaration is
+         insufficient especially in case of lack of elementdecl.
+       * XmlChar.cs : (Maybe this is compact than XmlConstructs.)
+         added IsWhitespace(),IsNCNameChar(),IsName(),IsNCName(),IsNmToken(),
+         IsPubid(). Copies IsValidIANAEncoding() from XmlConstructs.
+
+       * XmlInputStream.cs : Removed "version" declaration check. It should
+         be done by XmlTextReader.
+
+       * XmlNodeReader.cs : added internal GetInternalParserContext() and now
+         it can be used in XmlValidatingReader.ResolveEntity().
+         ResolveEntity() sets XmlTextReader.MaybeTextDecl.
+
 2003-08-05  Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
 
        * DTDValidatingReader.cs :
index 37a7dcdc34c61ccf74664f52a1dd97993f8cd33f..f328924f66bf6f127ff37ed726166b8601006a4e 100644 (file)
@@ -8,10 +8,13 @@
 //
 using System;
 using System.Collections;
+using System.Globalization;
+using System.IO;
 using System.Text;
 using System.Xml;
 using System.Xml.Schema;
 using Mono.Xml.Schema;
+using Mono.Xml.Native;
 
 namespace Mono.Xml
 {
@@ -21,6 +24,7 @@ namespace Mono.Xml
                DTDAttListDeclarationCollection attListDecls;
                DTDEntityDeclarationCollection entityDecls;
                DTDNotationDeclarationCollection notationDecls;
+               ArrayList validationErrors;
 
                public DTDObjectModel ()
                {
@@ -29,6 +33,7 @@ namespace Mono.Xml
                        entityDecls = new DTDEntityDeclarationCollection (this);
                        notationDecls = new DTDNotationDeclarationCollection (this);
                        factory = new DTDAutomataFactory (this);
+                       validationErrors = new ArrayList ();
                }
 
                public string BaseURI;
@@ -110,6 +115,15 @@ namespace Mono.Xml
                                return invalidAutomata;
                        }
                }
+
+               public XmlSchemaException [] Errors {
+                       get { return validationErrors.ToArray (typeof (XmlSchemaException)) as XmlSchemaException []; }
+               }
+
+               public void AddError (XmlSchemaException ex)
+               {
+                       validationErrors.Add (ex);
+               }
        }
 
        public class DTDElementDeclarationCollection
@@ -128,10 +142,12 @@ namespace Mono.Xml
 
                public void Add (string name, DTDElementDeclaration decl)
                {
-                       if (elementDecls [name] != null)
-                               throw new InvalidOperationException (String.Format (
+                       if (elementDecls [name] != null) {
+                               this.root.AddError (new XmlSchemaException (String.Format (
                                        "Element declaration for {0} was already added.",
-                                       name));
+                                       name), null));
+                               return;
+                       }
                        decl.SetRoot (root);
                        elementDecls.Add (name, decl);
                }
@@ -473,13 +489,48 @@ namespace Mono.Xml
                        StringBuilder sb = new StringBuilder ();
                        int pos = 0;
                        int next = 0;
-                       while ((next = this.UnresolvedDefaultValue.IndexOf ('&', pos)) >= 0) {
-                               sb.Append (this.UnresolvedDefaultValue.Substring (pos, next - 1));
-                               int semicolon = this.UnresolvedDefaultValue.IndexOf (';', next);
-                               string name = this.UnresolvedDefaultValue.Substring (pos + 1, semicolon - 1);
-                               sb.Append (Root.ResolveEntity (name));
+                       string value = this.UnresolvedDefaultValue;
+                       while ((next = value.IndexOf ('&', pos)) >= 0) {
+                               int semicolon = value.IndexOf (';', next);
+                               if (value [next + 1] == '#') {
+                                       // character reference.
+                                       char c = value [next + 2];
+                                       NumberStyles style = NumberStyles.Integer;
+                                       string spec;
+                                       if (c == 'x' || c == 'X') {
+                                               spec = value.Substring (next + 3, semicolon - next - 3);
+                                               style |= NumberStyles.HexNumber;
+                                       }
+                                       else
+                                               spec = value.Substring (next + 2, semicolon - next - 2);
+                                       sb.Append ((char) int.Parse (spec, style));
+                               } else {
+                                       sb.Append (value.Substring (pos, next - 1));
+                                       string name = value.Substring (pos + 1, semicolon - 1);
+                                       switch (name) {
+                                       case "lt":
+                                               sb.Append ("<");
+                                               break;
+                                       case "gt":
+                                               sb.Append (">");
+                                               break;
+                                       case "amp":
+                                               sb.Append ("&");
+                                               break;
+                                       case "quot":
+                                               sb.Append ("\"");
+                                               break;
+                                       case "apos":
+                                               sb.Append ("'");
+                                               break;
+                                       default:
+                                               sb.Append (Root.ResolveEntity (name));
+                                               break;
+                                       }
+                               }
+                               pos = semicolon + 1;
                        }
-                       sb.Append (this.UnresolvedDefaultValue.Substring (pos));
+                       sb.Append (value.Substring (pos));
                        // strip quote chars
                        string ret = sb.ToString (1, sb.Length - 2);
                        sb.Length = 0;
@@ -561,15 +612,61 @@ namespace Mono.Xml
 
        public class DTDEntityDeclaration : DTDNode
        {
+               string entityValue;
+
                public string Name;
                public string PublicId;
                public string SystemId;
                public string NotationName;
-               // FIXME: should have more complex value than simple string
-               public string EntityValue;
+               public string LiteralEntityValue;
                public bool IsInternalSubset;
 
-               internal DTDEntityDeclaration () {}
+               public string EntityValue {
+                       get {
+                               if (entityValue == null) {
+                                       if (SystemId == null)
+                                               entityValue = LiteralEntityValue;
+                                       else {
+                                               // FIXME: should use specified XmlUrlResolver.
+                                               entityValue = ResolveExternalEntity (new XmlUrlResolver ());
+                                       }
+                               }
+                               return entityValue;
+                       }
+               }
+
+               private string ResolveExternalEntity (XmlResolver resolver)
+               {
+                       string baseUri = Root.BaseURI;
+                       if (baseUri == "")
+                               baseUri = null;
+                       Uri uri = resolver.ResolveUri (
+                               baseUri != null ? new Uri (baseUri) : null, SystemId);
+                       Stream stream = resolver.GetEntity (uri, null, typeof (Stream)) as Stream;
+                       XmlStreamReader reader = new XmlStreamReader (stream, false);
+
+                       StringBuilder sb = new StringBuilder ();
+
+                       bool checkTextDecl = true;
+                       while (reader.Peek () != -1) {
+                               sb.Append (reader.Read ());
+                               if (checkTextDecl && sb.Length == 6) {
+                                       if (sb.ToString () == "<?xml ") {
+                                               // Skip Text declaration.
+                                               sb.Length = 0;
+                                               while (reader.Peek () == '>' || reader.Peek () == -1)
+                                                       reader.Read ();
+                                       }
+                                       checkTextDecl = false;
+                               }
+                       }
+                       return sb.ToString ();
+               }
+
+               internal DTDEntityDeclaration (DTDObjectModel root)
+               {
+                       this.SetRoot (root);
+               }
        }
 
        public class DTDNotationDeclaration : DTDNode
index e2dabbd5806f8c76f1ceebdd13fbaa6d9b9024ed..560921d1ddf47722392be3c7886bebe857a7c75d 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Specialized;
 using System.Collections;
+using System.IO;
 using System.Text;
 using System.Xml;
 using System.Xml.Schema;
@@ -26,10 +27,13 @@ namespace Mono.Xml
                        automataStack = new Stack ();
                        attributes = new StringCollection ();
                        attributeValues = new NameValueCollection ();
+                       attributeLocalNames = new NameValueCollection ();
+                       attributeNamespaces = new NameValueCollection ();
                        this.validatingReader = validatingReader;
                        valueBuilder = new StringBuilder ();
                        idList = new ArrayList ();
                        missingIDReferences = new ArrayList ();
+                       resolver = new XmlUrlResolver ();
                }
 
                Stack entityReaderStack;
@@ -44,6 +48,7 @@ namespace Mono.Xml
                string currentElement;
                string currentAttribute;
                string currentTextValue;
+               string constructingTextValue;
                bool shouldResetCurrentTextValue;
                bool consumedAttribute;
                bool insideContent;
@@ -52,9 +57,15 @@ namespace Mono.Xml
                bool isStandalone;
                StringCollection attributes;
                NameValueCollection attributeValues;
+               NameValueCollection attributeLocalNames;
+               NameValueCollection attributeNamespaces;
                StringBuilder valueBuilder;
                ArrayList idList;
                ArrayList missingIDReferences;
+               XmlResolver resolver;
+               EntityHandling currentEntityHandling;
+               bool isSignificantWhitespace;
+               bool isWhitespace;
 
                // This field is used to get properties and to raise events.
                XmlValidatingReader validatingReader;
@@ -80,7 +91,7 @@ namespace Mono.Xml
                        if (attributes.Count <= i)
                                throw new IndexOutOfRangeException ("Specified index is out of range: " + i);
 
-                       return FilterNormalization (attributeValues [i]);
+                       return FilterNormalization (attributes [i], attributeValues [i]);
                }
 
                public override string GetAttribute (string name)
@@ -91,7 +102,7 @@ namespace Mono.Xml
                        if (dtd == null)
                                return reader.GetAttribute (name);
 
-                       return FilterNormalization (attributeValues [name]);
+                       return FilterNormalization (name, attributeValues [name]);
                }
 
                public override string GetAttribute (string name, string ns)
@@ -102,11 +113,7 @@ namespace Mono.Xml
                        if (dtd == null)
                                return reader.GetAttribute (name, ns);
 
-                       // FIXME: check whether this way is correct.
-                       if (ns == String.Empty)
-                               return GetAttribute (name);
-                       else
-                               return FilterNormalization (reader.GetAttribute (name, ns));
+                       return reader.GetAttribute (attributeLocalNames [name], ns);
                }
 
                bool IXmlLineInfo.HasLineInfo ()
@@ -193,9 +200,10 @@ namespace Mono.Xml
                                return true;
                        }
 
-                       if (ns != String.Empty)
-                               throw new InvalidOperationException ("DTD validating reader does not support namespace.");
-                       return MoveToAttribute (name);
+                       foreach (string iter in attributes)
+                               if (attributeLocalNames [iter] == name)
+                                       return MoveToAttribute (iter);
+                       return false;
                }
 
                public override bool MoveToElement ()
@@ -264,6 +272,7 @@ namespace Mono.Xml
                                return false;
                }
 
+               [MonoTODO ("Handling of whitespace entities are still not enough.")]
                public override bool Read ()
                {
                        if (currentTextValue != null)
@@ -276,22 +285,34 @@ namespace Mono.Xml
                        consumedAttribute = false;
                        attributes.Clear ();
                        attributeValues.Clear ();
-
-                       return ReadContent () || currentTextValue != null;
+                       attributeNamespaces.Clear ();
+                       isWhitespace = false;
+                       isSignificantWhitespace = false;
+
+                       bool b = ReadContent () || currentTextValue != null;
+                       if (!b && this.missingIDReferences.Count > 0) {
+                               this.HandleError ("Missing ID reference was found: " +
+                                       String.Join (",", missingIDReferences.ToArray (typeof (string)) as string []),
+                                       XmlSeverityType.Error);
+                               // Don't output the same errors so many times.
+                               this.missingIDReferences.Clear ();
+                       }
+                       currentEntityHandling = validatingReader.EntityHandling;
+                       return b;
                }
 
                private bool ReadContent ()
                {
                        if (nextEntityReader != null) {
-                               if (DTD == null || DTD.EntityDecls [Name] == null)
-                                       throw new XmlException ("Entity '" + Name + "' was not declared.");
+                               if (DTD == null || DTD.EntityDecls [reader.Name] == null)
+                                       throw new XmlException ("Entity '" + reader.Name + "' was not declared.");
                                entityReaderStack.Push (reader);
-                               entityReaderNameStack.Push (Name);
+                               entityReaderNameStack.Push (reader.Name);
                                entityReaderDepthStack.Push (Depth);
                                reader = sourceTextReader = nextEntityReader;
                                nextEntityReader = null;
                                return ReadContent ();
-                       } else if (NodeType == XmlNodeType.EndEntity) {
+                       } else if (reader.EOF && entityReaderStack.Count > 0) {
                                reader = entityReaderStack.Pop () as XmlReader;
                                entityReaderNameStack.Pop ();
                                entityReaderDepthStack.Pop ();
@@ -316,8 +337,12 @@ namespace Mono.Xml
                        }
 
                        if (!b) {
-                               if (entityReaderStack.Count > 0)
-                                       return true;    // EndEntity
+                               if (entityReaderStack.Count > 0) {
+                                       if (validatingReader.EntityHandling == EntityHandling.ExpandEntities)
+                                               return ReadContent ();
+                                       else
+                                               return true;    // EndEntity
+                               }
 
                                if (elementStack.Count != 0)
                                        throw new InvalidOperationException ("Unexpected end of XmlReader.");
@@ -338,11 +363,35 @@ namespace Mono.Xml
                                                reader ["PUBLIC"], reader ["SYSTEM"], reader.Value);
                                }
                                this.dtd = xmlTextReader.DTD;
+
+                               // Validity Constraints Check.
+                               if (DTD.Errors.Length > 0)
+                                       foreach (XmlSchemaException ex in DTD.Errors)
+                                               HandleError (ex.Message, XmlSeverityType.Error);
+
+                               // NData target exists.
+                               foreach (DTDEntityDeclaration ent in dtd.EntityDecls.Values)
+                                       if (ent.NotationName != null && dtd.NotationDecls [ent.NotationName] == null)
+                                               this.HandleError ("Target notation was not found for NData in entity declaration " + ent.Name + ".",
+                                                       XmlSeverityType.Error);
+                               // NOTATION exists for attribute default values
+                               foreach (DTDAttListDeclaration attListIter in dtd.AttListDecls.Values)
+                                       foreach (DTDAttributeDefinition def in attListIter.Definitions)
+                                               if (def.Datatype.TokenizedType == XmlTokenizedType.NOTATION) {
+                                                       foreach (string notation in def.EnumeratedNotations)
+                                                               if (dtd.NotationDecls [notation] == null)
+                                                                       this.HandleError ("Target notation was not found for NOTATION typed attribute default " + def.Name + ".",
+                                                                               XmlSeverityType.Error);
+                                               }
+
                                break;
 
                        case XmlNodeType.Element:
-                               if (currentTextValue != null)
+                               if (constructingTextValue != null) {
+                                       currentTextValue = constructingTextValue;
+                                       constructingTextValue = null;
                                        return true;
+                               }
                                elementStack.Push (reader.Name);
                                // startElementDeriv
                                // If no schema specification, then skip validation.
@@ -394,8 +443,11 @@ namespace Mono.Xml
                                break;
 
                        case XmlNodeType.EndElement:
-                               if (currentTextValue != null)
+                               if (constructingTextValue != null) {
+                                       currentTextValue = constructingTextValue;
+                                       constructingTextValue = null;
                                        return true;
+                               }
                                elementStack.Pop ();
                                // endElementDeriv
                                // If no schema specification, then skip validation.
@@ -423,10 +475,15 @@ namespace Mono.Xml
                                break;
 
                        case XmlNodeType.CDATA:
-                               if (currentTextValue != null)
+                               if (currentTextValue != null) {
+                                       currentTextValue = constructingTextValue;
+                                       constructingTextValue = null;
                                        return true;
+                               }
                                goto case XmlNodeType.Text;
                        case XmlNodeType.SignificantWhitespace:
+//                             isSignificantWhitespace = true;
+                               goto case XmlNodeType.Text;
                        case XmlNodeType.Text:
                                // If no schema specification, then skip validation.
                                if (currentAutomata == null)
@@ -435,14 +492,22 @@ namespace Mono.Xml
                                DTDElementDeclaration elem = dtd.ElementDecls [elementStack.Peek () as string];
                                // Here element should have been already validated, so
                                // if no matching declaration is found, simply ignore.
-                               if (elem != null && !elem.IsMixedContent) {
+                               if (elem != null && !elem.IsMixedContent && !elem.IsAny) {
                                        HandleError (String.Format ("Current element {0} does not allow character data content.", elementStack.Peek () as string),
                                                XmlSeverityType.Error);
                                        // FIXME: validation recovery code here.
                                        currentAutomata = previousAutomata;
                                }
                                if (validatingReader.EntityHandling == EntityHandling.ExpandEntities) {
-                                       currentTextValue += reader.Value;
+                                       constructingTextValue += reader.Value;
+                                       return ReadContent ();
+                               }
+                               break;
+                       case XmlNodeType.Whitespace:
+//                             if (!isSignificantWhitespace)
+//                                     isWhitespace = true;
+                               if (validatingReader.EntityHandling == EntityHandling.ExpandEntities) {
+                                       constructingTextValue += reader.Value;
                                        return ReadContent ();
                                }
                                break;
@@ -462,6 +527,8 @@ namespace Mono.Xml
                                // If it was invalid, simply add specified attributes.
                                do {
                                        attributes.Add (reader.Name);
+                                       attributeLocalNames.Add (reader.Name, reader.LocalName);
+                                       attributeNamespaces.Add (reader.Name, reader.NamespaceURI);
                                        attributeValues.Add (reader.Name, reader.Value);
                                } while (reader.MoveToNextAttribute ());
                                reader.MoveToElement ();
@@ -486,7 +553,7 @@ namespace Mono.Xml
 
                        if (validatingReader != null)
                                this.validatingReader.OnValidationEvent (this,
-                                       new ValidationEventArgs (ex, message, severity));
+                                       new ValidationEventArgs (ex, ex.Message, severity));
                        else
                                throw ex;
                }
@@ -496,6 +563,8 @@ namespace Mono.Xml
                        while (reader.MoveToNextAttribute ()) {
                                string attrName = reader.Name;
                                attributes.Add (attrName);
+                               attributeLocalNames.Add (attrName, reader.LocalName);
+                               attributeNamespaces.Add (attrName, reader.NamespaceURI);
                                bool hasError = false;
                                while (reader.ReadAttributeValue ()) {
                                        if (reader.NodeType == XmlNodeType.EntityReference) {
@@ -523,13 +592,25 @@ namespace Mono.Xml
                                                XmlSeverityType.Error);
                                        // FIXME: validation recovery code here.
                                } else {
-                                       // check identity constraint
+                                       // check enumeration constraint
+                                       if (def.EnumeratedAttributeDeclaration.Count > 0)
+                                               if (!def.EnumeratedAttributeDeclaration.Contains (attrValue))
+                                                       HandleError (String.Format ("Attribute enumeration constraint error in attribute {0}, value {1}.",
+                                                               reader.Name, attrValue), XmlSeverityType.Error);
+                                       if (def.EnumeratedNotations.Count > 0)
+                                               if (!def.EnumeratedNotations.Contains (attrValue))
+                                                       HandleError (String.Format ("Attribute notation enumeration constraint error in attribute {0}, value {1}.",
+                                                               reader.Name, attrValue), XmlSeverityType.Error);
+
+                                       // check type constraint
                                        switch (def.Datatype.TokenizedType) {
                                        case XmlTokenizedType.ID:
-                                               if (this.idList.Contains (attrValue)) {
+                                               if (!XmlChar.IsName (FilterNormalization (def.Name, attrValue)))
+                                                       HandleError (String.Format ("ID attribute value must match the creation rule Name: {0}", attrValue),
+                                                               XmlSeverityType.Error);
+                                               else if (this.idList.Contains (attrValue)) {
                                                        HandleError (String.Format ("Node with ID {0} was already appeared.", attrValue),
                                                                XmlSeverityType.Error);
-                                                       // FIXME: validation recovery code here.
                                                } else {
                                                        if (missingIDReferences.Contains (attrValue))
                                                                missingIDReferences.Remove (attrValue);
@@ -537,35 +618,55 @@ namespace Mono.Xml
                                                }
                                                break;
                                        case XmlTokenizedType.IDREF:
+                                               if (!XmlChar.IsName (attrValue))
+                                                       HandleError (String.Format ("IDREF attribute value must match the creation rule Name: {0}", attrValue),
+                                                               XmlSeverityType.Error);
                                                if (!idList.Contains (attrValue))
                                                        missingIDReferences.Add (attrValue);
                                                break;
                                        case XmlTokenizedType.IDREFS:
                                                string [] idrefs = def.Datatype.ParseValue (attrValue, NameTable, null) as string [];
-                                               foreach (string idref in idrefs)
-                                                       if (!idList.Contains (attrValue))
+                                               foreach (string idref in idrefs) {
+                                                       if (!XmlChar.IsName (FilterNormalization (def.Name, idref)))
+                                                               HandleError (String.Format ("Each ID in IDREFS attribute value must match the creation rule Name: {0}", attrValue),
+                                                                       XmlSeverityType.Error);
+                                                       if (!idList.Contains (idref))
                                                                missingIDReferences.Add (attrValue);
+                                               }
                                                break;
-                                       }
-
-                                       switch (def.OccurenceType) {
-                                               case DTDAttributeOccurenceType.Required:
-                                               if (attrValue == String.Empty) {
-                                                       HandleError (String.Format ("Required attribute {0} in element {1} not found .",
-                                                               def.Name, decl.Name),
+                                       case XmlTokenizedType.ENTITY:
+                                               if (dtd.EntityDecls [attrValue] == null)
+                                                       HandleError (String.Format ("Reference to undeclared entity was found in attribute {0}.", reader.Name),
                                                                XmlSeverityType.Error);
-                                                       // FIXME: validation recovery code here.
-                                               }
                                                break;
-                                       case DTDAttributeOccurenceType.Fixed:
-                                               if (attrValue != def.DefaultValue) {
-                                                       HandleError (String.Format ("Fixed attribute {0} in element {1} has invalid value {2}.",
-                                                               def.Name, decl.Name, attrValue),
+                                       case XmlTokenizedType.ENTITIES:
+                                               string [] entrefs = def.Datatype.ParseValue (attrValue, NameTable, null) as string [];
+                                               foreach (string entref in entrefs)
+                                                       if (dtd.EntityDecls [entref] == null)
+                                                               HandleError (String.Format ("Reference to undeclared entity was found in attribute {0}.", reader.Name),
+                                                                       XmlSeverityType.Error);
+                                               break;
+                                       case XmlTokenizedType.NMTOKEN:
+                                               if (!XmlChar.IsNmToken (FilterNormalization (def.Name, attrValue)))
+                                                       HandleError (String.Format ("NMTOKEN attribute value must match the creation rule NMTOKEN. Name={0}", reader.Name),
                                                                XmlSeverityType.Error);
-                                                       // FIXME: validation recovery code here.
-                                               }
+                                               break;
+                                       case XmlTokenizedType.NMTOKENS:
+                                               string [] tokens = def.Datatype.ParseValue (attrValue, NameTable, null) as string [];
+                                               foreach (string token in tokens)
+                                                       if (!XmlChar.IsNmToken (FilterNormalization (def.Name, token)))
+                                                               HandleError (String.Format ("Name Token in NMTOKENS attribute value must match the creation rule NMTOKEN. Name={0}", reader.Name),
+                                                                       XmlSeverityType.Error);
                                                break;
                                        }
+
+                                       if (def.OccurenceType == DTDAttributeOccurenceType.Fixed &&
+                                                       attrValue != def.DefaultValue) {
+                                               HandleError (String.Format ("Fixed attribute {0} in element {1} has invalid value {2}.",
+                                                       def.Name, decl.Name, attrValue),
+                                                       XmlSeverityType.Error);
+                                               // FIXME: validation recovery code here.
+                                       }
                                }
                        }
                        // Check if all required attributes exist, and/or
@@ -573,13 +674,23 @@ namespace Mono.Xml
                        foreach (DTDAttributeDefinition def in decl.Definitions)
                                if (!attributes.Contains (def.Name)) {
                                        if (def.OccurenceType == DTDAttributeOccurenceType.Required) {
-                                               HandleError (String.Format ("Required attribute {0} was not found.", decl.Name),
+                                               HandleError (String.Format ("Required attribute {0} in element {1} not found .",
+                                                       def.Name, decl.Name),
                                                        XmlSeverityType.Error);
                                                // FIXME: validation recovery code here.
                                        }
                                        else if (def.DefaultValue != null) {
-                                               attributes.Add (def.Name);
-                                               attributeValues.Add (def.Name, def.DefaultValue);
+                                               switch (validatingReader.ValidationType) {
+                                               case ValidationType.DTD:
+                                               case ValidationType.None:
+                                                       // Other than them, ignore DTD defaults.
+                                                       attributes.Add (def.Name);
+                                                       int colonAt = def.Name.IndexOf (':');
+                                                       attributeLocalNames.Add (def.Name, colonAt < 0 ? def.Name : def.Name.Substring (colonAt + 1));
+                                                       attributeNamespaces.Add (def.Name, colonAt < 0 ? def.Name : def.Name.Substring (0, colonAt));
+                                                       attributeValues.Add (def.Name, def.DefaultValue);
+                                                       break;
+                                               }
                                        }
                                }
 
@@ -591,7 +702,7 @@ namespace Mono.Xml
                        if (consumedAttribute)
                                return false;
                        if (NodeType == XmlNodeType.Attribute &&
-                                       validatingReader.EntityHandling == EntityHandling.ExpandEntities) {
+                                       currentEntityHandling == EntityHandling.ExpandEntities) {
                                consumedAttribute = true;
                                return true;
                        }
@@ -625,28 +736,37 @@ namespace Mono.Xml
 
                public override void ResolveEntity ()
                {
-                       if (NodeType != XmlNodeType.EntityReference)
+                       // "reader." is required since NodeType must not be entityref by nature.
+                       if (reader.NodeType != XmlNodeType.EntityReference)
                                throw new InvalidOperationException ("The current node is not an Entity Reference");
-                       DTDEntityDeclaration entity = DTD != null ? DTD.EntityDecls [Name] as DTDEntityDeclaration : null;
-
-                       // MS.NET seems simply ignoring undeclared entity reference here ;-(
-                       string replacementText =
-                               (entity != null) ? entity.EntityValue : String.Empty;
+                       DTDEntityDeclaration entity = DTD != null ? DTD.EntityDecls [reader.Name] as DTDEntityDeclaration : null;
 
-                       XmlNodeType xmlReaderNodeType =
-                               (currentAttribute != null) ? XmlNodeType.Attribute : XmlNodeType.Element;
+                       XmlParserContext ctx = null;
+                       if (sourceTextReader != null)
+                               ctx = sourceTextReader.GetInternalParserContext ();
+                       else if (reader is XmlNodeReader)
+                               ctx = ((XmlNodeReader) reader).GetInternalParserContext ();
+                       else if (reader is IHasXmlParserContext)
+                               ctx = ((IHasXmlParserContext) reader).ParserContext;
 
-                       if (sourceTextReader == null)
+                       if (ctx == null)
                                throw new NotSupportedException (
                                        "Entity resolution from non-XmlTextReader XmlReader could not be supported.");
-                       XmlParserContext ctx = sourceTextReader.GetInternalParserContext ();
 
-                       // FIXME: is seems impossible to get namespaceManager from XmlReader.
-//                     ctx = new XmlParserContext (document.NameTable,
-//                             new XmlNamespaceManager (NameTable),
-//                             DTD,
-//                             BaseURI, XmlLang, XmlSpace, Encoding.Unicode);
-                       nextEntityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ctx);
+                       XmlNodeType xmlReaderNodeType =
+                               (currentAttribute != null) ? XmlNodeType.Attribute : XmlNodeType.Element;
+
+                       // MS.NET seems simply ignoring undeclared entity reference here ;-(
+                       if (entity != null && entity.SystemId != null) {
+                               Uri baseUri = entity.BaseURI == null ? null : new Uri (entity.BaseURI);
+                               Stream stream = resolver.GetEntity (resolver.ResolveUri (baseUri, entity.SystemId), null, typeof (Stream)) as Stream;
+                               nextEntityReader = new XmlTextReader (stream, xmlReaderNodeType, ctx);
+                       } else {
+                               string replacementText =
+                                       (entity != null) ? entity.EntityValue : String.Empty;
+                               nextEntityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ctx);
+                       }
+                       nextEntityReader.MaybeTextDecl = true;
                }
 
                public override int AttributeCount {
@@ -679,6 +799,9 @@ namespace Mono.Xml
                                        if (NodeType != XmlNodeType.EndEntity)
                                                baseNum++;
                                }
+                               if (currentTextValue != null && reader.NodeType == XmlNodeType.EndElement)
+                                       baseNum++;
+
                                return IsDefault ? baseNum + 1 : baseNum;
                        }
                }
@@ -775,7 +898,9 @@ namespace Mono.Xml
                public override XmlNodeType NodeType {
                        get {
                                if (currentTextValue != null)
-                                       return XmlNodeType.Text;
+                                       return isSignificantWhitespace ? XmlNodeType.SignificantWhitespace :
+                                               isWhitespace ? XmlNodeType.Whitespace :
+                                               XmlNodeType.Text;
 
                                if (entityReaderStack.Count > 0 && reader.EOF)
                                        return XmlNodeType.EndEntity;
@@ -814,14 +939,14 @@ namespace Mono.Xml
                }
 
                char [] whitespaceChars = new char [] {' '};
-               private string FilterNormalization (string rawValue)
+               private string FilterNormalization (string attrName, string rawValue)
                {
                        if (DTD != null &&
                                        NodeType == XmlNodeType.Attribute &&
                                        sourceTextReader != null && 
                                        sourceTextReader.Normalization) {
                                DTDAttributeDefinition def = 
-                                       dtd.AttListDecls [currentElement] [currentAttribute] as DTDAttributeDefinition;
+                                       dtd.AttListDecls [currentElement].Get (attrName);
                                valueBuilder.Append (rawValue);
                                valueBuilder.Replace ('\r', ' ');
                                valueBuilder.Replace ('\n', ' ');
@@ -859,12 +984,12 @@ namespace Mono.Xml
                                }
                                // As to this property, MS.NET seems ignorant of EntityHandling...
                                else if (NodeType == XmlNodeType.Attribute)// &&
-                                       // validatingReader.EntityHandling == EntityHandling.ExpandEntities)
-                                       return FilterNormalization (attributeValues [currentAttribute]);
+                                       // currentEntityHandling == EntityHandling.ExpandEntities)
+                                       return FilterNormalization (Name, attributeValues [currentAttribute]);
                                else if (consumedAttribute)
-                                       return FilterNormalization (attributeValues [this.currentAttribute]);
+                                       return FilterNormalization (Name, attributeValues [this.currentAttribute]);
                                else
-                                       return FilterNormalization (reader.Value);
+                                       return FilterNormalization (Name, reader.Value);
                        }
                }
 
@@ -875,6 +1000,12 @@ namespace Mono.Xml
                        }
                }
 
+               public XmlResolver XmlResolver {
+                       set {
+                               resolver = value;
+                       }
+               }
+
                public override XmlSpace XmlSpace {
                        get {
                                string val = this ["xml:space"];
index a434ed72536c709b9e5c180a3fac437f25222ce0..92216c20892fd8ea351218ee1d0f3b0d6c2be408 100644 (file)
@@ -253,8 +253,8 @@ namespace System.Xml
                        XmlDocumentType doctype = node.OwnerDocument.DocumentType;
                        if (doctype == null || doctype.DTD == null)
                                return existing;
-                       DTDElementDeclaration elem = doctype.DTD.ElementDecls [ownerElement.Name];
-                       DTDAttributeDefinition attdef = elem == null ? null : elem.Attributes [node.Name];
+                       DTDAttListDeclaration attList = doctype.DTD.AttListDecls [ownerElement.Name];
+                       DTDAttributeDefinition attdef = attList == null ? null : attList.Get (node.Name);
                        if (attdef == null || attdef.Datatype.TokenizedType != XmlTokenizedType.ID)
                                return existing;
 
index 3bdd932c82be9a7973888b893695d650df98eab1..47be7985e00e586c83fde6cd028072daa1e6f180 100644 (file)
@@ -17,6 +17,14 @@ namespace System.Xml
                        return ch == 0x20 || ch == 0x9 || ch == 0xD || ch == 0xA;\r
                }\r
 \r
+               internal static bool IsWhitespace (string str)\r
+               {\r
+                       foreach (char c in str)\r
+                               if (!IsWhitespace (c))\r
+                                       return false;\r
+                       return true;\r
+               }\r
+\r
                internal static bool IsFirstNameChar(int ch)\r
                {\r
                        bool result = false;\r
@@ -41,11 +49,102 @@ namespace System.Xml
                        return result;\r
                }\r
 \r
+               internal static bool IsNCNameChar(int ch)\r
+               {\r
+                       bool result = false;\r
+\r
+                       if (ch >= 0 && ch <= 0xFFFF && ch != ':')\r
+                       {\r
+                               result = (nameBitmap[(namePages[ch >> 8] << 3) + ((ch & 0xFF) >> 5)] & (1 << (ch & 0x1F))) != 0;\r
+                       }\r
+\r
+                       return result;\r
+               }\r
+\r
+               internal static bool IsName (string str)\r
+               {\r
+                       if (str.Length == 0)\r
+                               return false;\r
+                       if (!IsFirstNameChar (str [0]))\r
+                               return false;\r
+                       foreach (char c in str)\r
+                               if (!IsNameChar (c))\r
+                                       return false;\r
+                       return true;\r
+               }\r
+\r
+               internal static bool IsNCName (string str)\r
+               {\r
+                       if (str.Length == 0)\r
+                               return false;\r
+                       if (!IsFirstNameChar (str [0]))\r
+                               return false;\r
+                       foreach (char c in str)\r
+                               if (!IsNCNameChar (c))\r
+                                       return false;\r
+                       return true;\r
+               }\r
+\r
+               internal static bool IsNmToken (string str)\r
+               {\r
+                       if (str.Length == 0)\r
+                               return false;\r
+                       foreach (char c in str)\r
+                               if (!IsNameChar (c))\r
+                                       return false;\r
+                       return true;\r
+               }\r
+\r
                internal static bool IsPubidChar(int ch)\r
                {\r
                        return IsWhitespace(ch) | ('a' <= ch && ch <= 'z') | ('A' <= ch && ch <= 'Z') | ('0' <= ch && ch <= '9') | "-'()+,./:=?;!*#@$_%".IndexOf((char)ch) >= 0;\r
                }\r
 \r
+               internal static bool IsPubid (string str)\r
+               {\r
+                       foreach (char c in str)\r
+                               if (!IsPubidChar (c))\r
+                                       return false;\r
+                       return true;\r
+               }\r
+\r
+               // encodings (copied from XmlConstructs.cs)\r
+\r
+               /// <summary>\r
+               /// Returns true if the encoding name is a valid IANA encoding.\r
+               /// This method does not verify that there is a decoder available\r
+               /// for this encoding, only that the characters are valid for an\r
+               /// IANA encoding name.\r
+               /// </summary>\r
+               /// <param name="ianaEncoding">The encoding to check.</param>\r
+               /// <returns></returns>\r
+               internal static bool IsValidIANAEncoding(String ianaEncoding) \r
+               {\r
+                       if (ianaEncoding != null) \r
+                       {\r
+                               int length = ianaEncoding.Length;\r
+                               if (length > 0) \r
+                               {\r
+                                       char c = ianaEncoding[0];\r
+                                       if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) \r
+                                       {\r
+                                               for (int i = 1; i < length; i++) \r
+                                               {\r
+                                                       c = ianaEncoding[i];\r
+                                                       if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&\r
+                                                               (c < '0' || c > '9') && c != '.' && c != '_' &&\r
+                                                               c != '-') \r
+                                                       {\r
+                                                               return false;\r
+                                                       }\r
+                                               }\r
+                                               return true;\r
+                                       }\r
+                               }\r
+                       }\r
+                       return false;\r
+               }\r
+\r
                private static byte[] firstNamePages =\r
                {\r
                        0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,\r
index 88e5d1f4809c94699cc8cd83b2a126e5eeef2dd5..14bc8173c842a5a7916bd07598ec3247d18342d7 100644 (file)
@@ -7,6 +7,7 @@
 // (C) Ximian, Inc.\r
 //\r
 using System;\r
+using System.IO;\r
 using System.Collections;\r
 using Mono.Xml;\r
 \r
@@ -34,7 +35,7 @@ namespace System.Xml
                        this.systemId = systemId;\r
                        this.internalSubset = internalSubset;\r
 \r
-                       XmlTextReader xtr = new XmlTextReader ("", XmlNodeType.Document, null);\r
+                       XmlTextReader xtr = new XmlTextReader (BaseURI, new StringReader (""), doc.NameTable);\r
                        xtr.GenerateDTDObjectModel (name, publicId, systemId, internalSubset);\r
                        this.dtd = xtr.DTD;\r
 \r
@@ -62,7 +63,7 @@ namespace System.Xml
                                XmlNode n = new XmlEntity (decl.Name, decl.NotationName,
                                        decl.PublicId, decl.SystemId, OwnerDocument);
                                // FIXME: Value is more complex, similar to Attribute.
-                               n.insertBeforeIntern (OwnerDocument.CreateTextNode (decl.EntityValue), null);
+                               n.insertBeforeIntern (OwnerDocument.CreateTextNode (decl.LiteralEntityValue), null);
                                entities.Nodes.Add (n);
                        }
                        foreach (DTDNotationDeclaration decl in DTD.NotationDecls.Values) {
index 8526a3f76363da7dc8647630ea62c1f4387a5465..4035b66c132044d372916982fcef478c70467316 100644 (file)
@@ -172,8 +172,9 @@ namespace Mono.Xml.Native
 
                                        // version. It is optional here.
                                        if (c != 'v') {
-                                               if (isDocumentEntity)
-                                                       throw new XmlException ("invalid xml declaration.");
+                                               // FIXME: temporarily comment out here.
+//                                             if (isDocumentEntity)
+//                                                     throw new XmlException ("invalid xml declaration.");
                                        } else {
                                                ms.WriteByte ((byte)'v');
                                                while (loop++ >= 0 && c >= 0) {
@@ -209,7 +210,7 @@ namespace Mono.Xml.Native
                                                                ms.WriteByte ((byte)c);
                                                        }
                                                        string encodingName = Encoding.UTF8.GetString (ms.GetBuffer (), start, (int)ms.Position - start);
-                                                       if (!XmlConstructs.IsValidIANAEncoding (encodingName))
+                                                       if (!XmlChar.IsValidIANAEncoding (encodingName))
                                                                throw encodingException;
                                                        ms.WriteByte ((byte)quoteChar);
                                                        enc = Encoding.GetEncoding (encodingName);
index 144d77460199cc3e7e3d7c4fea2637ff11f7b8e5..28a4aa0d845cbeb8585b62b343c486f4c2567e00 100755 (executable)
@@ -476,6 +476,16 @@ namespace System.Xml
                        return null;
                }
 
+               internal XmlParserContext GetInternalParserContext ()
+               {
+                       if (entityReader != null)
+                               return entityReader.GetInternalParserContext ();
+                       else
+                               return new XmlParserContext (document.NameTable,
+                                       current.ConstructNamespaceManager (),
+                                       XmlLang, XmlSpace);
+               }
+
                public override string LookupNamespace (string prefix)
                {
                        if (entityReader != null && entityReader.ReadState != ReadState.Initial)
@@ -893,6 +903,7 @@ namespace System.Xml
                                        BaseURI, XmlLang, XmlSpace, Encoding.Unicode);
                        }
                        entityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ctx);
+                       entityReader.MaybeTextDecl = true;
                }
 
                public override void Skip ()
index 339307e5e1f24c2bf3c5b7f4dc011ccddb3e1c8b..bcfb7635e682502b8fbb7eb0e42b86d4d4cce2c3 100644 (file)
@@ -603,6 +603,7 @@ namespace System.Xml
                                        value,
                                        false);
 
+                       returnEntityReference = false;
                        return true;
                }
 
@@ -715,6 +716,9 @@ namespace System.Xml
                #region Internals
                // Parsed DTD Objects
                internal DTDObjectModel DTD;
+               internal bool MaybeTextDecl {
+                       set { if (value) this.maybeTextDecl = 2; }
+               }
                #endregion
 
                #region Privates
@@ -1020,10 +1024,12 @@ namespace System.Xml
                                case ' ':
                                        if (whitespaceHandling == WhitespaceHandling.All ||
                                                whitespaceHandling == WhitespaceHandling.Significant)
-                                               return ReadWhitespace ();
-
-                                       SkipWhitespace ();
-                                       return ReadContent ();
+                                               ReadWhitespace ();
+                                       else {
+                                               SkipWhitespace ();
+                                               return ReadContent ();
+                                       }
+                                       break;
                                case -1:
                                        if (depth > 0)
                                                throw new XmlException ("unexpected end of file. Current depth is " + depth);
@@ -1041,6 +1047,8 @@ namespace System.Xml
                                        break;
                                }
                        }
+                       if (NodeType == XmlNodeType.XmlDeclaration && maybeTextDecl == 1)
+                               return ReadContent ();
                        return this.ReadState != ReadState.EndOfFile;
                }
 
@@ -1100,7 +1108,7 @@ namespace System.Xml
                        ClearAttributes ();
 
                        SkipWhitespace ();
-                       if (XmlConstructs.IsNameStart (PeekChar ()))
+                       if (XmlChar.IsFirstNameChar (PeekChar ()))
                                ReadAttributes (false);
 
                        string baseUri = GetAttribute ("xml:base");
@@ -1336,7 +1344,7 @@ namespace System.Xml
                        Expect (';');
 
                        string name = CreateNameString ();
-                       if (XmlConstructs.IsValidName (name) >= 0)
+                       if (!XmlChar.IsName (name))
                                throw new XmlException (this as IXmlLineInfo,
                                        "Invalid entity reference name was found.");
 
@@ -1396,9 +1404,7 @@ namespace System.Xml
 
                                AddAttribute (name, value);
 
-                               if (XmlConstructs.IsSpace (PeekChar ()))
-                                       SkipWhitespace ();
-                               else
+                               if (!SkipWhitespace ())
                                        requireWhitespace = true;
                                peekChar = PeekChar ();
                                if (peekChar == '?' && allowPIEnd)
@@ -1492,7 +1498,9 @@ namespace System.Xml
                                        throw new XmlException (this as IXmlLineInfo,
                                                "XML declaration cannot appear in this state.");
                        }
-                       currentState = XmlNodeType.XmlDeclaration;
+                       // Is this required?
+//                     if (maybeTextDecl != 0)
+//                             currentState = XmlNodeType.XmlDeclaration;
 
                        ClearAttributes ();
 
@@ -1503,7 +1511,7 @@ namespace System.Xml
 
                        string message = null;
                        if (parserInputStack.Count == 0) {
-                               if (orderedAttributes [0] as string != "version" || version != "1.0")
+                               if (maybeTextDecl == 0 && (orderedAttributes [0] as string != "version" || version != "1.0"))
                                        message = "Version 1.0 declaration is required in XML Declaration.";
                                else if (orderedAttributes.Count > 1 &&
                                                (orderedAttributes [1] as string != "encoding" &&
@@ -1535,7 +1543,8 @@ namespace System.Xml
                                if (this ["standalone"] != null)
                                        throw new XmlException (this as IXmlLineInfo,
                                                "Invalid text declaration.");
-                       maybeTextDecl = 0;
+                       if (maybeTextDecl == 2)
+                               maybeTextDecl = 1;
 
                        SetProperties (
                                XmlNodeType.XmlDeclaration, // nodeType
@@ -1595,6 +1604,10 @@ namespace System.Xml
                                        break;
                                }
 
+                               if (XmlConstructs.IsInvalid (ch))
+                                       throw new XmlException (this as IXmlLineInfo,
+                                               "Not allowed character was found.");
+
                                AppendValueChar ((char)ch);
                        }
 
@@ -1754,6 +1767,7 @@ namespace System.Xml
                                } while (nodeType != XmlNodeType.None || parserInputStack.Count > originalParserDepth + 1);
                                PopParserInput ();
                        }
+                       // TODO: Check entity nesting
 
                        return DTD;
                }
@@ -2003,6 +2017,8 @@ namespace System.Xml
                                }
                                break;
                        case ']':
+                               if (dtdIncludeSect == 0)
+                                       throw new XmlException (this as IXmlLineInfo, "Unbalanced end of INCLUDE/IGNORE section.");
                                // End of inclusion
                                Expect ("]]>");
                                dtdIncludeSect--;
@@ -2034,14 +2050,12 @@ namespace System.Xml
                                        LOOPBACK:
                                        if (PeekChar () == '%') {
                                                ReadChar ();
-                                               if (!XmlConstructs.IsSpace (PeekChar ())) {
+                                               if (!SkipWhitespace ()) {
                                                        ExpandPERef ();
                                                        goto LOOPBACK;
-//                                                     throw new XmlException (this as IXmlLineInfo,"expected whitespace between '%' and name.");
                                                } else {
-                                                       SkipWhitespace ();
                                                        TryExpandPERef ();
-                                                       if (XmlConstructs.IsName (PeekChar ()))
+                                                       if (XmlChar.IsNameChar (PeekChar ()))
                                                        ReadParameterEntityDecl ();
                                                        else
                                                                throw new XmlException (this as IXmlLineInfo,"expected name character");
@@ -2165,6 +2179,8 @@ namespace System.Xml
                                if(PeekChar () == '#') {
                                        // Mixed Contents. "#PCDATA" must appear first.
                                        decl.IsMixedContent = true;
+                                       model.Occurence = DTDOccurence.ZeroOrMore;
+                                       model.OrderType = DTDContentOrderType.Or;
                                        Expect ("#PCDATA");
                                        SkipWhitespace ();
                                        TryExpandPERef ();
@@ -2175,16 +2191,14 @@ namespace System.Xml
                                                TryExpandPERef ();
                                                SkipWhitespace ();
                                                DTDContentModel elem = new DTDContentModel (DTD, decl.Name);
-                                               model.ElementName = ReadName ();
+                                               elem.ElementName = ReadName ();
                                                model.ChildModels.Add (elem);
                                                SkipWhitespace ();
                                                TryExpandPERef ();
                                        }
                                        Expect (')');
-                                       if (model.ChildModels.Count > 0) {
+                                       if (model.ChildModels.Count > 0)
                                                Expect ('*');
-                                               model.Occurence = DTDOccurence.ZeroOrMore;
-                                       }
                                        else if (PeekChar () == '*')
                                                Expect ('*');
                                } else {
@@ -2387,8 +2401,18 @@ namespace System.Xml
                                        sb = new StringBuilder ();
                                else
                                        sb.Length = 0;
-                               while (PeekChar () != -1)
+                               bool checkTextDecl = true;
+                               while (PeekChar () != -1) {
                                        sb.Append (ReadChar ());
+                                       if (checkTextDecl && sb.Length == 6) {
+                                               if (sb.ToString () == "<?xml ") {
+                                                       // Skip Text declaration.
+                                                       sb.Length = 0;
+                                                       while (PeekChar () == '>' || PeekChar () == -1)
+                                                               ReadChar ();
+                                               }
+                                       }
+                               }
                                PopParserInput ();
                                appendStr = sb.ToString ();
                        } else {
@@ -2402,7 +2426,7 @@ namespace System.Xml
                // The reader is positioned on the head of the name.
                private DTDEntityDeclaration ReadEntityDecl ()
                {
-                       DTDEntityDeclaration decl = new DTDEntityDeclaration ();
+                       DTDEntityDeclaration decl = new DTDEntityDeclaration (DTD);
                        decl.IsInternalSubset = isIntSubset;
                        decl.Name = ReadName ();
                        if (!SkipWhitespace ())
@@ -2428,8 +2452,8 @@ namespace System.Xml
                                }
                        }
                        else {
-                               // general entity
-                               decl.EntityValue = ReadEntityValueDecl ();
+                               // literal entity
+                               decl.LiteralEntityValue = ReadEntityValueDecl ();
                        }
                        SkipWhitespace ();
                        // This expanding is only allowed as a non-validating parser.
@@ -2487,7 +2511,7 @@ namespace System.Xml
                        TryExpandPERef ();
                        SkipWhitespace ();
 
-                       while (XmlConstructs.IsName ((char) PeekChar ())) {
+                       while (XmlChar.IsNameChar ((char) PeekChar ())) {
                                DTDAttributeDefinition def = ReadAttributeDefinition ();
                                if (decl [def.Name] == null)
                                        decl.Add (def);
@@ -2580,6 +2604,7 @@ namespace System.Xml
                                }
                                break;
                        default:        // Enumerated Values
+                               def.Datatype = XmlSchemaDatatype.FromName ("string");
                                TryExpandPERef ();
                                Expect ('(');
                                SkipWhitespace ();
@@ -2682,7 +2707,7 @@ namespace System.Xml
                {
                        if (PeekChar () == '%') {
                                ReadChar ();
-                               if (!XmlConstructs.IsName (PeekChar ()))
+                               if (!XmlChar.IsNameChar (PeekChar ()))
                                        return;
                                ExpandPERef ();
                        }
@@ -2705,8 +2730,11 @@ namespace System.Xml
                {
                        DTDParameterEntityDeclaration decl =
                                parameterEntities [peName] as DTDParameterEntityDeclaration;
-                       if (decl == null)
-                               throw new XmlException ("undeclared parameter entity: '" + peName + "'");
+                       if (decl == null) {
+                               DTD.AddError (new XmlSchemaException (
+                                       "undeclared parameter entity: '" + peName + "'", null));
+                               return;
+                       }
                        if (decl.SystemId != null) {
                                PushParserInput (decl.SystemId);
 //                             currentInput.InsertParameterEntityBuffer (this.GetExternalTextMarkup (decl));
@@ -2769,7 +2797,7 @@ namespace System.Xml
                        {
                                c = ReadChar ();
                                if(c < 0) throw new XmlException (this as IXmlLineInfo,"Unexpected end of stream in ExternalID.");
-                               if(c != quoteChar && !XmlConstructs.IsPubid (c))
+                               if(c != quoteChar && !XmlChar.IsPubidChar (c))
                                        throw new XmlException (this as IXmlLineInfo,"character '" + (char)c + "' not allowed for PUBLIC ID");
                        }
                        return currentTag.ToString (startPos, currentTag.Length - 1 - startPos);
@@ -2793,11 +2821,11 @@ namespace System.Xml
                {
                        int ch = PeekChar ();
                        if(isNameToken) {
-                               if (!XmlConstructs.IsName ((char) ch))
+                               if (!XmlChar.IsNameChar ((char) ch))
                                        throw new XmlException (this as IXmlLineInfo,String.Format ("a nmtoken did not start with a legal character {0} ({1})", ch, (char)ch));
                        }
                        else {
-                               if (!XmlConstructs.IsNameStart ((char) ch))
+                               if (!XmlChar.IsFirstNameChar (ch))
                                        throw new XmlException (this as IXmlLineInfo,String.Format ("a name did not start with a legal character {0} ({1})", ch, (char)ch));
                        }
 
@@ -2805,7 +2833,7 @@ namespace System.Xml
 
                        AppendNameChar (ReadChar ());
 
-                       while (XmlConstructs.IsName (PeekChar ())) {
+                       while (XmlChar.IsNameChar (PeekChar ())) {
                                AppendNameChar (ReadChar ());
                        }
 
@@ -2840,13 +2868,13 @@ namespace System.Xml
                private bool SkipWhitespace ()
                {
                        //FIXME: Should not skip if whitespaceHandling == WhiteSpaceHandling.None
-                       bool skipped = XmlConstructs.IsSpace (PeekChar ());
-                       while (XmlConstructs.IsSpace (PeekChar ()))
+                       bool skipped = XmlChar.IsWhitespace (PeekChar ());
+                       while (XmlChar.IsWhitespace (PeekChar ()))
                                ReadChar ();
                        return skipped;
                }
 
-               private bool ReadWhitespace ()
+               private void ReadWhitespace ()
                {
                        if (currentState == XmlNodeType.None)
                                currentState = XmlNodeType.XmlDeclaration;
@@ -2855,7 +2883,7 @@ namespace System.Xml
                        int ch = PeekChar ();
                        do {
                                AppendValueChar (ReadChar ());
-                       } while ((ch = PeekChar ()) != -1 && XmlConstructs.IsSpace (ch));
+                       } while ((ch = PeekChar ()) != -1 && XmlChar.IsWhitespace (ch));
 
                        if (currentState == XmlNodeType.Element && ch != -1 && ch != '<')
                                ReadText (false);
@@ -2866,7 +2894,7 @@ namespace System.Xml
                                               valueBuffer,
                                               true);
 
-                       return (PeekChar () != -1);
+                       return; // (PeekChar () != -1);
                }
 
                // read entity reference from attribute string and if parsable then return the value.
index 7ff64a378749d782437adbc47e802249c00c431e..b790c147c8f69cd3132967a677fcdc0676dcdf5a 100644 (file)
@@ -59,7 +59,7 @@ namespace System.Xml {
 
                public override string BaseURI {
                        [MonoTODO]
-                       get { return validatingReader == null ? String.Empty : validatingReader.BaseURI; }
+                       get { return validatingReader == null ? sourceReader.BaseURI : validatingReader.BaseURI; }
                }
 
                public override bool CanResolveEntity {
@@ -76,7 +76,6 @@ namespace System.Xml {
                        get { throw new NotImplementedException (); }
                }
 
-               [MonoTODO]
                public EntityHandling EntityHandling {
                        get { return entityHandling; }
                        set { entityHandling = value; }
@@ -239,7 +238,15 @@ namespace System.Xml {
 
                public XmlResolver XmlResolver {
                        [MonoTODO]
-                       set { resolver = value; }
+                       set {
+                               resolver = value;
+                               DTDValidatingReader dvr = validatingReader as DTDValidatingReader;
+                               if (dvr != null)
+                                       dvr.XmlResolver = value;
+//                             XmlSchemaValidatingReader xsvr = validatingReader as XmlSchemaValidatingReader;
+//                             if (xsvr != null)
+//                                     xsvr.XmlResolver = value;
+                       }
                }
 
                public override XmlSpace XmlSpace {